From a8e4132c3e2e9c3b3fcb0360901b35571b6464ea Mon Sep 17 00:00:00 2001
From: hsy <1029150275@qq.com>
Date: 星期五, 28 八月 2026 10:13:01 +0800
Subject: [PATCH] feat: 综合业务模块功能补充与实体拓展
---
src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java | 277 +++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 248 insertions(+), 29 deletions(-)
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java
index 2a4f52a..6d3b8d6 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java
@@ -48,6 +48,11 @@
import com.ruoyi.sales.pojo.ShippingInfo;
import com.ruoyi.staff.mapper.HolidayApplicationMapper;
import com.ruoyi.staff.pojo.HolidayApplication;
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.device.pojo.DeviceStatusChangeRecord;
+import com.ruoyi.device.service.IDeviceStatusChangeRecordService;
+import com.ruoyi.device.pojo.DeviceLedger;
+import com.ruoyi.device.service.IDeviceLedgerService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -94,6 +99,8 @@
private final EnterpriseNewsMapper enterpriseNewsMapper;
private final EnterpriseNewsScopeDeptMapper enterpriseNewsScopeDeptMapper;
private final ApprovalTemplateNodeApproverMapper approvalTemplateNodeApproverMapper;
+ private final IDeviceStatusChangeRecordService deviceStatusChangeRecordService;
+ private final IDeviceLedgerService deviceLedgerService;
@Override
public R listPage(Page<ApprovalInstanceVo> page, ApprovalInstanceDto approvalInstanceDto) {
@@ -105,6 +112,29 @@
}
records.forEach(vo -> {
vo.setBusinessName(TypeEnums.getLabelByValue(vo.getBusinessType()));
+
+ // 鏍规嵁涓氬姟绫诲瀷鏌ヨ瀵瑰簲鐨勫崟鍙�
+ if (vo.getBusinessType() != null && vo.getBusinessId() != null) {
+ if (TypeEnums.PURCHASE_APPROVAL.getCode().equals(vo.getBusinessType())) {
+ // 閲囪喘瀹℃壒 - 鏌ヨ閲囪喘鍗曞彿
+ PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(vo.getBusinessId());
+ if (purchaseLedger != null) {
+ vo.setPurchaseContractNumber(purchaseLedger.getPurchaseContractNumber());
+ }
+ } else if (TypeEnums.QUOTATION_APPROVAL.getCode().equals(vo.getBusinessType())) {
+ // 鎶ヤ环瀹℃壒 - 鏌ヨ鎶ヤ环鍗曞彿
+ SalesQuotation salesQuotation = salesQuotationMapper.selectById(vo.getBusinessId());
+ if (salesQuotation != null) {
+ vo.setQuotationNo(salesQuotation.getQuotationNo());
+ }
+ } else if (TypeEnums.SHIPPING_APPROVAL.getCode().equals(vo.getBusinessType())) {
+ // 鍙戣揣瀹℃壒 - 鏌ヨ鍙戣揣鍗曞彿
+ ShippingInfo shippingInfo = shippingInfoMapper.selectById(vo.getBusinessId());
+ if (shippingInfo != null) {
+ vo.setShippingNo(shippingInfo.getShippingNo());
+ }
+ }
+ }
});
Long currentUserId = SecurityUtils.getUserId();
@@ -144,6 +174,63 @@
approvalInstanceDto.setInstanceNo(instanceNo);
approvalInstanceDto.setStatus("PENDING");
approvalInstanceDto.setCurrentLevel(1);
+
+ if (approvalInstanceDto.getApplicantId() == null) {
+ approvalInstanceDto.setApplicantId(SecurityUtils.getUserId());
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ if (loginUser != null && loginUser.getUser() != null) {
+ approvalInstanceDto.setApplicantName(loginUser.getUser().getNickName());
+ }
+ }
+
+ // 鏍¢獙璁惧鐘舵�佸彉鏇村鎵癸細濡傛灉璇ヨ澶囧凡鏈夋鍦ㄥ鎵圭殑浠诲姟锛屾棤娉曞啀娆¤繘琛屽鎵�
+ if (TypeEnums.DEVICE_STATUS_CHANGE_APPROVAL.getCode().equals(approvalInstanceDto.getBusinessType())) {
+ Long deviceId = approvalInstanceDto.getBusinessId();
+
+ long pendingCount = deviceStatusChangeRecordService.count(Wrappers.<DeviceStatusChangeRecord>lambdaQuery()
+ .eq(DeviceStatusChangeRecord::getDeviceId, deviceId)
+ .eq(DeviceStatusChangeRecord::getApprovalStatus, "PENDING")
+ .eq(DeviceStatusChangeRecord::getDeleted, 0)
+ );
+ if (pendingCount > 0) {
+ throw new ServiceException("璇ヨ澶囧凡鏈夋鍦ㄨ繘琛岀殑鐘舵�佸彉鏇村鎵癸紝鏃犳硶鍐嶆鎻愪氦");
+ }
+
+ DeviceLedger device = deviceLedgerService.getById(deviceId);
+ if (device == null) {
+ throw new ServiceException("璁惧涓嶅瓨鍦�");
+ }
+
+ Integer targetStatus = null;
+ String reason = "";
+ if (StringUtils.hasText(approvalInstanceDto.getFormConfig())) {
+ try {
+ JSONObject formObj = JSONObject.parseObject(approvalInstanceDto.getFormConfig());
+ if (formObj.containsKey("targetStatus")) {
+ targetStatus = formObj.getInteger("targetStatus");
+ } else if (formObj.containsKey("status")) {
+ targetStatus = formObj.getInteger("status");
+ }
+ if (formObj.containsKey("reason")) {
+ reason = formObj.getString("reason");
+ }
+ } catch (Exception e) {
+ log.error("瑙f瀽鐘舵�佸彉鏇磋〃鍗曞け璐�", e);
+ }
+ }
+
+ DeviceStatusChangeRecord record = new DeviceStatusChangeRecord();
+ record.setDeviceId(deviceId);
+ record.setOriginalStatus(Integer.valueOf(device.getStatus()));
+ record.setTargetStatus(targetStatus);
+ record.setReason(reason);
+ record.setApprovalStatus("PENDING");
+ deviceStatusChangeRecordService.save(record);
+
+ // 缁戝畾鍒板叧鑱旇褰曠殑涓婚敭
+ approvalInstanceDto.setBusinessId(record.getId());
+ }
+
boolean saved = this.save(approvalInstanceDto);
if (!saved) {
return false;
@@ -261,13 +348,94 @@
);
//瀹℃壒鎷掔粷鐨勫鐞�
if ("REJECTED".equals(approveAction)) {
- return rejectCurrentNode(instance, currentNode, now);
+ return rejectCurrentNode(instance, currentNode, approvalInstanceDto.getApproveComment(), now);
}
if (!approveProcessConfigNodeUtils.canProceedToNextLevel(instance.getId(), currentNode.getApproveType())) {
return R.ok("瀹℃壒鎴愬姛锛岀瓑寰呭叾浠栧鎵逛汉澶勭悊");
}
return approveAndMoveNext(instance, currentNode, approvalInstanceDto, now);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public R autoApprove(Long instanceId) {
+ if (instanceId == null) {
+ return R.fail("瀹℃壒瀹炰緥 ID 涓嶈兘涓虹┖");
+ }
+
+ ApprovalInstance instance = getPendingApprovalInstance(instanceId);
+ if (instance == null) {
+ return R.fail("瀹℃壒瀹炰緥涓嶅瓨鍦�");
+ }
+ if ("REJECTED".equals(instance.getStatus())) {
+ return R.fail("瀹℃壒宸查┏鍥烇紝鏃犳硶鑷姩閫氳繃");
+ }
+ if ("APPROVED".equals(instance.getStatus())) {
+ return R.ok("瀹℃壒宸插畬鎴�");
+ }
+
+ ApprovalInstanceDto autoApproveDto = new ApprovalInstanceDto();
+ autoApproveDto.setId(instanceId);
+ autoApproveDto.setApproveComment("绯荤粺鑷姩瀹℃壒");
+
+ int loopCount = 0;
+ while (loopCount++ < 20) {
+ ApprovalInstance currentInstance = getPendingApprovalInstance(instanceId);
+ if (currentInstance == null) {
+ return R.fail("瀹℃壒瀹炰緥涓嶅瓨鍦�");
+ }
+ if ("APPROVED".equals(currentInstance.getStatus())) {
+ return R.ok("瀹℃壒宸插畬鎴�");
+ }
+ if ("REJECTED".equals(currentInstance.getStatus())) {
+ return R.fail("瀹℃壒宸查┏鍥烇紝鏃犳硶鑷姩閫氳繃");
+ }
+
+ ApprovalInstanceNode currentNode = approveProcessConfigNodeUtils.getCurrentNode(currentInstance.getId());
+ if (currentNode == null) {
+ currentInstance.setStatus("APPROVED");
+ currentInstance.setFinishTime(LocalDateTime.now());
+ this.updateById(currentInstance);
+ handleBusinessAfterApprovalFinished(currentInstance, null);
+ return R.ok("瀹℃壒宸插畬鎴�");
+ }
+
+ List<ApprovalTask> pendingTasks = approvalTaskService.list(
+ Wrappers.<ApprovalTask>lambdaQuery()
+ .eq(ApprovalTask::getInstanceId, currentInstance.getId())
+ .eq(ApprovalTask::getNodeId, currentNode.getId())
+ .eq(ApprovalTask::getTaskStatus, "PENDING")
+ .eq(ApprovalTask::getDeleted, 0)
+ );
+
+ LocalDateTime now = LocalDateTime.now();
+ for (ApprovalTask currentTask : pendingTasks) {
+ if (!updateCurrentTask(autoApproveDto, "APPROVED", currentTask, now)) {
+ return R.fail("褰撳墠浠诲姟宸茶澶勭悊锛岃鍒锋柊鍚庨噸璇�");
+ }
+ saveApprovalRecord(
+ currentInstance.getId(),
+ currentNode.getId(),
+ currentTask.getId(),
+ 0L,
+ "绯荤粺鑷姩瀹℃壒",
+ "APPROVED",
+ autoApproveDto.getApproveComment()
+ );
+ }
+
+ if (!approveProcessConfigNodeUtils.canProceedToNextLevel(currentInstance.getId(), currentNode.getApproveType())) {
+ return R.ok("瀹℃壒鎴愬姛锛岀瓑寰呭叾浠栧鎵逛汉澶勭悊");
+ }
+
+ R moveResult = moveToNextLevel(currentInstance, currentNode, autoApproveDto, now, false);
+ if (!R.isSuccess(moveResult)) {
+ return moveResult;
+ }
+ }
+
+ return R.fail("鑷姩瀹℃壒寰幆娆℃暟瓒呴檺");
}
private String normalizeApproveAction(String approveAction) {
@@ -306,7 +474,7 @@
);
}
- private R rejectCurrentNode(ApprovalInstance instance, ApprovalInstanceNode currentNode, LocalDateTime now) {
+ private R rejectCurrentNode(ApprovalInstance instance, ApprovalInstanceNode currentNode, String approveComment, LocalDateTime now) {
if (!updateCurrentNodeStatus(currentNode.getId(), "REJECTED", now)) {
return R.ok("褰撳墠鑺傜偣宸插鐞嗗畬鎴�");
}
@@ -315,20 +483,8 @@
instance.setStatus("REJECTED");
instance.setFinishTime(now);
this.updateById(instance);
- // 椹冲洖瀵瑰簲鐨勪紒涓氭柊闂伙紝 宸梾鎶ラ攢
- if (instance.getBusinessType().equals(TypeEnums.ENTERPRISE_NEWS_APPROVAL.getCode())) {
- enterpriseNewsMapper.update(
- new LambdaUpdateWrapper<EnterpriseNews>()
- .eq(EnterpriseNews::getId, instance.getBusinessId())
- .set(EnterpriseNews::getStatus, "REJECTED")
- );
- }else if (instance.getBusinessType().equals(TypeEnums.TRAVEL_REIMBURSEMENT_APPROVAL.getCode())||instance.getBusinessType().equals(TypeEnums.EXPENSE_APPROVAL.getCode())) {
- finReimbursementMapper.update(
- new LambdaUpdateWrapper<FinReimbursement>()
- .eq(FinReimbursement::getId, instance.getBusinessId())
- .set(FinReimbursement::getBillStatus, "REJECTED")
- );
- }
+ // 缁熶竴澶勭悊涓氬姟鐘舵�佹洿鏂�
+ handleBusinessAfterApprovalFinished(instance, approveComment);
return R.ok("瀹℃壒宸查┏鍥�");
}
@@ -336,6 +492,14 @@
ApprovalInstanceNode currentNode,
ApprovalInstanceDto approvalInstanceDto,
LocalDateTime now) {
+ return moveToNextLevel(instance, currentNode, approvalInstanceDto, now, true);
+ }
+
+ private R moveToNextLevel(ApprovalInstance instance,
+ ApprovalInstanceNode currentNode,
+ ApprovalInstanceDto approvalInstanceDto,
+ LocalDateTime now,
+ boolean notifyNextNode) {
if (!updateCurrentNodeStatus(currentNode.getId(), "APPROVED", now)) {
return R.ok("褰撳墠鑺傜偣宸插鐞嗗畬鎴�");
}
@@ -359,14 +523,16 @@
instance.setCurrentLevel(nextLevel);
instance.setStatus("PENDING");
this.updateById(instance);
- List<ApprovalTask> nextTasks = approvalTaskService.list(
- Wrappers.<ApprovalTask>lambdaQuery()
- .eq(ApprovalTask::getInstanceId, instance.getId())
- .eq(ApprovalTask::getNodeId, nextInstanceNode.getId())
- .eq(ApprovalTask::getTaskStatus, "PENDING")
- .eq(ApprovalTask::getDeleted, 0)
- );
- sendApproveNotice(instance, nextTasks);
+ if (notifyNextNode) {
+ List<ApprovalTask> nextTasks = approvalTaskService.list(
+ Wrappers.<ApprovalTask>lambdaQuery()
+ .eq(ApprovalTask::getInstanceId, instance.getId())
+ .eq(ApprovalTask::getNodeId, nextInstanceNode.getId())
+ .eq(ApprovalTask::getTaskStatus, "PENDING")
+ .eq(ApprovalTask::getDeleted, 0)
+ );
+ sendApproveNotice(instance, nextTasks);
+ }
return R.ok("瀹℃壒鎴愬姛锛屽凡娴佽浆鍒颁笅涓�鑺傜偣");
}
@@ -382,7 +548,7 @@
instance.setStatus("APPROVED");
instance.setFinishTime(now);
this.updateById(instance);
- handleBusinessAfterApprovalFinished(instance);
+ handleBusinessAfterApprovalFinished(instance, null);
return R.ok("瀹℃壒宸插畬鎴�");
}
@@ -390,7 +556,9 @@
instance.setStatus("PENDING");
this.updateById(instance);
approveProcessConfigNodeUtils.createCurrentNodeAndTasks(instance, false);
- sendApproveNotice(instance, approveProcessConfigNodeUtils.getCurrentPendingTasks(approvalInstanceDto.getId()));
+ if (notifyNextNode) {
+ sendApproveNotice(instance, approveProcessConfigNodeUtils.getCurrentPendingTasks(approvalInstanceDto.getId()));
+ }
return R.ok("瀹℃壒鎴愬姛锛屽凡娴佽浆鍒颁笅涓�鑺傜偣");
}
@@ -417,7 +585,7 @@
);
}
- private void handleBusinessAfterApprovalFinished(ApprovalInstance instance) {
+ private void handleBusinessAfterApprovalFinished(ApprovalInstance instance, String rejectReason) {
String status = instance.getStatus();
Long businessType = instance.getBusinessType();
if (TypeEnums.PURCHASE_APPROVAL.getCode().equals(businessType)) {
@@ -445,7 +613,39 @@
}
if (TypeEnums.ENTERPRISE_NEWS_APPROVAL.getCode().equals(businessType)) {
handleNewsApprovalFinished(instance, status);
+ return;
}
+ if (TypeEnums.DEVICE_STATUS_CHANGE_APPROVAL.getCode().equals(businessType)) {
+ handleDeviceStatusChangeApprovalFinished(instance, status, rejectReason);
+ return;
+ }
+ }
+
+ private void handleDeviceStatusChangeApprovalFinished(ApprovalInstance instance, String status, String rejectReason) {
+ if (instance == null || instance.getBusinessId() == null) {
+ return;
+ }
+ DeviceStatusChangeRecord record = deviceStatusChangeRecordService.getById(instance.getBusinessId());
+ if (record == null) {
+ return;
+ }
+ if ("APPROVED".equals(status)) {
+ record.setApprovalStatus("APPROVED");
+ if (record.getTargetStatus() != null) {
+ DeviceLedger device = new DeviceLedger();
+ device.setId(record.getDeviceId());
+ device.setStatus(String.valueOf(record.getTargetStatus()));
+ deviceLedgerService.updateById(device);
+ }
+ } else if ("REJECTED".equals(status)) {
+ record.setApprovalStatus("REJECTED");
+ if (rejectReason != null) {
+ record.setRejectReason(rejectReason);
+ }
+ } else if ("PENDING".equals(status)) {
+ record.setApprovalStatus("PENDING");
+ }
+ deviceStatusChangeRecordService.updateById(record);
}
private void handleReimbursementApprovalFinished(ApprovalInstance instance, String status) {
@@ -565,7 +765,7 @@
private void handleShippingApprovalFinished(ApprovalInstance instance, String status) {
ShippingInfo shippingInfo = shippingInfoMapper.selectOne(
new LambdaQueryWrapper<ShippingInfo>()
- .eq(ShippingInfo::getId, instance.getTitle())
+ .eq(ShippingInfo::getShippingNo, instance.getTitle())
.orderByDesc(ShippingInfo::getCreateTime)
.last("limit 1")
);
@@ -640,10 +840,29 @@
String title = StringUtils.hasText(instance.getTemplateName()) ? instance.getTemplateName() : "瀹℃壒鎻愰啋";
String message = "瀹℃壒鍗曞彿 " + instance.getInstanceNo() + " 闇�瑕佹偍瀹℃壒";
- String jumpPath = "/officeProcessAutomation/ApproveManage/approve-list?id=" + instance.getId();
+ String jumpPath = getJumpPathByBusinessType(instance.getBusinessType(), instance.getId());
sysNoticeService.simpleNoticeByUser(title, message, approverIds, jumpPath);
}
+ private String getJumpPathByBusinessType(Long businessType, Long instanceId) {
+ if (businessType == null) {
+ return "/collaborativeApproval/approve-list?id=" + instanceId;
+ }
+ if (TypeEnums.LEAVE_APPROVAL.getCode().equals(businessType)) {
+ return "/collaborativeApproval/AttendManage/leave-apply?id=" + instanceId;
+ }
+ if (TypeEnums.OVERTIME_APPROVAL.getCode().equals(businessType)) {
+ return "/collaborativeApproval/AttendManage/overtime-apply?id=" + instanceId;
+ }
+ if (TypeEnums.TRAVEL_REIMBURSEMENT_APPROVAL.getCode().equals(businessType)) {
+ return "/collaborativeApproval/ReimburseManage/travel-reimburse?id=" + instanceId;
+ }
+ if (TypeEnums.EXPENSE_APPROVAL.getCode().equals(businessType)) {
+ return "/collaborativeApproval/ReimburseManage/cost-reimburse?id=" + instanceId;
+ }
+ return "/collaborativeApproval/approve-list?id=" + instanceId;
+ }
+
private void sendEnterpriseNewsNotice(Long newsId) {
EnterpriseNews enterpriseNews = enterpriseNewsMapper.selectById(newsId);
if (enterpriseNews == null) {
--
Gitblit v1.9.3