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