feat: project local tidy recovery evidence
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
package com.ruoyi.algorithm.wms;
|
||||
|
||||
import com.ruoyi.algorithm.wms.tidy.TidyModeSnapshot;
|
||||
import com.ruoyi.algorithm.wms.tidy.TidyLaneClaim;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
import com.ruoyi.algorithm.wms.tidy.TidyWorkflowState;
|
||||
import com.ruoyi.algorithm.wms.tidy.TidyRecoveryEvidence;
|
||||
|
||||
@Mapper
|
||||
public interface WmsAlgorithmMapper {
|
||||
TidyLaneClaim claimTidyLane(@Param("warehouseId") String warehouseId,
|
||||
@Param("claimedBy") String claimedBy, @Param("leaseSeconds") int leaseSeconds);
|
||||
|
||||
TidyLaneClaim claimTidyLaneFromCandidates(@Param("warehouseId") String warehouseId,
|
||||
@Param("eligibleLaneCodes") String eligibleLaneCodes,
|
||||
@Param("claimedBy") String claimedBy, @Param("leaseSeconds") int leaseSeconds);
|
||||
|
||||
int releaseTidyLane(@Param("warehouseId") String warehouseId, @Param("laneCode") String laneCode,
|
||||
@Param("claimToken") java.util.UUID claimToken, @Param("claimedVersion") long claimedVersion,
|
||||
@Param("completed") boolean completed, @Param("lastError") String lastError);
|
||||
|
||||
int countActiveAutomaticTidy();
|
||||
|
||||
String selectLaneCodeForSpace(@Param("warehouseId") String warehouseId,
|
||||
@Param("spaceId") String spaceId);
|
||||
|
||||
String selectDatabaseName();
|
||||
|
||||
int insertTidyWorkflow(@Param("workflowId") String workflowId, @Param("warehouseId") String warehouseId,
|
||||
@Param("laneCode") String laneCode, @Param("origin") String origin,
|
||||
@Param("candidateType") String candidateType, @Param("sourceSpaceId") String sourceSpaceId,
|
||||
@Param("targetSpaceId") String targetSpaceId, @Param("trayCode") String trayCode,
|
||||
@Param("status") String status, @Param("dirtyVersion") long dirtyVersion,
|
||||
@Param("claimToken") String claimToken);
|
||||
|
||||
int insertTidyStep(@Param("stepId") String stepId, @Param("workflowId") String workflowId,
|
||||
@Param("stepNo") int stepNo, @Param("sourceSpaceId") String sourceSpaceId,
|
||||
@Param("targetSpaceId") String targetSpaceId, @Param("trayCode") String trayCode,
|
||||
@Param("status") String status, @Param("dependsOnStepId") String dependsOnStepId);
|
||||
|
||||
int lockTidyResource(@Param("lockId") java.util.UUID lockId, @Param("workflowId") String workflowId,
|
||||
@Param("warehouseId") String warehouseId, @Param("resourceType") String resourceType,
|
||||
@Param("resourceId") String resourceId);
|
||||
|
||||
int insertTidyMoveJob(@Param("workflowId") String workflowId, @Param("stepId") String stepId);
|
||||
String selectTidyWorkflowIdByJob(@Param("jobId") String jobId);
|
||||
String selectTidyStepIdByJob(@Param("jobId") String jobId);
|
||||
int insertTidyCallbackEventIfAbsent(@Param("eventId") java.util.UUID eventId,
|
||||
@Param("workflowId") String workflowId, @Param("stepId") String stepId,
|
||||
@Param("wcsTaskId") String wcsTaskId, @Param("eventStage") String eventStage,
|
||||
@Param("resultCode") String resultCode);
|
||||
int completeTidyStep(@Param("stepId") String stepId);
|
||||
String selectNextTidyStepId(@Param("workflowId") String workflowId);
|
||||
int completeTidyWorkflow(@Param("workflowId") String workflowId);
|
||||
int releaseTidyResources(@Param("workflowId") String workflowId);
|
||||
int pauseTidyWorkflow(@Param("workflowId") String workflowId, @Param("statusReason") String statusReason);
|
||||
int pauseTidyStep(@Param("workflowId") String workflowId, @Param("stepNo") int stepNo,
|
||||
@Param("statusReason") String statusReason);
|
||||
List<TidyWorkflowState> selectActiveTidyWorkflows(@Param("warehouseId") String warehouseId);
|
||||
List<TidyRecoveryEvidence> selectTidyRecoveryEvidence(@Param("warehouseId") String warehouseId);
|
||||
TidyModeSnapshot selectTidyMode(@Param("warehouseId") String warehouseId);
|
||||
|
||||
TidyModeSnapshot selectTidyModeForUpdate(@Param("warehouseId") String warehouseId);
|
||||
|
||||
int setTidyModeRequest(@Param("warehouseId") String warehouseId,
|
||||
@Param("requestedEnabled") boolean requestedEnabled,
|
||||
@Param("effectiveState") String effectiveState,
|
||||
@Param("statusReason") String statusReason,
|
||||
@Param("updatedBy") String updatedBy,
|
||||
@Param("expectedVersion") long expectedVersion);
|
||||
|
||||
int countActiveBusinessExecution(@Param("warehouseId") String warehouseId);
|
||||
|
||||
int countActiveManualTidy(@Param("warehouseId") String warehouseId);
|
||||
|
||||
List<String> selectActiveManualTidyVehicleIds(@Param("warehouseId") String warehouseId);
|
||||
|
||||
int assignTidyWorkflowVehicle(@Param("workflowId") String workflowId,
|
||||
@Param("vehicleId") String vehicleId);
|
||||
|
||||
List<InboundTaskItem> selectInboundTaskItems(@Param("jobId") String jobId);
|
||||
|
||||
int claimInboundSpace(@Param("reservationId") String reservationId,
|
||||
@Param("warehouseId") String warehouseId,
|
||||
@Param("laneCode") String laneCode,
|
||||
@Param("spaceId") String spaceId,
|
||||
@Param("trayCode") String trayCode);
|
||||
|
||||
int assignInboundJob(@Param("jobId") String jobId, @Param("spaceId") String spaceId);
|
||||
|
||||
int releaseInboundSpace(@Param("jobId") String jobId,
|
||||
@Param("warehouseId") String warehouseId,
|
||||
@Param("spaceId") String spaceId,
|
||||
@Param("trayCode") String trayCode);
|
||||
|
||||
int clearInboundJobAssignment(@Param("jobId") String jobId,
|
||||
@Param("spaceId") String spaceId);
|
||||
|
||||
OutboundStockReference selectOutboundStockReference(@Param("stockId") String stockId);
|
||||
|
||||
List<OutboundStockReference> selectOutboundStockReferences(@Param("warehouseId") String warehouseId,
|
||||
@Param("spaceId") String spaceId,
|
||||
@Param("trayCode") String trayCode,
|
||||
@Param("projectNo") String projectNo);
|
||||
|
||||
List<OutboundStockReference> selectOutboundStocksAtSpace(@Param("warehouseId") String warehouseId,
|
||||
@Param("spaceId") String spaceId);
|
||||
|
||||
OutboundStockReference selectOutboundShallowCommitStockForUpdate(
|
||||
@Param("stockId") String stockId,
|
||||
@Param("warehouseId") String warehouseId,
|
||||
@Param("spaceId") String spaceId,
|
||||
@Param("trayCode") String trayCode,
|
||||
@Param("projectNo") String projectNo);
|
||||
|
||||
OutboundStockReference selectOutboundWorkflowStartStockForUpdate(@Param("stockId") String stockId);
|
||||
|
||||
int countActiveOutboundWorkflow(@Param("requestId") String requestId,
|
||||
@Param("warehouseId") String warehouseId,
|
||||
@Param("floorNo") int floorNo);
|
||||
|
||||
int insertOutboundWorkflow(OutboundWorkflowHeaderState workflow);
|
||||
|
||||
int insertOutboundWorkflowStep(OutboundWorkflowStepState step);
|
||||
|
||||
int lockOutboundWorkflowSpace(OutboundWorkflowSpaceLock lock);
|
||||
|
||||
OutboundWorkflowStepState selectNextPendingWorkflowStep(@Param("workflowId") String workflowId);
|
||||
|
||||
int insertOutboundWorkflowMoveJob(OutboundWorkflowStepState step);
|
||||
|
||||
int markOutboundWorkflowStepRunning(@Param("assignmentId") String assignmentId,
|
||||
@Param("jobId") String jobId);
|
||||
|
||||
OutboundWorkflowStepState selectOutboundWorkflowStepByJobId(@Param("jobId") String jobId);
|
||||
|
||||
OutboundWorkflowStepState selectOutboundWorkflowStepForTray(@Param("trayCode") String trayCode);
|
||||
|
||||
int countStockAtSpaceByTray(@Param("spaceId") String spaceId,
|
||||
@Param("trayCode") String trayCode);
|
||||
|
||||
int markOutboundWorkflowStepCompleted(@Param("assignmentId") String assignmentId);
|
||||
|
||||
int markOutboundWorkflowStepAtExit(@Param("assignmentId") String assignmentId);
|
||||
|
||||
int unlockOutboundWorkflowSpace(@Param("workflowId") String workflowId,
|
||||
@Param("warehouseId") String warehouseId,
|
||||
@Param("spaceId") String spaceId);
|
||||
|
||||
int relockOutboundWorkflowSpace(@Param("workflowId") String workflowId,
|
||||
@Param("warehouseId") String warehouseId,
|
||||
@Param("spaceId") String spaceId);
|
||||
|
||||
String selectActiveOutboundJobId(@Param("stockId") String stockId,
|
||||
@Param("stockoutDetailId") String stockoutDetailId);
|
||||
|
||||
int completeOutboundWorkflow(@Param("workflowId") String workflowId);
|
||||
|
||||
int unlockOutboundWorkflowSpaces(@Param("workflowId") String workflowId);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.ruoyi.algorithm.wms.tidy;
|
||||
|
||||
public record TidyRecoveryEvidence(
|
||||
String workflowId, TidyOrigin origin, String workflowStatus, int activeLockCount,
|
||||
String stepId, Integer stepNo, String stepStatus, String sourceSpaceId, String targetSpaceId,
|
||||
String trayCode, int activeTidyJobCount, String activeJobId, String activeJobStatus,
|
||||
String activeJobInOrOut, String activeJobTrayCode, String activeJobSourceSpaceId,
|
||||
String activeJobTargetSpaceId, String finishedJobId, String finishedJobStatus,
|
||||
String finishedJobInOrOut, String finishedJobTrayCode, String finishedJobSourceSpaceId,
|
||||
String finishedJobTargetSpaceId, int sourceStockRows, int targetStockRows,
|
||||
String sourceSpaceStatus, String sourceSpaceTrayCode, String targetSpaceStatus,
|
||||
String targetSpaceTrayCode) { }
|
||||
@@ -0,0 +1,838 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.algorithm.wms.WmsAlgorithmMapper">
|
||||
|
||||
<select id="claimTidyLane" resultType="com.ruoyi.algorithm.wms.tidy.TidyLaneClaim">
|
||||
exec alg.usp_claim_tidy_lane
|
||||
@warehouse_id = #{warehouseId},
|
||||
@claimed_by = #{claimedBy},
|
||||
@lease_seconds = #{leaseSeconds}
|
||||
</select>
|
||||
|
||||
<select id="claimTidyLaneFromCandidates" resultType="com.ruoyi.algorithm.wms.tidy.TidyLaneClaim">
|
||||
exec alg.usp_claim_tidy_lane
|
||||
@warehouse_id = #{warehouseId},
|
||||
@eligible_lane_codes = #{eligibleLaneCodes},
|
||||
@claimed_by = #{claimedBy},
|
||||
@lease_seconds = #{leaseSeconds}
|
||||
</select>
|
||||
|
||||
<select id="releaseTidyLane" resultType="int">
|
||||
exec alg.usp_release_tidy_lane
|
||||
@warehouse_id = #{warehouseId},
|
||||
@lane_code = #{laneCode},
|
||||
@claim_token = #{claimToken},
|
||||
@claimed_version = #{claimedVersion},
|
||||
@completed = #{completed},
|
||||
@last_error = #{lastError}
|
||||
</select>
|
||||
|
||||
<select id="countActiveAutomaticTidy" resultType="int">
|
||||
select count(*) from alg.tidy_workflow
|
||||
where origin = 'AUTO_TIDY'
|
||||
and status in ('CLAIMED', 'WAITING_DISPATCH', 'DISPATCHED', 'RUNNING', 'PAUSED_RECOVERY')
|
||||
</select>
|
||||
|
||||
<select id="selectLaneCodeForSpace" resultType="string">
|
||||
select lane_code from alg.space_topology
|
||||
where warehouse_id = #{warehouseId} and space_id = #{spaceId}
|
||||
</select>
|
||||
|
||||
<select id="selectDatabaseName" resultType="string">select DB_NAME()</select>
|
||||
|
||||
<insert id="insertTidyWorkflow">
|
||||
insert into alg.tidy_workflow (
|
||||
workflow_id, warehouse_id, lane_code, origin, candidate_type,
|
||||
source_space_id, target_space_id, stock_id, tray_code, status,
|
||||
claimed_dirty_version, lane_claim_token, mode_version)
|
||||
values (#{workflowId}, #{warehouseId}, #{laneCode}, #{origin}, #{candidateType},
|
||||
#{sourceSpaceId}, #{targetSpaceId}, #{workflowId}, #{trayCode}, #{status},
|
||||
#{dirtyVersion}, try_convert(uniqueidentifier, #{claimToken}), 0)
|
||||
</insert>
|
||||
|
||||
<insert id="insertTidyStep">
|
||||
insert into alg.tidy_step (
|
||||
step_id, workflow_id, step_no, source_space_id, target_space_id,
|
||||
stock_id, tray_code, status, expected_event_stage)
|
||||
values (#{stepId}, #{workflowId}, #{stepNo}, #{sourceSpaceId}, #{targetSpaceId},
|
||||
#{stepId}, #{trayCode}, #{status}, 'FINISHED')
|
||||
</insert>
|
||||
|
||||
<insert id="lockTidyResource">
|
||||
insert into alg.tidy_space_lock (
|
||||
lock_id, workflow_id, warehouse_id, resource_type, resource_id, status)
|
||||
values (#{lockId}, #{workflowId}, #{warehouseId}, #{resourceType}, #{resourceId}, 'ACTIVE')
|
||||
</insert>
|
||||
|
||||
<insert id="insertTidyMoveJob">
|
||||
insert into mydo_job (
|
||||
job_id, status, on_line_type, task_no, tray_code, cargo_space_id,
|
||||
target_cargo_space_id, priority, execution_phase, in_or_out,
|
||||
create_time, warehouse_id)
|
||||
select concat('TDY-', #{workflowId}, '-', #{stepId}), '1', '1',
|
||||
concat('TDY-', #{workflowId}, '-', #{stepId}), step.tray_code,
|
||||
step.source_space_id, step.target_space_id, 10, '0', '28',
|
||||
convert(varchar(19), getdate(), 120), workflow.warehouse_id
|
||||
from alg.tidy_step step
|
||||
join alg.tidy_workflow workflow on workflow.workflow_id = step.workflow_id
|
||||
where step.workflow_id = #{workflowId}
|
||||
and step.step_id = #{stepId}
|
||||
and step.status = 'PENDING'
|
||||
and not exists (
|
||||
select 1 from mydo_job job where job.job_id = concat('TDY-', #{workflowId}, '-', #{stepId})
|
||||
)
|
||||
</insert>
|
||||
|
||||
<select id="selectTidyWorkflowIdByJob" resultType="string">
|
||||
select top (1) workflow_id from alg.tidy_step
|
||||
where wms_job_id = #{jobId}
|
||||
or #{jobId} = concat('TDY-', workflow_id, '-', step_id)
|
||||
</select>
|
||||
|
||||
<select id="selectTidyStepIdByJob" resultType="string">
|
||||
select top (1) step_id from alg.tidy_step
|
||||
where wms_job_id = #{jobId}
|
||||
or #{jobId} = concat('TDY-', workflow_id, '-', step_id)
|
||||
</select>
|
||||
|
||||
<insert id="insertTidyCallbackEventIfAbsent">
|
||||
if not exists (
|
||||
select 1 from alg.tidy_callback_event with (updlock, holdlock)
|
||||
where workflow_id = #{workflowId} and step_id = #{stepId}
|
||||
and wcs_task_id = #{wcsTaskId} and event_stage = #{eventStage})
|
||||
begin
|
||||
insert into alg.tidy_callback_event (
|
||||
callback_event_id, workflow_id, step_id, wcs_task_id, event_stage, result_code)
|
||||
values (#{eventId}, #{workflowId}, #{stepId}, #{wcsTaskId}, #{eventStage}, #{resultCode});
|
||||
select 1;
|
||||
end
|
||||
else select 0;
|
||||
</insert>
|
||||
|
||||
<update id="completeTidyStep">
|
||||
update alg.tidy_step
|
||||
set status = 'COMPLETED', completed_at = SYSUTCDATETIME()
|
||||
where step_id = #{stepId} and status in ('PENDING', 'DISPATCHED', 'RUNNING')
|
||||
</update>
|
||||
|
||||
<select id="selectNextTidyStepId" resultType="string">
|
||||
select top (1) nextStep.step_id
|
||||
from alg.tidy_step nextStep
|
||||
where nextStep.workflow_id = #{workflowId}
|
||||
and nextStep.status = 'PENDING'
|
||||
and not exists (
|
||||
select 1 from alg.tidy_step dependency
|
||||
where dependency.workflow_id = nextStep.workflow_id
|
||||
and dependency.step_no < nextStep.step_no
|
||||
and dependency.status <> 'COMPLETED')
|
||||
order by nextStep.step_no
|
||||
</select>
|
||||
|
||||
<update id="completeTidyWorkflow">
|
||||
update alg.tidy_workflow
|
||||
set status = 'COMPLETED', completed_at = SYSUTCDATETIME(), updated_at = SYSUTCDATETIME()
|
||||
where workflow_id = #{workflowId}
|
||||
and not exists (select 1 from alg.tidy_step where workflow_id = #{workflowId} and status <> 'COMPLETED')
|
||||
</update>
|
||||
|
||||
<update id="releaseTidyResources">
|
||||
update alg.tidy_space_lock
|
||||
set status = 'RELEASED', released_at = SYSUTCDATETIME()
|
||||
where workflow_id = #{workflowId} and status = 'ACTIVE'
|
||||
</update>
|
||||
|
||||
<update id="pauseTidyWorkflow">
|
||||
update alg.tidy_workflow
|
||||
set status = 'PAUSED_RECOVERY', status_reason = #{statusReason}, updated_at = SYSUTCDATETIME()
|
||||
where workflow_id = #{workflowId} and status not in ('COMPLETED', 'CANCELLED_RECONCILED')
|
||||
</update>
|
||||
|
||||
<update id="pauseTidyStep">
|
||||
update alg.tidy_step
|
||||
set status = 'PAUSED_RECOVERY'
|
||||
where workflow_id = #{workflowId}
|
||||
and step_no = #{stepNo}
|
||||
and status in ('PENDING', 'DISPATCHED', 'RUNNING')
|
||||
</update>
|
||||
|
||||
<resultMap id="tidyWorkflowStateMap" type="com.ruoyi.algorithm.wms.tidy.TidyWorkflowState">
|
||||
<constructor>
|
||||
<arg column="workflowId" javaType="java.lang.String" />
|
||||
<arg column="origin" javaType="com.ruoyi.algorithm.wms.tidy.TidyOrigin" />
|
||||
<arg column="status" javaType="java.lang.String" />
|
||||
<arg column="laneCode" javaType="java.lang.String" />
|
||||
<arg column="sourceSpaceId" javaType="java.lang.String" />
|
||||
<arg column="targetSpaceId" javaType="java.lang.String" />
|
||||
<arg column="trayCode" javaType="java.lang.String" />
|
||||
<arg column="wcsTaskId" javaType="java.lang.String" />
|
||||
<arg column="activeStep" javaType="_int" />
|
||||
</constructor>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectActiveTidyWorkflows" resultMap="tidyWorkflowStateMap">
|
||||
select workflow.workflow_id as workflowId,
|
||||
workflow.origin as origin,
|
||||
workflow.status as status,
|
||||
workflow.lane_code as laneCode,
|
||||
workflow.source_space_id as sourceSpaceId,
|
||||
workflow.target_space_id as targetSpaceId,
|
||||
workflow.tray_code as trayCode,
|
||||
coalesce(workflow.wcs_task_id, job.task_no) as wcsTaskId,
|
||||
active_step.step_no as activeStep
|
||||
from alg.tidy_workflow workflow
|
||||
cross apply (
|
||||
select top (1) step.step_no, step.step_id
|
||||
from alg.tidy_step step
|
||||
where step.workflow_id = workflow.workflow_id
|
||||
and step.status in ('PENDING', 'DISPATCHED', 'RUNNING', 'PAUSED_RECOVERY')
|
||||
order by step.step_no
|
||||
) active_step
|
||||
left join dbo.mydo_job job
|
||||
on job.job_id = concat('TDY-', workflow.workflow_id, '-', active_step.step_id)
|
||||
where workflow.warehouse_id = #{warehouseId}
|
||||
and workflow.status in (
|
||||
'CLAIMED', 'WAITING_DISPATCH', 'DISPATCHED', 'RUNNING', 'PAUSED_RECOVERY'
|
||||
)
|
||||
</select>
|
||||
|
||||
<sql id="tidyModeProjection">
|
||||
mode.warehouse_id as warehouseId,
|
||||
mode.requested_enabled as requestedEnabled,
|
||||
mode.effective_state as effectiveState,
|
||||
(select count(*)
|
||||
from mydo_job job
|
||||
where job.warehouse_id = mode.warehouse_id
|
||||
and job.status in ('1', '2', '3')
|
||||
and try_convert(int, job.in_or_out) is not null
|
||||
and not exists (
|
||||
select 1 from alg.tidy_step tidyStep where tidyStep.wms_job_id = job.job_id
|
||||
)) as drainCount,
|
||||
(select count(*)
|
||||
from alg.tidy_workflow tidyWorkflow
|
||||
where tidyWorkflow.warehouse_id = mode.warehouse_id
|
||||
and tidyWorkflow.origin = 'MANUAL_TIDY'
|
||||
and tidyWorkflow.status in (
|
||||
'CLAIMED', 'WAITING_DISPATCH', 'DISPATCHED', 'RUNNING', 'PAUSED_RECOVERY'
|
||||
)) as activeTidyCount,
|
||||
mode.status_reason as statusReason,
|
||||
mode.mode_version as version,
|
||||
mode.updated_by as updatedBy,
|
||||
mode.updated_at as updatedAt
|
||||
</sql>
|
||||
|
||||
<select id="selectTidyMode" resultType="com.ruoyi.algorithm.wms.tidy.TidyModeSnapshot">
|
||||
select <include refid="tidyModeProjection" />
|
||||
from alg.tidy_mode mode
|
||||
where mode.warehouse_id = #{warehouseId}
|
||||
</select>
|
||||
|
||||
<select id="selectTidyModeForUpdate" resultType="com.ruoyi.algorithm.wms.tidy.TidyModeSnapshot">
|
||||
select
|
||||
mode.warehouse_id as warehouseId,
|
||||
mode.requested_enabled as requestedEnabled,
|
||||
mode.effective_state as effectiveState,
|
||||
0 as drainCount,
|
||||
0 as activeTidyCount,
|
||||
mode.status_reason as statusReason,
|
||||
mode.mode_version as version,
|
||||
mode.updated_by as updatedBy,
|
||||
mode.updated_at as updatedAt
|
||||
from alg.tidy_mode mode with (updlock, holdlock)
|
||||
where mode.warehouse_id = #{warehouseId}
|
||||
</select>
|
||||
|
||||
<update id="setTidyModeRequest">
|
||||
update alg.tidy_mode with (updlock, rowlock)
|
||||
set requested_enabled = #{requestedEnabled},
|
||||
effective_state = #{effectiveState},
|
||||
status_reason = #{statusReason},
|
||||
mode_version = mode_version + 1,
|
||||
updated_by = #{updatedBy},
|
||||
updated_at = SYSUTCDATETIME()
|
||||
where warehouse_id = #{warehouseId}
|
||||
and mode_version = #{expectedVersion}
|
||||
</update>
|
||||
|
||||
<select id="countActiveBusinessExecution" resultType="int">
|
||||
select count(*)
|
||||
from mydo_job job
|
||||
where job.warehouse_id = #{warehouseId}
|
||||
and (
|
||||
job.status in ('2', '3')
|
||||
or (
|
||||
job.status = '1'
|
||||
and nullif(ltrim(rtrim(job.cargo_space_id)), '') is not null
|
||||
)
|
||||
)
|
||||
and try_convert(int, job.in_or_out) is not null
|
||||
and not exists (
|
||||
select 1 from alg.tidy_step tidyStep
|
||||
where tidyStep.wms_job_id = job.job_id
|
||||
)
|
||||
</select>
|
||||
|
||||
<select id="countActiveManualTidy" resultType="int">
|
||||
select count(*)
|
||||
from alg.tidy_workflow workflow
|
||||
where workflow.warehouse_id = #{warehouseId}
|
||||
and workflow.origin = 'MANUAL_TIDY'
|
||||
and workflow.status in (
|
||||
'CLAIMED', 'WAITING_DISPATCH', 'DISPATCHED', 'RUNNING', 'PAUSED_RECOVERY'
|
||||
)
|
||||
</select>
|
||||
|
||||
<select id="selectActiveManualTidyVehicleIds" resultType="string">
|
||||
select vehicle_id
|
||||
from alg.tidy_workflow
|
||||
where warehouse_id = #{warehouseId}
|
||||
and origin = 'MANUAL_TIDY'
|
||||
and vehicle_id is not null
|
||||
and status in ('CLAIMED', 'WAITING_DISPATCH', 'DISPATCHED', 'RUNNING', 'PAUSED_RECOVERY')
|
||||
</select>
|
||||
|
||||
<update id="assignTidyWorkflowVehicle">
|
||||
update alg.tidy_workflow
|
||||
set vehicle_id = #{vehicleId}, updated_at = SYSUTCDATETIME()
|
||||
where workflow_id = #{workflowId} and vehicle_id is null
|
||||
</update>
|
||||
|
||||
<select id="selectInboundTaskItems" resultType="com.ruoyi.algorithm.wms.InboundTaskItem">
|
||||
select coalesce(nullif(ltrim(rtrim(isd.spare4)), ''),
|
||||
nullif(ltrim(rtrim(bs.spare4)), '')) as projectNo,
|
||||
mjd.product_id as productId,
|
||||
mjd.lot_no as lotNo
|
||||
from mydo_job_detail mjd
|
||||
left join in_stockin_detail isd on isd.stockin_detail_id = mjd.stockin_detail_id
|
||||
left join bas_stock bs on bs.stock_id = mjd.stock_id
|
||||
where mjd.job_id = #{jobId}
|
||||
order by mjd.job_detail_id
|
||||
</select>
|
||||
|
||||
<update id="claimInboundSpace">
|
||||
update target with (updlock, rowlock)
|
||||
set target.status = '3',
|
||||
target.tray_code = #{trayCode}
|
||||
from bas_cargo_space target
|
||||
where target.cargo_space_id = #{spaceId}
|
||||
and target.warehouse_id = #{warehouseId}
|
||||
and target.group_coding_no = #{laneCode}
|
||||
and target.status = '1'
|
||||
and (target.locked is null or ltrim(rtrim(target.locked)) in ('', '0', 'N'))
|
||||
and nullif(ltrim(rtrim(target.tray_code)), '') is null
|
||||
and not exists (
|
||||
select 1 from bas_stock stock with (updlock, holdlock)
|
||||
where stock.cargo_space_id = target.cargo_space_id
|
||||
)
|
||||
and exists (
|
||||
select 1 from alg.reservation reservation with (updlock, holdlock)
|
||||
where reservation.reservation_id = #{reservationId}
|
||||
and reservation.warehouse_id = #{warehouseId}
|
||||
and reservation.lane_code = #{laneCode}
|
||||
and reservation.space_id = #{spaceId}
|
||||
and reservation.status = 'ACTIVE'
|
||||
)
|
||||
</update>
|
||||
|
||||
<update id="assignInboundJob">
|
||||
update job
|
||||
set job.cargo_space_id = #{spaceId},
|
||||
job.roadway_id = target.roadway_id
|
||||
from mydo_job job
|
||||
inner join bas_cargo_space target on target.cargo_space_id = #{spaceId}
|
||||
where job.job_id = #{jobId}
|
||||
and (job.cargo_space_id is null or ltrim(rtrim(job.cargo_space_id)) = ''
|
||||
or job.cargo_space_id = #{spaceId})
|
||||
and target.status = '3'
|
||||
</update>
|
||||
|
||||
<update id="releaseInboundSpace">
|
||||
update target with (updlock, rowlock)
|
||||
set target.status = '1',
|
||||
target.tray_code = null
|
||||
from bas_cargo_space target
|
||||
where target.cargo_space_id = #{spaceId}
|
||||
and target.warehouse_id = #{warehouseId}
|
||||
and target.status = '3'
|
||||
and target.tray_code = #{trayCode}
|
||||
and not exists (
|
||||
select 1 from bas_stock stock with (updlock, holdlock)
|
||||
where stock.cargo_space_id = target.cargo_space_id
|
||||
)
|
||||
and exists (
|
||||
select 1 from mydo_job job with (updlock, holdlock)
|
||||
where job.job_id = #{jobId}
|
||||
and job.cargo_space_id = target.cargo_space_id
|
||||
)
|
||||
</update>
|
||||
|
||||
<update id="clearInboundJobAssignment">
|
||||
update mydo_job
|
||||
set cargo_space_id = null,
|
||||
roadway_id = null,
|
||||
fault_flag = '1'
|
||||
where job_id = #{jobId}
|
||||
and cargo_space_id = #{spaceId}
|
||||
</update>
|
||||
|
||||
<select id="selectOutboundStockReference" resultType="com.ruoyi.algorithm.wms.OutboundStockReference">
|
||||
select stock.stock_id as stockId,
|
||||
stock.tray_code as trayCode,
|
||||
stock.cargo_space_id as spaceId,
|
||||
stock.warehouse_id as warehouseId,
|
||||
stock.spare4 as projectNo,
|
||||
stock.product_id as productId
|
||||
from bas_stock stock
|
||||
where stock.stock_id = #{stockId}
|
||||
and stock.stock_status = '1'
|
||||
and stock.product_status = '1'
|
||||
and stock.quantity > stock.out_quantity
|
||||
</select>
|
||||
|
||||
<select id="selectOutboundStockReferences" resultType="com.ruoyi.algorithm.wms.OutboundStockReference">
|
||||
select stock.stock_id as stockId,
|
||||
stock.tray_code as trayCode,
|
||||
stock.cargo_space_id as spaceId,
|
||||
stock.warehouse_id as warehouseId,
|
||||
stock.spare4 as projectNo,
|
||||
stock.product_id as productId
|
||||
from bas_stock stock with (updlock, rowlock)
|
||||
inner join bas_cargo_space space on space.cargo_space_id = stock.cargo_space_id
|
||||
where stock.warehouse_id = #{warehouseId}
|
||||
and stock.cargo_space_id = #{spaceId}
|
||||
and stock.tray_code = #{trayCode}
|
||||
and stock.spare4 = #{projectNo}
|
||||
and stock.stock_status = '1'
|
||||
and stock.product_status = '1'
|
||||
and stock.quantity > stock.out_quantity
|
||||
and space.locked = 'N'
|
||||
order by stock.stock_id
|
||||
</select>
|
||||
|
||||
<select id="selectOutboundStocksAtSpace" resultType="com.ruoyi.algorithm.wms.OutboundStockReference">
|
||||
select stock.stock_id as stockId,
|
||||
stock.tray_code as trayCode,
|
||||
stock.cargo_space_id as spaceId,
|
||||
stock.warehouse_id as warehouseId,
|
||||
stock.spare4 as projectNo,
|
||||
stock.product_id as productId
|
||||
from bas_stock stock with (updlock, holdlock)
|
||||
where stock.warehouse_id = #{warehouseId}
|
||||
and stock.cargo_space_id = #{spaceId}
|
||||
and stock.stock_status = '1'
|
||||
and stock.product_status = '1'
|
||||
and stock.quantity > stock.out_quantity
|
||||
order by stock.stock_id
|
||||
</select>
|
||||
|
||||
<select id="selectOutboundShallowCommitStockForUpdate"
|
||||
resultType="com.ruoyi.algorithm.wms.OutboundStockReference"><![CDATA[
|
||||
select stock.stock_id as stockId,
|
||||
stock.tray_code as trayCode,
|
||||
stock.cargo_space_id as spaceId,
|
||||
stock.warehouse_id as warehouseId,
|
||||
stock.spare4 as projectNo,
|
||||
stock.product_id as productId
|
||||
from bas_stock stock with (updlock, holdlock)
|
||||
inner join bas_cargo_space source with (updlock, holdlock)
|
||||
on source.cargo_space_id = stock.cargo_space_id
|
||||
and source.warehouse_id = stock.warehouse_id
|
||||
where stock.stock_id = #{stockId}
|
||||
and stock.warehouse_id = #{warehouseId}
|
||||
and stock.cargo_space_id = #{spaceId}
|
||||
and stock.tray_code = #{trayCode}
|
||||
and (stock.spare4 = #{projectNo}
|
||||
or (#{projectNo} is null and nullif(ltrim(rtrim(stock.spare4)), '') is null))
|
||||
and stock.stock_status = '1'
|
||||
and stock.product_status = '1'
|
||||
and stock.quantity > stock.out_quantity
|
||||
and source.status = '2'
|
||||
and source.tray_code = #{trayCode}
|
||||
and (source.locked is null or ltrim(rtrim(source.locked)) in ('', '0', 'N'))
|
||||
and nullif(ltrim(rtrim(source.group_coding_no)), '') is not null
|
||||
and try_convert(int, source.group_coding) is not null
|
||||
and not exists (
|
||||
select 1
|
||||
from bas_cargo_space outer_space with (updlock, holdlock)
|
||||
where outer_space.warehouse_id = source.warehouse_id
|
||||
and outer_space.group_coding_no = source.group_coding_no
|
||||
and try_convert(int, outer_space.group_coding)
|
||||
> try_convert(int, source.group_coding)
|
||||
and (
|
||||
isnull(outer_space.status, '') <> '1'
|
||||
or nullif(ltrim(rtrim(outer_space.tray_code)), '') is not null
|
||||
or (outer_space.locked is not null
|
||||
and ltrim(rtrim(outer_space.locked)) not in ('', '0', 'N'))
|
||||
or exists (
|
||||
select 1
|
||||
from bas_stock outer_stock with (updlock, holdlock)
|
||||
where outer_stock.cargo_space_id = outer_space.cargo_space_id
|
||||
)
|
||||
)
|
||||
)
|
||||
]]></select>
|
||||
|
||||
<select id="selectOutboundWorkflowStartStockForUpdate"
|
||||
resultType="com.ruoyi.algorithm.wms.OutboundStockReference">
|
||||
select stock.stock_id as stockId,
|
||||
stock.tray_code as trayCode,
|
||||
stock.cargo_space_id as spaceId,
|
||||
stock.warehouse_id as warehouseId,
|
||||
stock.spare4 as projectNo,
|
||||
stock.product_id as productId
|
||||
from bas_stock stock with (updlock, holdlock)
|
||||
inner join bas_cargo_space space with (updlock, holdlock)
|
||||
on space.cargo_space_id = stock.cargo_space_id
|
||||
and space.warehouse_id = stock.warehouse_id
|
||||
where stock.stock_id = #{stockId}
|
||||
and stock.stock_status = '1'
|
||||
and stock.product_status = '1'
|
||||
and stock.quantity > stock.out_quantity
|
||||
and space.status = '2'
|
||||
and (space.locked is null or ltrim(rtrim(space.locked)) in ('', '0', 'N'))
|
||||
</select>
|
||||
|
||||
<select id="countActiveOutboundWorkflow" resultType="int">
|
||||
select count(1)
|
||||
from alg.outbound_workflow workflow with (updlock, holdlock)
|
||||
where workflow.request_id = #{requestId}
|
||||
and workflow.warehouse_id = #{warehouseId}
|
||||
and workflow.floor_no = #{floorNo}
|
||||
and workflow.status = 'ACTIVE'
|
||||
</select>
|
||||
|
||||
<insert id="insertOutboundWorkflow">
|
||||
insert into alg.outbound_workflow (
|
||||
workflow_id, request_id, stockout_detail_id, warehouse_id,
|
||||
source_stock_id, selected_tray_code, source_space_id, lane_code,
|
||||
floor_no, exit_id, status, current_step, total_steps, created_at, updated_at)
|
||||
values (
|
||||
#{workflowId}, #{requestId}, #{stockoutDetailId}, #{warehouseId},
|
||||
#{sourceStockId}, #{selectedTrayCode}, #{sourceSpaceId}, #{laneCode},
|
||||
#{floorNo}, #{exitId}, #{status}, #{currentStep}, #{totalSteps},
|
||||
SYSUTCDATETIME(), SYSUTCDATETIME())
|
||||
</insert>
|
||||
|
||||
<insert id="insertOutboundWorkflowStep">
|
||||
insert into alg.outbound_workflow_step (
|
||||
assignment_id, workflow_id, phase, source_space_id, target_space_id,
|
||||
workflow_step, workflow_total_steps, depends_on_assignment_id,
|
||||
stock_id, tray_code, status, wms_job_id, created_at)
|
||||
values (
|
||||
#{assignmentId}, #{workflowId}, #{phase}, #{sourceSpaceId}, #{targetSpaceId},
|
||||
#{workflowStep}, #{workflowTotalSteps}, #{dependsOnAssignmentId},
|
||||
#{stockId}, #{trayCode}, #{status}, #{jobId}, SYSUTCDATETIME())
|
||||
</insert>
|
||||
|
||||
<insert id="lockOutboundWorkflowSpace">
|
||||
insert into alg.outbound_workflow_space (
|
||||
workflow_id, space_id, status, locked_at)
|
||||
select #{workflowId}, space.cargo_space_id, 'ACTIVE', SYSUTCDATETIME()
|
||||
from bas_cargo_space space with (updlock, holdlock)
|
||||
where space.cargo_space_id = #{spaceId}
|
||||
and space.warehouse_id = #{warehouseId}
|
||||
and (space.locked is null or ltrim(rtrim(space.locked)) in ('', '0', 'N'))
|
||||
and not exists (
|
||||
select 1
|
||||
from alg.outbound_workflow_space held with (updlock, holdlock)
|
||||
where held.space_id = space.cargo_space_id
|
||||
and held.status = 'ACTIVE'
|
||||
);
|
||||
update space
|
||||
set space.locked = 'Y'
|
||||
from bas_cargo_space space
|
||||
inner join alg.outbound_workflow_space held
|
||||
on held.space_id = space.cargo_space_id
|
||||
and held.workflow_id = #{workflowId}
|
||||
and held.status = 'ACTIVE'
|
||||
where space.cargo_space_id = #{spaceId}
|
||||
and space.warehouse_id = #{warehouseId};
|
||||
</insert>
|
||||
|
||||
<sql id="outboundWorkflowStepColumns">
|
||||
step.assignment_id as assignmentId,
|
||||
step.workflow_id as workflowId,
|
||||
workflow.stockout_detail_id as stockoutDetailId,
|
||||
workflow.warehouse_id as warehouseId,
|
||||
workflow.floor_no as floorNo,
|
||||
workflow.request_id as requestId,
|
||||
workflow.exit_id as exitId,
|
||||
step.phase as phase,
|
||||
step.source_space_id as sourceSpaceId,
|
||||
step.target_space_id as targetSpaceId,
|
||||
step.workflow_step as workflowStep,
|
||||
step.workflow_total_steps as workflowTotalSteps,
|
||||
step.depends_on_assignment_id as dependsOnAssignmentId,
|
||||
step.stock_id as stockId,
|
||||
step.tray_code as trayCode,
|
||||
step.status as status,
|
||||
step.wms_job_id as jobId
|
||||
</sql>
|
||||
|
||||
<select id="selectNextPendingWorkflowStep"
|
||||
resultType="com.ruoyi.algorithm.wms.OutboundWorkflowStepState">
|
||||
select top (1) <include refid="outboundWorkflowStepColumns"/>
|
||||
from alg.outbound_workflow_step step with (updlock, holdlock)
|
||||
inner join alg.outbound_workflow workflow with (updlock, holdlock)
|
||||
on workflow.workflow_id = step.workflow_id
|
||||
left join alg.outbound_workflow_step dependency with (updlock, holdlock)
|
||||
on dependency.assignment_id = step.depends_on_assignment_id
|
||||
where step.workflow_id = #{workflowId}
|
||||
and workflow.status = 'ACTIVE'
|
||||
and step.status = 'PENDING'
|
||||
and (step.depends_on_assignment_id is null or dependency.status = 'COMPLETED')
|
||||
order by step.workflow_step, step.assignment_id
|
||||
</select>
|
||||
|
||||
<insert id="insertOutboundWorkflowMoveJob">
|
||||
insert into mydo_job (
|
||||
job_id, status, on_line_type, task_no, tray_code,
|
||||
roadway_id, cargo_space_id, target_roadway_id, target_cargo_space_id,
|
||||
priority, execution_phase, in_or_out, create_time, exit_id, warehouse_id)
|
||||
select #{assignmentId}, '1', '1', #{assignmentId}, #{trayCode},
|
||||
source_space.roadway_id, #{sourceSpaceId},
|
||||
target_space.roadway_id, #{targetSpaceId},
|
||||
10, '0', '28', convert(varchar(19), getdate(), 120),
|
||||
#{exitId}, #{warehouseId}
|
||||
from bas_cargo_space source_space with (updlock, holdlock)
|
||||
inner join bas_cargo_space target_space with (updlock, holdlock)
|
||||
on target_space.cargo_space_id = #{targetSpaceId}
|
||||
and target_space.warehouse_id = #{warehouseId}
|
||||
inner join bas_stock source_stock with (updlock, holdlock)
|
||||
on source_stock.stock_id = #{stockId}
|
||||
and source_stock.tray_code = #{trayCode}
|
||||
and source_stock.cargo_space_id = source_space.cargo_space_id
|
||||
and source_stock.warehouse_id = #{warehouseId}
|
||||
inner join alg.outbound_workflow_space source_lock with (updlock, holdlock)
|
||||
on source_lock.workflow_id = #{workflowId}
|
||||
and source_lock.space_id = source_space.cargo_space_id
|
||||
and source_lock.status = 'ACTIVE'
|
||||
inner join alg.outbound_workflow_space target_lock with (updlock, holdlock)
|
||||
on target_lock.workflow_id = #{workflowId}
|
||||
and target_lock.space_id = target_space.cargo_space_id
|
||||
and target_lock.status = 'ACTIVE'
|
||||
where source_space.cargo_space_id = #{sourceSpaceId}
|
||||
and source_space.warehouse_id = #{warehouseId}
|
||||
and source_space.status = '2'
|
||||
and source_space.tray_code = #{trayCode}
|
||||
and source_space.locked = 'Y'
|
||||
and source_stock.stock_status = '1'
|
||||
and source_stock.product_status = '1'
|
||||
and source_stock.quantity > source_stock.out_quantity
|
||||
and target_space.status = '1'
|
||||
and nullif(ltrim(rtrim(target_space.tray_code)), '') is null
|
||||
and target_space.locked = 'Y'
|
||||
and #{phase} in ('MOVE_OUT', 'RESTORE')
|
||||
and not exists (
|
||||
select 1
|
||||
from bas_stock target_stock with (updlock, holdlock)
|
||||
where target_stock.cargo_space_id = target_space.cargo_space_id
|
||||
)
|
||||
and not exists (
|
||||
select 1 from mydo_job job with (updlock, holdlock)
|
||||
where job.job_id = #{assignmentId}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<update id="markOutboundWorkflowStepRunning">
|
||||
update step with (updlock, rowlock)
|
||||
set step.status = 'RUNNING',
|
||||
step.wms_job_id = #{jobId},
|
||||
step.started_at = SYSUTCDATETIME()
|
||||
from alg.outbound_workflow_step step
|
||||
left join alg.outbound_workflow_step dependency
|
||||
on dependency.assignment_id = step.depends_on_assignment_id
|
||||
where step.assignment_id = #{assignmentId}
|
||||
and step.status = 'PENDING'
|
||||
and (step.depends_on_assignment_id is null or dependency.status = 'COMPLETED');
|
||||
update workflow
|
||||
set workflow.current_step = step.workflow_step,
|
||||
workflow.updated_at = SYSUTCDATETIME()
|
||||
from alg.outbound_workflow workflow
|
||||
inner join alg.outbound_workflow_step step
|
||||
on step.workflow_id = workflow.workflow_id
|
||||
where step.assignment_id = #{assignmentId}
|
||||
and step.status = 'RUNNING'
|
||||
and step.wms_job_id = #{jobId};
|
||||
</update>
|
||||
|
||||
<select id="selectOutboundWorkflowStepByJobId"
|
||||
resultType="com.ruoyi.algorithm.wms.OutboundWorkflowStepState">
|
||||
select top (1) <include refid="outboundWorkflowStepColumns"/>
|
||||
from alg.outbound_workflow_step step with (updlock, holdlock)
|
||||
inner join alg.outbound_workflow workflow with (updlock, holdlock)
|
||||
on workflow.workflow_id = step.workflow_id
|
||||
where step.wms_job_id = #{jobId}
|
||||
and step.status = 'RUNNING'
|
||||
and workflow.status = 'ACTIVE'
|
||||
order by step.workflow_step
|
||||
</select>
|
||||
|
||||
<select id="selectOutboundWorkflowStepForTray"
|
||||
resultType="com.ruoyi.algorithm.wms.OutboundWorkflowStepState">
|
||||
select top (1) <include refid="outboundWorkflowStepColumns"/>
|
||||
from alg.outbound_workflow_step step with (updlock, holdlock)
|
||||
inner join alg.outbound_workflow workflow with (updlock, holdlock)
|
||||
on workflow.workflow_id = step.workflow_id
|
||||
where step.tray_code = #{trayCode}
|
||||
and step.phase = 'OUTBOUND'
|
||||
and step.status = 'AT_EXIT'
|
||||
and workflow.status = 'ACTIVE'
|
||||
order by step.workflow_step
|
||||
</select>
|
||||
|
||||
<select id="countStockAtSpaceByTray" resultType="int">
|
||||
select count(1)
|
||||
from bas_stock stock with (updlock, holdlock)
|
||||
where stock.cargo_space_id = #{spaceId}
|
||||
and stock.tray_code = #{trayCode}
|
||||
</select>
|
||||
|
||||
<update id="markOutboundWorkflowStepCompleted">
|
||||
update step with (updlock, rowlock)
|
||||
set step.status = 'COMPLETED',
|
||||
step.completed_at = SYSUTCDATETIME()
|
||||
from alg.outbound_workflow_step step
|
||||
where step.assignment_id = #{assignmentId}
|
||||
and step.status in ('RUNNING', 'AT_EXIT');
|
||||
update workflow
|
||||
set workflow.current_step = step.workflow_step,
|
||||
workflow.updated_at = SYSUTCDATETIME()
|
||||
from alg.outbound_workflow workflow
|
||||
inner join alg.outbound_workflow_step step
|
||||
on step.workflow_id = workflow.workflow_id
|
||||
where step.assignment_id = #{assignmentId}
|
||||
and step.status = 'COMPLETED';
|
||||
</update>
|
||||
|
||||
<update id="markOutboundWorkflowStepAtExit">
|
||||
update step with (updlock, rowlock)
|
||||
set step.status = 'AT_EXIT',
|
||||
step.at_exit_at = SYSUTCDATETIME()
|
||||
from alg.outbound_workflow_step step
|
||||
where step.assignment_id = #{assignmentId}
|
||||
and step.phase = 'OUTBOUND'
|
||||
and step.status = 'RUNNING';
|
||||
update workflow
|
||||
set workflow.current_step = step.workflow_step,
|
||||
workflow.updated_at = SYSUTCDATETIME()
|
||||
from alg.outbound_workflow workflow
|
||||
inner join alg.outbound_workflow_step step
|
||||
on step.workflow_id = workflow.workflow_id
|
||||
where step.assignment_id = #{assignmentId}
|
||||
and step.status = 'AT_EXIT';
|
||||
</update>
|
||||
|
||||
<update id="unlockOutboundWorkflowSpace">
|
||||
update space with (updlock, rowlock)
|
||||
set space.locked = 'N'
|
||||
from bas_cargo_space space
|
||||
where space.cargo_space_id = #{spaceId}
|
||||
and space.warehouse_id = #{warehouseId}
|
||||
and space.locked = 'Y'
|
||||
and exists (
|
||||
select 1
|
||||
from alg.outbound_workflow_space held with (updlock, holdlock)
|
||||
where held.workflow_id = #{workflowId}
|
||||
and held.space_id = #{spaceId}
|
||||
and held.space_id = space.cargo_space_id
|
||||
and held.status = 'ACTIVE'
|
||||
)
|
||||
</update>
|
||||
|
||||
<update id="relockOutboundWorkflowSpace">
|
||||
update space with (updlock, rowlock)
|
||||
set space.locked = 'Y'
|
||||
from bas_cargo_space space
|
||||
where space.cargo_space_id = #{spaceId}
|
||||
and space.warehouse_id = #{warehouseId}
|
||||
and space.status = '1'
|
||||
and (space.locked is null or ltrim(rtrim(space.locked)) in ('', '0', 'N'))
|
||||
and nullif(ltrim(rtrim(space.tray_code)), '') is null
|
||||
and not exists (
|
||||
select 1
|
||||
from bas_stock stock with (updlock, holdlock)
|
||||
where stock.cargo_space_id = space.cargo_space_id
|
||||
)
|
||||
and exists (
|
||||
select 1
|
||||
from alg.outbound_workflow_space held with (updlock, holdlock)
|
||||
where held.workflow_id = #{workflowId}
|
||||
and held.space_id = #{spaceId}
|
||||
and held.space_id = space.cargo_space_id
|
||||
and held.status = 'ACTIVE'
|
||||
)
|
||||
</update>
|
||||
|
||||
<select id="selectActiveOutboundJobId" resultType="string">
|
||||
select top (1) job.job_id
|
||||
from mydo_job job with (updlock, holdlock)
|
||||
inner join mydo_job_detail detail with (updlock, holdlock)
|
||||
on detail.job_id = job.job_id
|
||||
where detail.stock_id = #{stockId}
|
||||
and detail.in_or_out_d_id = #{stockoutDetailId}
|
||||
and try_convert(int, job.in_or_out) >= 20
|
||||
and try_convert(int, job.in_or_out) <> 28
|
||||
order by job.create_time desc, job.job_id desc
|
||||
</select>
|
||||
|
||||
<update id="completeOutboundWorkflow">
|
||||
update workflow with (updlock, rowlock)
|
||||
set workflow.status = 'COMPLETED',
|
||||
workflow.current_step = workflow.total_steps,
|
||||
workflow.updated_at = SYSUTCDATETIME(),
|
||||
workflow.completed_at = SYSUTCDATETIME()
|
||||
from alg.outbound_workflow workflow
|
||||
where workflow.workflow_id = #{workflowId}
|
||||
and workflow.status = 'ACTIVE'
|
||||
and not exists (
|
||||
select 1
|
||||
from alg.outbound_workflow_step step with (updlock, holdlock)
|
||||
where step.workflow_id = workflow.workflow_id
|
||||
and step.status <> 'COMPLETED'
|
||||
)
|
||||
</update>
|
||||
|
||||
<update id="unlockOutboundWorkflowSpaces">
|
||||
update space with (updlock, rowlock)
|
||||
set space.locked = 'N'
|
||||
from bas_cargo_space space
|
||||
inner join alg.outbound_workflow_space held with (updlock, holdlock)
|
||||
on held.space_id = space.cargo_space_id
|
||||
and held.workflow_id = #{workflowId}
|
||||
and held.status = 'ACTIVE'
|
||||
where space.locked = 'Y';
|
||||
update alg.outbound_workflow_space
|
||||
set status = 'RELEASED', released_at = SYSUTCDATETIME()
|
||||
where workflow_id = #{workflowId}
|
||||
and status = 'ACTIVE';
|
||||
</update>
|
||||
|
||||
<resultMap id="tidyRecoveryEvidenceMap" type="com.ruoyi.algorithm.wms.tidy.TidyRecoveryEvidence">
|
||||
<constructor>
|
||||
<arg column="workflowId" javaType="java.lang.String"/><arg column="origin" javaType="com.ruoyi.algorithm.wms.tidy.TidyOrigin"/><arg column="workflowStatus" javaType="java.lang.String"/><arg column="activeLockCount" javaType="_int"/>
|
||||
<arg column="stepId" javaType="java.lang.String"/><arg column="stepNo" javaType="java.lang.Integer"/><arg column="stepStatus" javaType="java.lang.String"/><arg column="sourceSpaceId" javaType="java.lang.String"/><arg column="targetSpaceId" javaType="java.lang.String"/><arg column="trayCode" javaType="java.lang.String"/><arg column="activeTidyJobCount" javaType="_int"/>
|
||||
<arg column="activeJobId" javaType="java.lang.String"/><arg column="activeJobStatus" javaType="java.lang.String"/><arg column="activeJobInOrOut" javaType="java.lang.String"/><arg column="activeJobTrayCode" javaType="java.lang.String"/><arg column="activeJobSourceSpaceId" javaType="java.lang.String"/><arg column="activeJobTargetSpaceId" javaType="java.lang.String"/><arg column="finishedJobId" javaType="java.lang.String"/><arg column="finishedJobStatus" javaType="java.lang.String"/><arg column="finishedJobInOrOut" javaType="java.lang.String"/><arg column="finishedJobTrayCode" javaType="java.lang.String"/><arg column="finishedJobSourceSpaceId" javaType="java.lang.String"/><arg column="finishedJobTargetSpaceId" javaType="java.lang.String"/><arg column="sourceStockRows" javaType="_int"/><arg column="targetStockRows" javaType="_int"/><arg column="sourceSpaceStatus" javaType="java.lang.String"/><arg column="sourceSpaceTrayCode" javaType="java.lang.String"/><arg column="targetSpaceStatus" javaType="java.lang.String"/><arg column="targetSpaceTrayCode" javaType="java.lang.String"/>
|
||||
</constructor>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectTidyRecoveryEvidence" resultMap="tidyRecoveryEvidenceMap">
|
||||
select workflow.workflow_id workflowId, workflow.origin origin, workflow.status workflowStatus,
|
||||
(select count(*) from alg.tidy_space_lock held where held.workflow_id = workflow.workflow_id and held.status = 'ACTIVE') activeLockCount,
|
||||
active_step.step_id stepId, active_step.step_no stepNo, active_step.status stepStatus, active_step.source_space_id sourceSpaceId, active_step.target_space_id targetSpaceId, active_step.tray_code trayCode,
|
||||
(select count(*) from dbo.mydo_job workflow_job where workflow_job.job_id like concat('TDY-', workflow.workflow_id, '-%')) activeTidyJobCount,
|
||||
active_job.job_id activeJobId, active_job.status activeJobStatus, active_job.in_or_out activeJobInOrOut, active_job.tray_code activeJobTrayCode, active_job.cargo_space_id activeJobSourceSpaceId, active_job.target_cargo_space_id activeJobTargetSpaceId,
|
||||
finished_job.job_id finishedJobId, finished_job.status finishedJobStatus, finished_job.in_or_out finishedJobInOrOut, finished_job.tray_code finishedJobTrayCode, finished_job.cargo_space_id finishedJobSourceSpaceId, finished_job.target_cargo_space_id finishedJobTargetSpaceId,
|
||||
(select count(*) from dbo.bas_stock source_stock where source_stock.cargo_space_id = active_step.source_space_id and source_stock.tray_code = active_step.tray_code) sourceStockRows,
|
||||
(select count(*) from dbo.bas_stock target_stock where target_stock.cargo_space_id = active_step.target_space_id and target_stock.tray_code = active_step.tray_code) targetStockRows,
|
||||
source_space.status sourceSpaceStatus, source_space.tray_code sourceSpaceTrayCode, target_space.status targetSpaceStatus, target_space.tray_code targetSpaceTrayCode
|
||||
from alg.tidy_workflow workflow
|
||||
outer apply (select top (1) step.step_id, step.step_no, step.status, step.source_space_id, step.target_space_id, step.tray_code from alg.tidy_step step where step.workflow_id = workflow.workflow_id and step.status in ('PENDING','DISPATCHED','RUNNING','PAUSED_RECOVERY') order by step.step_no) active_step
|
||||
left join dbo.mydo_job active_job on active_job.job_id = concat('TDY-', workflow.workflow_id, '-', active_step.step_id)
|
||||
left join dbo.mydo_job_finish finished_job on finished_job.job_id = concat('TDY-', workflow.workflow_id, '-', active_step.step_id)
|
||||
left join dbo.bas_cargo_space source_space on source_space.cargo_space_id = active_step.source_space_id
|
||||
left join dbo.bas_cargo_space target_space on target_space.cargo_space_id = active_step.target_space_id
|
||||
where workflow.warehouse_id = #{warehouseId} and workflow.status in ('CLAIMED','WAITING_DISPATCH','DISPATCHED','RUNNING','PAUSED_RECOVERY')
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -0,0 +1,225 @@
|
||||
package com.ruoyi.algorithm.wms;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class WmsAlgorithmMapperWorkflowSqlTest {
|
||||
|
||||
@Test
|
||||
void startStockReadLocksLiveStockAndRequiresAnAvailableOccupiedSpace() throws IOException {
|
||||
String statement = statement("select", "selectOutboundWorkflowStartStockForUpdate");
|
||||
|
||||
assertThat(statement)
|
||||
.contains("from bas_stock stock with (updlock, holdlock)")
|
||||
.contains("inner join bas_cargo_space space with (updlock, holdlock)")
|
||||
.contains("stock.stock_id = #{stockid}")
|
||||
.contains("space.status = '2'")
|
||||
.contains("ltrim(rtrim(space.locked)) in ('', '0', 'n')");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shallowCommitLocksTheExactLiveSelectionAndRejectsAnyOuterBlocker() throws IOException {
|
||||
String statement = statement("select", "selectOutboundShallowCommitStockForUpdate");
|
||||
|
||||
assertThat(statement)
|
||||
.contains("from bas_stock stock with (updlock, holdlock)")
|
||||
.contains("inner join bas_cargo_space source with (updlock, holdlock)")
|
||||
.doesNotContain("cross apply")
|
||||
.doesNotContain("lane_guard")
|
||||
.contains("stock.stock_id = #{stockid}")
|
||||
.contains("stock.warehouse_id = #{warehouseid}")
|
||||
.contains("stock.cargo_space_id = #{spaceid}")
|
||||
.contains("stock.tray_code = #{traycode}")
|
||||
.contains("stock.spare4 = #{projectno}")
|
||||
.contains("stock.stock_status = '1'")
|
||||
.contains("stock.product_status = '1'")
|
||||
.contains("stock.quantity > stock.out_quantity")
|
||||
.contains("source.status = '2'")
|
||||
.contains("source.tray_code = #{traycode}")
|
||||
.contains("ltrim(rtrim(source.locked)) in ('', '0', 'n')")
|
||||
.contains("from bas_cargo_space outer_space with (updlock, holdlock)")
|
||||
.contains("outer_space.group_coding_no = source.group_coding_no")
|
||||
.contains("try_convert(int, outer_space.group_coding) > try_convert(int, source.group_coding)")
|
||||
.contains("isnull(outer_space.status, '') <> '1'")
|
||||
.doesNotContain("<")
|
||||
.doesNotContain(">")
|
||||
.contains("nullif(ltrim(rtrim(outer_space.tray_code)), '') is not null")
|
||||
.contains("ltrim(rtrim(outer_space.locked)) not in ('', '0', 'n')")
|
||||
.contains("from bas_stock outer_stock with (updlock, holdlock)")
|
||||
.contains("outer_stock.cargo_space_id = outer_space.cargo_space_id");
|
||||
}
|
||||
|
||||
@Test
|
||||
void relocationInsertRequiresExactSourceEmptyTargetAndWorkflowOwnedLocks() throws IOException {
|
||||
String statement = statement("insert", "insertOutboundWorkflowMoveJob");
|
||||
|
||||
assertThat(statement)
|
||||
.contains("source_stock.stock_id = #{stockid}")
|
||||
.contains("source_stock.tray_code = #{traycode}")
|
||||
.contains("source_stock.cargo_space_id = source_space.cargo_space_id")
|
||||
.contains("target_space.status = '1'")
|
||||
.contains("nullif(ltrim(rtrim(target_space.tray_code)), '') is null")
|
||||
.contains("from bas_stock target_stock with (updlock, holdlock)")
|
||||
.contains("source_lock.workflow_id = #{workflowid}")
|
||||
.contains("target_lock.workflow_id = #{workflowid}")
|
||||
.contains("source_lock.status = 'active'")
|
||||
.contains("target_lock.status = 'active'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void selectiveUnlockIsScopedAndPreservesWorkflowOwnership() throws IOException {
|
||||
String statement = statement("update", "unlockOutboundWorkflowSpace");
|
||||
|
||||
assertThat(statement)
|
||||
.contains("held.workflow_id = #{workflowid}")
|
||||
.contains("held.space_id = #{spaceid}")
|
||||
.contains("space.warehouse_id = #{warehouseid}")
|
||||
.doesNotContain("update alg.outbound_workflow_space")
|
||||
.doesNotContain("status = 'released'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void restoreRelockIsScopedToActiveOwnershipAndAnEmptyAvailableTarget() throws IOException {
|
||||
String statement = statement("update", "relockOutboundWorkflowSpace");
|
||||
|
||||
assertThat(statement)
|
||||
.contains("space.cargo_space_id = #{spaceid}")
|
||||
.contains("space.warehouse_id = #{warehouseid}")
|
||||
.contains("space.status = '1'")
|
||||
.contains("ltrim(rtrim(space.locked)) in ('', '0', 'n')")
|
||||
.contains("nullif(ltrim(rtrim(space.tray_code)), '') is null")
|
||||
.contains("from bas_stock stock with (updlock, holdlock)")
|
||||
.contains("held.workflow_id = #{workflowid}")
|
||||
.contains("held.space_id = #{spaceid}")
|
||||
.contains("held.status = 'active'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void finalUnlockStillReleasesPhysicalLocksAndActiveOwnershipRows() throws IOException {
|
||||
String statement = statement("update", "unlockOutboundWorkflowSpaces");
|
||||
|
||||
assertThat(statement)
|
||||
.contains("set space.locked = 'n'")
|
||||
.contains("held.workflow_id = #{workflowid}")
|
||||
.contains("held.status = 'active'")
|
||||
.contains("update alg.outbound_workflow_space")
|
||||
.contains("set status = 'released'")
|
||||
.contains("where workflow_id = #{workflowid}")
|
||||
.contains("and status = 'active'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void activeWorkflowOwnershipCheckUsesRequestWarehouseAndFloor() throws IOException {
|
||||
String statement = statement("select", "countActiveOutboundWorkflow");
|
||||
|
||||
assertThat(statement)
|
||||
.contains("workflow.request_id = #{requestid}")
|
||||
.contains("workflow.warehouse_id = #{warehouseid}")
|
||||
.contains("workflow.floor_no = #{floorno}")
|
||||
.contains("workflow.status = 'active'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void tidyAdmissionCountsDoNotTakeUpdateOrRangeLocks() throws IOException {
|
||||
assertThat(statement("select", "countActiveBusinessExecution"))
|
||||
.doesNotContain("updlock")
|
||||
.doesNotContain("holdlock");
|
||||
assertThat(statement("select", "countActiveManualTidy"))
|
||||
.doesNotContain("updlock")
|
||||
.doesNotContain("holdlock");
|
||||
}
|
||||
|
||||
@Test
|
||||
void tidyDrainIgnoresPendingBusinessDocumentsUntilTheyHaveAnExecutionTarget() throws IOException {
|
||||
assertThat(statement("select", "countActiveBusinessExecution"))
|
||||
.contains("job.status in ('2', '3')")
|
||||
.contains("job.status = '1'")
|
||||
.contains("nullif(ltrim(rtrim(job.cargo_space_id)), '') is not null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void tidyModeLockReadsOnlyTheModeRow() throws IOException {
|
||||
assertThat(statement("select", "selectTidyModeForUpdate"))
|
||||
.contains("from alg.tidy_mode mode with (updlock, holdlock)")
|
||||
.contains("0 as draincount")
|
||||
.contains("0 as activetidycount")
|
||||
.doesNotContain("<include")
|
||||
.doesNotContain("mydo_job")
|
||||
.doesNotContain("tidy_workflow");
|
||||
}
|
||||
|
||||
@Test
|
||||
void candidateLaneClaimDelegatesFilteringToTheAtomicClaimProcedure() throws IOException {
|
||||
assertThat(statement("select", "claimTidyLaneFromCandidates"))
|
||||
.contains("exec alg.usp_claim_tidy_lane")
|
||||
.contains("@eligible_lane_codes = #{eligiblelanecodes}")
|
||||
.doesNotContain("foreach");
|
||||
}
|
||||
|
||||
@Test
|
||||
void activeTidyWorkflowUsesAnExplicitDatabaseShapedConstructorMapping() throws IOException {
|
||||
assertThat(statement("resultmap", "tidyWorkflowStateMap"))
|
||||
.contains("<constructor>")
|
||||
.contains("column=\"workflowid\" javatype=\"java.lang.string\"")
|
||||
.contains("column=\"origin\" javatype=\"com.ruoyi.algorithm.wms.tidy.tidyorigin\"")
|
||||
.contains("column=\"activestep\" javatype=\"_int\"");
|
||||
assertThat(statement("select", "selectActiveTidyWorkflows"))
|
||||
.contains("resultmap=\"tidyworkflowstatemap\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void tidyRecoveryProjectionMapsWorkflowJobInventoryAndLockEvidence() throws IOException {
|
||||
String mapping = statement("resultmap", "tidyRecoveryEvidenceMap");
|
||||
assertThat(mapping)
|
||||
.contains("type=\"com.ruoyi.algorithm.wms.tidy.tidyrecoveryevidence\"")
|
||||
.contains("column=\"workflowid\"")
|
||||
.contains("column=\"stepid\"")
|
||||
.contains("column=\"activejobid\"")
|
||||
.contains("column=\"finishedjobid\"")
|
||||
.contains("column=\"sourcestockrows\"")
|
||||
.contains("column=\"targetstockrows\"")
|
||||
.contains("column=\"activelockcount\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void tidyRecoveryQueryUsesOnlyWmsLocalAuthoritativeTables() throws IOException {
|
||||
String query = statement("select", "selectTidyRecoveryEvidence");
|
||||
assertThat(query)
|
||||
.contains("from alg.tidy_workflow workflow")
|
||||
.contains("outer apply")
|
||||
.contains("from alg.tidy_step step")
|
||||
.contains("left join dbo.mydo_job active_job")
|
||||
.contains("left join dbo.mydo_job_finish finished_job")
|
||||
.contains("from dbo.bas_stock")
|
||||
.contains("left join dbo.bas_cargo_space source_space")
|
||||
.contains("left join dbo.bas_cargo_space target_space")
|
||||
.contains("from alg.tidy_space_lock")
|
||||
.contains("concat('tdy-', workflow.workflow_id, '-', active_step.step_id)")
|
||||
.doesNotContain("wcs_task_id");
|
||||
}
|
||||
|
||||
private String statement(String element, String id) throws IOException {
|
||||
String xml = mapperXml().toLowerCase().replaceAll("\\s+", " ");
|
||||
String opening = "<" + element + " id=\"" + id.toLowerCase() + "\"";
|
||||
int start = xml.indexOf(opening);
|
||||
assertThat(start).as("mapper statement %s", id).isGreaterThanOrEqualTo(0);
|
||||
int end = xml.indexOf("</" + element + ">", start);
|
||||
assertThat(end).as("closing tag for mapper statement %s", id).isGreaterThan(start);
|
||||
return xml.substring(start, end);
|
||||
}
|
||||
|
||||
private String mapperXml() throws IOException {
|
||||
try (InputStream stream = getClass().getResourceAsStream(
|
||||
"/mapper/algorithm/WmsAlgorithmMapper.xml")) {
|
||||
if (stream == null) {
|
||||
throw new IOException("WmsAlgorithmMapper.xml not found on the test classpath");
|
||||
}
|
||||
return new String(stream.readAllBytes(), StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user