feat: add ERP push failure recovery
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
package com.ruoyi.erp.push.controller;
|
||||
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.erp.push.domain.ErpPushException;
|
||||
import com.ruoyi.erp.push.domain.ErpPushRetryRequest;
|
||||
import com.ruoyi.erp.push.service.IErpPushExceptionService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/erp/push-exception")
|
||||
public class ErpPushExceptionController extends BaseController {
|
||||
private final IErpPushExceptionService service;
|
||||
|
||||
public ErpPushExceptionController(IErpPushExceptionService service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('erp:pushException:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(ErpPushException query) {
|
||||
startPage();
|
||||
List<ErpPushException> list = service.selectFailureList(query);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('erp:pushException:retry')")
|
||||
@Log(title = "ERP推送异常重推", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/retry")
|
||||
public AjaxResult retry(@RequestBody ErpPushRetryRequest request) {
|
||||
if (service.retry(request)) {
|
||||
return AjaxResult.success("已加入重试队列");
|
||||
}
|
||||
return AjaxResult.error("单据状态已变化,可能已被处理,请刷新列表");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.ruoyi.erp.push.domain;
|
||||
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
|
||||
public class ErpPushException extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String documentType;
|
||||
private String recordId;
|
||||
private String documentNo;
|
||||
private String businessReference;
|
||||
private String failureTime;
|
||||
private String errorMessage;
|
||||
|
||||
public String getDocumentType() {
|
||||
return documentType;
|
||||
}
|
||||
|
||||
public void setDocumentType(String documentType) {
|
||||
this.documentType = documentType;
|
||||
}
|
||||
|
||||
public String getRecordId() {
|
||||
return recordId;
|
||||
}
|
||||
|
||||
public void setRecordId(String recordId) {
|
||||
this.recordId = recordId;
|
||||
}
|
||||
|
||||
public String getDocumentNo() {
|
||||
return documentNo;
|
||||
}
|
||||
|
||||
public void setDocumentNo(String documentNo) {
|
||||
this.documentNo = documentNo;
|
||||
}
|
||||
|
||||
public String getBusinessReference() {
|
||||
return businessReference;
|
||||
}
|
||||
|
||||
public void setBusinessReference(String businessReference) {
|
||||
this.businessReference = businessReference;
|
||||
}
|
||||
|
||||
public String getFailureTime() {
|
||||
return failureTime;
|
||||
}
|
||||
|
||||
public void setFailureTime(String failureTime) {
|
||||
this.failureTime = failureTime;
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ruoyi.erp.push.domain;
|
||||
|
||||
public class ErpPushRetryRequest {
|
||||
private String documentType;
|
||||
private String recordId;
|
||||
|
||||
public String getDocumentType() {
|
||||
return documentType;
|
||||
}
|
||||
|
||||
public void setDocumentType(String documentType) {
|
||||
this.documentType = documentType;
|
||||
}
|
||||
|
||||
public String getRecordId() {
|
||||
return recordId;
|
||||
}
|
||||
|
||||
public void setRecordId(String recordId) {
|
||||
this.recordId = recordId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.ruoyi.erp.push.mapper;
|
||||
|
||||
import com.ruoyi.erp.push.domain.ErpPushException;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ErpPushExceptionMapper {
|
||||
List<ErpPushException> selectFailureList(ErpPushException query);
|
||||
|
||||
int requeueInboundHeader(@Param("recordId") String recordId);
|
||||
|
||||
int requeueInboundDetails(@Param("recordId") String recordId);
|
||||
|
||||
int requeueOutboundHeader(@Param("recordId") String recordId);
|
||||
|
||||
int requeueOutboundDetails(@Param("recordId") String recordId);
|
||||
|
||||
int requeueMove(@Param("recordId") String recordId);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.ruoyi.erp.push.service;
|
||||
|
||||
import com.ruoyi.erp.push.domain.ErpPushException;
|
||||
import com.ruoyi.erp.push.domain.ErpPushRetryRequest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IErpPushExceptionService {
|
||||
List<ErpPushException> selectFailureList(ErpPushException query);
|
||||
|
||||
boolean retry(ErpPushRetryRequest request);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.ruoyi.erp.push.service.impl;
|
||||
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.erp.push.domain.ErpPushException;
|
||||
import com.ruoyi.erp.push.domain.ErpPushRetryRequest;
|
||||
import com.ruoyi.erp.push.mapper.ErpPushExceptionMapper;
|
||||
import com.ruoyi.erp.push.service.IErpPushExceptionService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
@Service
|
||||
public class ErpPushExceptionServiceImpl implements IErpPushExceptionService {
|
||||
private final ErpPushExceptionMapper mapper;
|
||||
|
||||
public ErpPushExceptionServiceImpl(ErpPushExceptionMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ErpPushException> selectFailureList(ErpPushException query) {
|
||||
return mapper.selectFailureList(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean retry(ErpPushRetryRequest request) {
|
||||
if (request == null || StringUtils.isEmpty(request.getDocumentType())
|
||||
|| StringUtils.isEmpty(request.getRecordId())) {
|
||||
throw new ServiceException("单据类型和记录编号不能为空");
|
||||
}
|
||||
|
||||
String type = request.getDocumentType().trim().toUpperCase(Locale.ROOT);
|
||||
String recordId = request.getRecordId().trim();
|
||||
switch (type) {
|
||||
case "INBOUND":
|
||||
return retryInbound(recordId);
|
||||
case "OUTBOUND":
|
||||
return retryOutbound(recordId);
|
||||
case "MOVE":
|
||||
return mapper.requeueMove(recordId) == 1;
|
||||
default:
|
||||
throw new ServiceException("不支持的单据类型: " + request.getDocumentType());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean retryInbound(String recordId) {
|
||||
if (mapper.requeueInboundHeader(recordId) != 1) {
|
||||
return false;
|
||||
}
|
||||
if (mapper.requeueInboundDetails(recordId) < 1) {
|
||||
throw new ServiceException("入库单缺少可重推的失败明细,已取消本次操作");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean retryOutbound(String recordId) {
|
||||
if (mapper.requeueOutboundHeader(recordId) != 1) {
|
||||
return false;
|
||||
}
|
||||
if (mapper.requeueOutboundDetails(recordId) < 1) {
|
||||
throw new ServiceException("出库单缺少可重推的失败明细,已取消本次操作");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?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.erp.push.mapper.ErpPushExceptionMapper">
|
||||
|
||||
<resultMap id="ErpPushExceptionResult" type="com.ruoyi.erp.push.domain.ErpPushException">
|
||||
<result property="documentType" column="document_type"/>
|
||||
<result property="recordId" column="record_id"/>
|
||||
<result property="documentNo" column="document_no"/>
|
||||
<result property="businessReference" column="business_reference"/>
|
||||
<result property="failureTime" column="failure_time"/>
|
||||
<result property="errorMessage" column="error_message"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="failureUnion">
|
||||
SELECT 'INBOUND' AS document_type,
|
||||
CONVERT(nvarchar(100), stockin_guid) AS record_id,
|
||||
CONVERT(nvarchar(100), stockin_id) AS document_no,
|
||||
CONVERT(nvarchar(300), stockin_id) AS business_reference,
|
||||
CONVERT(nvarchar(30), send_time) AS failure_time,
|
||||
CONVERT(nvarchar(max), msg) AS error_message
|
||||
FROM in_stockin_back
|
||||
WHERE send_status = '2' AND stock_source = '1'
|
||||
AND TRY_CONVERT(datetime2, send_time, 120) >= DATEADD(month, -1, SYSDATETIME())
|
||||
UNION ALL
|
||||
SELECT 'OUTBOUND',
|
||||
CONVERT(nvarchar(100), stockout_guid),
|
||||
CONVERT(nvarchar(100), stockout_id),
|
||||
CONVERT(nvarchar(300), stockout_id),
|
||||
CONVERT(nvarchar(30), send_time),
|
||||
CONVERT(nvarchar(max), msg)
|
||||
FROM out_stockout_back
|
||||
WHERE send_status = '2' AND stockout_source = '1'
|
||||
AND TRY_CONVERT(datetime2, send_time, 120) >= DATEADD(month, -1, SYSDATETIME())
|
||||
UNION ALL
|
||||
SELECT 'MOVE',
|
||||
CONVERT(nvarchar(100), id),
|
||||
CONVERT(nvarchar(100), id),
|
||||
CONCAT(ISNULL(tray_code, ''), ' ', ISNULL(old_space, ''), ' -> ', ISNULL(new_space, '')),
|
||||
CONVERT(nvarchar(30), send_time),
|
||||
CONVERT(nvarchar(max), msg)
|
||||
FROM move_msg
|
||||
WHERE status = '2'
|
||||
AND TRY_CONVERT(datetime2, send_time, 120) >= DATEADD(month, -1, SYSDATETIME())
|
||||
</sql>
|
||||
|
||||
<select id="selectFailureList" parameterType="com.ruoyi.erp.push.domain.ErpPushException"
|
||||
resultMap="ErpPushExceptionResult">
|
||||
SELECT failures.document_type,
|
||||
failures.record_id,
|
||||
failures.document_no,
|
||||
failures.business_reference,
|
||||
failures.failure_time,
|
||||
failures.error_message
|
||||
FROM (
|
||||
<include refid="failureUnion"/>
|
||||
) failures
|
||||
<where>
|
||||
<if test="documentType != null and documentType != ''">
|
||||
AND failures.document_type = #{documentType}
|
||||
</if>
|
||||
<if test="documentNo != null and documentNo != ''">
|
||||
AND failures.document_no LIKE CONCAT('%', #{documentNo}, '%')
|
||||
</if>
|
||||
<if test="errorMessage != null and errorMessage != ''">
|
||||
AND failures.error_message LIKE CONCAT('%', #{errorMessage}, '%')
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY failures.failure_time DESC, failures.record_id DESC
|
||||
</select>
|
||||
|
||||
<update id="requeueInboundHeader">
|
||||
UPDATE in_stockin_back
|
||||
SET send_status = '0', send_time = NULL, msg = N'已手动加入重试队列'
|
||||
WHERE stockin_guid = #{recordId} AND send_status = '2' AND stock_source = '1'
|
||||
AND TRY_CONVERT(datetime2, send_time, 120) >= DATEADD(month, -1, SYSDATETIME())
|
||||
</update>
|
||||
|
||||
<update id="requeueInboundDetails">
|
||||
UPDATE in_stockin_detail_back
|
||||
SET send_status = '0', send_time = NULL, msg = N'已手动加入重试队列'
|
||||
WHERE stockin_guid = #{recordId} AND send_status = '2'
|
||||
AND TRY_CONVERT(datetime2, send_time, 120) >= DATEADD(month, -1, SYSDATETIME())
|
||||
</update>
|
||||
|
||||
<update id="requeueOutboundHeader">
|
||||
UPDATE out_stockout_back
|
||||
SET send_status = '0', send_time = NULL, msg = N'已手动加入重试队列'
|
||||
WHERE stockout_guid = #{recordId} AND send_status = '2' AND stockout_source = '1'
|
||||
AND TRY_CONVERT(datetime2, send_time, 120) >= DATEADD(month, -1, SYSDATETIME())
|
||||
</update>
|
||||
|
||||
<update id="requeueOutboundDetails">
|
||||
UPDATE out_stockout_detail_back
|
||||
SET send_status = '0', send_time = NULL, msg = N'已手动加入重试队列'
|
||||
WHERE stockout_guid = #{recordId} AND send_status = '2'
|
||||
AND TRY_CONVERT(datetime2, send_time, 120) >= DATEADD(month, -1, SYSDATETIME())
|
||||
</update>
|
||||
|
||||
<update id="requeueMove">
|
||||
UPDATE move_msg
|
||||
SET status = '0', send_time = NULL, msg = N'已手动加入重试队列'
|
||||
WHERE id = #{recordId} AND status = '2'
|
||||
AND TRY_CONVERT(datetime2, send_time, 120) >= DATEADD(month, -1, SYSDATETIME())
|
||||
</update>
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user