重构手表绑定导入接口
This commit is contained in:
+30
@@ -0,0 +1,30 @@
|
||||
package com.renkang.watch.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
|
||||
@Data
|
||||
@Schema(title = "手表绑定记录导入v2版本")
|
||||
public class WatchDeviceExcelV2 {
|
||||
@Excel(name = "手表SN编码(必填)", width = 30)
|
||||
@Schema(title = "手表SN编码(必填)")
|
||||
private String watchNo;
|
||||
|
||||
@Excel(name = "员工编号(必填)", width = 25)
|
||||
@Schema(title = "员工编号(必填)")
|
||||
private String workNo;
|
||||
|
||||
@Excel(name = "员工姓名", width = 20)
|
||||
@Schema(title = "员工姓名")
|
||||
private String realName;
|
||||
|
||||
@Excel(name = "处理结果", width = 20)
|
||||
@Schema(title = "处理结果(导入成功,导入失败)")
|
||||
private String successFlag;
|
||||
|
||||
@Excel(name = "备注信息", width = 50)
|
||||
@Schema(title = "备注信息")
|
||||
private String remark;
|
||||
}
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ public class WatchDevice implements Serializable {
|
||||
*/
|
||||
@Excel(name = "绑定状态", width = 15)
|
||||
@TableField(exist = false)
|
||||
@Schema(title = "绑定状态")
|
||||
@Schema(title = "绑定状态(0-未绑定,1-已绑定)")
|
||||
private java.lang.String watchStatus;
|
||||
/**
|
||||
* 在线状态
|
||||
|
||||
+228
-20
@@ -1,22 +1,32 @@
|
||||
package com.renkang.watch.async;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.read.listener.PageReadListener;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.renkang.watch.dto.WatchDeviceExcel;
|
||||
import com.renkang.watch.dto.WatchDeviceExcelV2;
|
||||
import com.renkang.watch.entity.WatchBindHis;
|
||||
import com.renkang.watch.entity.WatchDevice;
|
||||
import com.renkang.watch.entity.WatchDeviceSwitch;
|
||||
import com.renkang.watch.mapper.WatchBindHisMapper;
|
||||
import com.renkang.watch.service.IWatchBindHisService;
|
||||
import com.renkang.watch.service.IWatchDeviceService;
|
||||
import com.renkang.watch.service.IWatchDeviceSwitchService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.jeecg.bean.request.ListUser;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.exception.ExceptionAssertsUtil;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.common.export.ExportUtils;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
@@ -26,18 +36,22 @@ import org.jeecg.modules.exports.entity.CommonExportsInfo;
|
||||
import org.jeecg.modules.manager.ISysCache;
|
||||
import org.jeecg.modules.system.entity.SysDepart;
|
||||
import org.jeecg.modules.system.entity.SysUser;
|
||||
import org.jeecgframework.poi.excel.ExcelExportUtil;
|
||||
import org.jeecgframework.poi.excel.ExcelImportUtil;
|
||||
import org.jeecgframework.poi.excel.entity.ExportParams;
|
||||
import org.jeecgframework.poi.excel.entity.ImportParams;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -46,23 +60,24 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class AsyncImportService {
|
||||
|
||||
@Resource
|
||||
private ISysBaseAPI sysBaseAPI;
|
||||
|
||||
@Resource
|
||||
private AsyncTaskExecutor taskExecutor;
|
||||
|
||||
@Resource
|
||||
private ISysCache sysCache;
|
||||
|
||||
@Resource
|
||||
private IWatchDeviceService watchDeviceService;
|
||||
@Resource
|
||||
private IWatchBindHisService watchBindHisService;
|
||||
@Resource
|
||||
private IWatchDeviceSwitchService watchDeviceSwitchService;
|
||||
// 导入设备code
|
||||
private final String WATCH_IMPORT_BIND_CODE = "importWatchBindCode";
|
||||
// 导入设备中
|
||||
private final String WATCH_IMPORT_BIND_DOING = "9";
|
||||
// 导入设备完成
|
||||
private final String WATCH_IMPORT_BIND_FINISH = "10";
|
||||
// 导入设备失败
|
||||
private final String WATCH_IMPORT_BIND_ERRCODE = "11";
|
||||
private final ISysBaseAPI sysBaseAPI;
|
||||
private final AsyncTaskExecutor taskExecutor;
|
||||
private final ISysCache sysCache;
|
||||
private final IWatchDeviceService watchDeviceService;
|
||||
private final IWatchBindHisService watchBindHisService;
|
||||
private final IWatchDeviceSwitchService watchDeviceSwitchService;
|
||||
private final AsyncTaskExecutor asyncTaskExecutor;
|
||||
private final WatchBindHisMapper watchBindHisMapper;
|
||||
|
||||
/**
|
||||
* 验证并填充开关列表switchList
|
||||
@@ -436,4 +451,197 @@ public class AsyncImportService {
|
||||
watchDevice.setBindDate(deviceExcel.getBindDate());
|
||||
return watchDevice;
|
||||
}
|
||||
|
||||
public Result<String> importExcelBindDataV2(MultipartFile file) {
|
||||
try {
|
||||
//1.导入模板和空模板校验,模板不合法直接报错,省去所有后续操作
|
||||
ImportParams params = new ImportParams();
|
||||
params.setTitleRows(1);
|
||||
params.setHeadRows(2);
|
||||
List<WatchDeviceExcelV2> importExceldataList = ExcelImportUtil.importExcel(file.getInputStream(), WatchDeviceExcelV2.class, params);
|
||||
if (ObjectUtils.isEmpty(importExceldataList) || ObjectUtils.isEmpty(importExceldataList.get(0))) {
|
||||
ExceptionAssertsUtil.fail("数据解析失败,请检查导入模板是否正确或填充数据后再导入");
|
||||
}
|
||||
Boolean flag = sysBaseAPI.getFinishFlagByCode(WATCH_IMPORT_BIND_CODE, WATCH_IMPORT_BIND_DOING);
|
||||
if (!flag) {
|
||||
return Result.error("已存在执行中的导入任务,请稍后导入或点击【查看导入任务】查看任务导出进度!");
|
||||
}
|
||||
//异步执行数据导入操作
|
||||
asyncTaskExecutor.execute(() -> importExcelBindDataV2Execute(importExceldataList,file.getOriginalFilename()));
|
||||
} catch (Exception e) {
|
||||
ExceptionAssertsUtil.fail("数据解析失败,请检查导入模板是否正确");
|
||||
}
|
||||
return Result.ok("导入任务启动成功,请点击【入库导入记录】查看导入详情!");
|
||||
}
|
||||
|
||||
/**
|
||||
* V2版本相较上一个版本的导入 最大的优化项是标记了每一项的导入结果, 如果导入失败会收集失败原因,并将结果追加到excel表中返回
|
||||
* 其次V2版本中新增了 用户重复绑定的校验 以及优化了代码的查询逻辑
|
||||
*/
|
||||
private void importExcelBindDataV2Execute(List<WatchDeviceExcelV2> importExceldataList,String fileName) {
|
||||
LoginUser loginUser = GlobalUtils.getLoginUser();
|
||||
int total = importExceldataList.size(); //数据总条数
|
||||
int index = 0; //成功数量计数器
|
||||
String successFlagTrue = "导入成功";
|
||||
String successFlagFalse = "导入失败";
|
||||
//新增异步导入的日志
|
||||
CommonExportsInfo exportsLog = saveCommonExportsInfo(total);
|
||||
try {
|
||||
//根据手表编号反查设备信息以及根据工号反查用户信息
|
||||
List<SysUser> userList = sysBaseAPI.getUserListByWorkNoList(importExceldataList.stream().map(WatchDeviceExcelV2::getWorkNo).collect(Collectors.toList()));
|
||||
//查手表信息的同时查出本次导入的用户是否有已经绑定的手表, 用于后续的重复绑定校验
|
||||
LambdaQueryWrapper<WatchDevice> deviceWrapper = new LambdaQueryWrapper<>();
|
||||
deviceWrapper.in(WatchDevice::getWatchNo,importExceldataList.stream().map(WatchDeviceExcelV2::getWatchNo).collect(Collectors.toList()));
|
||||
if(ObjectUtil.isNotEmpty(userList)){
|
||||
deviceWrapper.or().in(WatchDevice::getBindUserId,userList.stream().map(SysUser::getId).collect(Collectors.toList()));
|
||||
}
|
||||
List<WatchDevice> watchDeviceList = watchDeviceService.list(deviceWrapper);
|
||||
Map<String,WatchDevice> deviceMap = watchDeviceList.stream()
|
||||
.collect(Collectors.toMap(WatchDevice::getWatchNo,watchDevice->watchDevice));
|
||||
//已经绑定过手表的用户信息
|
||||
Map<String,WatchDevice> userDeviceMap = watchDeviceList.stream()
|
||||
.filter(watchDevice -> ObjectUtil.isNotEmpty(watchDevice.getBindUserId()))
|
||||
.collect(Collectors.toMap(WatchDevice::getBindUserId,watchDevice->watchDevice));
|
||||
for (WatchDeviceExcelV2 excelVO : importExceldataList) {
|
||||
try {
|
||||
//处理时包含数据校验,包括手表编号校验, 员工工号校验, 重复绑定校验等
|
||||
WatchDevice device = deviceMap.get(excelVO.getWatchNo());
|
||||
SysUser user = userList.stream().filter(u -> u.getWorkNo().equals(excelVO.getWorkNo())).findFirst().orElse(null);
|
||||
if(device == null){
|
||||
excelVO.setSuccessFlag(successFlagFalse);
|
||||
excelVO.setRemark("手表编号不存在或未入库");
|
||||
continue;
|
||||
}
|
||||
if(user == null){
|
||||
excelVO.setSuccessFlag(successFlagFalse);
|
||||
excelVO.setRemark("员工工号不存在");
|
||||
continue;
|
||||
}
|
||||
//判断用户有没有绑定手表,一个员工不能同时绑定两个手表
|
||||
WatchDevice userDevice = userDeviceMap.get(user.getId());
|
||||
if(userDevice != null && !excelVO.getWatchNo().equals(userDevice.getWatchNo())){
|
||||
excelVO.setSuccessFlag(successFlagFalse);
|
||||
excelVO.setRemark("员工已绑定手表,手表编号: " + userDevice.getWatchNo());
|
||||
continue;
|
||||
}
|
||||
//判断手表是否是已经绑定状态,如果是已经绑定状态则解绑换人,如果未绑定则新增绑定记录
|
||||
if(ObjectUtil.isNotEmpty(device.getBindUserId())){
|
||||
if(!user.getId().equals(device.getBindUserId())){
|
||||
device = deviceUnbindAndUpdate(device,user,loginUser);
|
||||
userDeviceMap.put(user.getId(),device);
|
||||
excelVO.setRemark("更换手表绑定人员");
|
||||
}
|
||||
excelVO.setSuccessFlag(successFlagTrue);
|
||||
}else {
|
||||
device = insertDeviceBind(device,user,loginUser);
|
||||
userDeviceMap.put(user.getId(),device);
|
||||
excelVO.setSuccessFlag(successFlagTrue);
|
||||
}
|
||||
index ++ ;
|
||||
} catch (Exception e) {
|
||||
excelVO.setSuccessFlag(successFlagFalse);
|
||||
excelVO.setRemark("内部错误,请联系管理员");
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
//上传附带错误信息记录的文件
|
||||
String excelUrl = uploadBindDataExcel(importExceldataList,fileName);
|
||||
exportsLog.setExportUrl(excelUrl);
|
||||
//更新异步任务的状态,这里等所有的数据处理完之后只更新一次(没有必要处理一条更新一次)
|
||||
String msg = index != total ? "导入成功" + index + "条,导入失败" + (total - index) +"条" : total + "条数据导入完成";
|
||||
logErrorAndUpdateExportInfo(exportsLog,WATCH_IMPORT_BIND_FINISH,msg,index,total);
|
||||
} catch (Exception e) {
|
||||
//这里只为捕获前置处理的异常,具体某条数据的导入异常由内层的catch()捕获
|
||||
logErrorAndUpdateExportInfo(exportsLog, WATCH_IMPORT_BIND_ERRCODE, "系统内部错误,请联系管理员", index, total);
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private String uploadBindDataExcel(List<WatchDeviceExcelV2> importExceldataList,String fileName) {
|
||||
String url = null;
|
||||
try {
|
||||
//这里将收集了上传结果的数据重新生成一个新的excel文件上传
|
||||
ExportParams params = new ExportParams("设备绑定用户模板", "设备绑定用户模板");
|
||||
HSSFWorkbook workbook = (HSSFWorkbook) ExcelExportUtil.exportExcel(params, WatchDeviceExcelV2.class, importExceldataList);
|
||||
url = MyUploadUtil.upload(ExportUtils.workbookToInputStream(workbook), MyUploadUtil.IMPORT_BIZ, fileName + "");
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
private WatchDevice insertDeviceBind(WatchDevice device, SysUser user,LoginUser loginUser) {
|
||||
//修改设备绑定状态
|
||||
updateWatchDevice(device,user,loginUser);
|
||||
//新增设备绑定记录
|
||||
WatchBindHis watchBindHis = initWatchBindHis(device,user,loginUser);
|
||||
watchDeviceService.saveOrUpdate(device);
|
||||
watchBindHisService.save(watchBindHis);
|
||||
return device;
|
||||
}
|
||||
|
||||
private void updateWatchDevice(WatchDevice device,SysUser user,LoginUser loginUser){
|
||||
device.setBindUserId(user.getId());
|
||||
device.setBindDate(new Date());
|
||||
device.setUpdateDate(new Date());
|
||||
device.setUpdateBy(loginUser.getId());
|
||||
}
|
||||
|
||||
private WatchBindHis initWatchBindHis(WatchDevice device,SysUser user,LoginUser loginUser){
|
||||
WatchBindHis watchBindHis = new WatchBindHis();
|
||||
watchBindHis.setWatchNo(device.getWatchNo());
|
||||
watchBindHis.setBindDate(device.getBindDate());
|
||||
watchBindHis.setCreateDate(new Date());
|
||||
watchBindHis.setCreateBy(loginUser.getId());
|
||||
watchBindHis.setBindUserId(user.getId());
|
||||
if (user.getDepart()!=null && StrUtil.isNotBlank(user.getDepart().getOrgCode())){
|
||||
watchBindHis.setDeptId(user.getDepart().getId());
|
||||
watchBindHis.setOrgCode(user.getDepart().getOrgCode());
|
||||
}
|
||||
return watchBindHis;
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入更换手表绑定人员 ,先解绑之前的用户再绑定新的用户
|
||||
* @param device
|
||||
* @param user
|
||||
* @return
|
||||
*/
|
||||
public WatchDevice deviceUnbindAndUpdate(WatchDevice device,SysUser user,LoginUser loginUser) {
|
||||
//查询之前的绑定记录,并将更新解绑时间
|
||||
LambdaQueryWrapper<WatchBindHis> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(WatchBindHis::getWatchNo,device.getWatchNo());
|
||||
queryWrapper.isNull(WatchBindHis::getBindEndDate);
|
||||
queryWrapper.orderByDesc(WatchBindHis::getCreateDate);
|
||||
queryWrapper.last("limit 1");
|
||||
//解绑
|
||||
WatchBindHis updateHis = watchBindHisMapper.selectOne(queryWrapper);
|
||||
//修改绑定用户
|
||||
updateWatchDevice(device,user,loginUser);
|
||||
//新增设备绑定记录
|
||||
WatchBindHis watchBindHis = initWatchBindHis(device,user,loginUser);
|
||||
if(null != updateHis){
|
||||
updateHis.setBindEndDate(new Date());
|
||||
updateHis.setUpdateBy(loginUser.getId());
|
||||
updateHis.setUpdateDate(new Date());
|
||||
watchBindHisMapper.updateById(updateHis);
|
||||
}
|
||||
watchDeviceService.saveOrUpdate(device);
|
||||
watchBindHisService.save(watchBindHis);
|
||||
return device;
|
||||
}
|
||||
|
||||
private CommonExportsInfo saveCommonExportsInfo(int total) {
|
||||
CommonExportsInfo info = new CommonExportsInfo();
|
||||
info.setBatchNo(String.valueOf(System.currentTimeMillis()));
|
||||
info.setTaskCode(WATCH_IMPORT_BIND_CODE);
|
||||
info.setCreateBy(GlobalUtils.getLoginUser().getId());
|
||||
info.setHandleMsg("0/"+total);
|
||||
info.setCreateDate(new Date());
|
||||
info.setExportMsg("设备绑定导入");
|
||||
//数据导入中
|
||||
info.setExportStatus(WATCH_IMPORT_BIND_DOING);
|
||||
info.setHandleStartTime(new Date());
|
||||
return sysBaseAPI.updateExportsInfo(info);
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -494,6 +494,11 @@ public class WatchDeviceController extends JeecgController<WatchDevice, IWatchDe
|
||||
return watchDeviceService.importExcelBindData();
|
||||
}
|
||||
|
||||
@Operation(summary = "导入绑定数据(V2版本)", description = "导入绑定数据(20251222重构版本)")
|
||||
@RequestMapping(value = "/importExcelBindData/v2", consumes = "multipart/*", method = RequestMethod.POST, headers = "content-type=multipart/form-data")
|
||||
public Result<String> importExcelBindDataV2(@Parameter(description = "文件", required = true) MultipartFile file){
|
||||
return asyncImportService.importExcelBindDataV2(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已绑定员工id
|
||||
|
||||
Reference in New Issue
Block a user