|
@@ -1,10 +1,13 @@
|
|
package org.jeecg.modules.quartz.job;
|
|
package org.jeecg.modules.quartz.job;
|
|
|
|
|
|
|
|
|
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
import lombok.AllArgsConstructor;
|
|
import lombok.AllArgsConstructor;
|
|
|
|
+import lombok.Data;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.apache.commons.lang3.ObjectUtils;
|
|
import org.apache.commons.lang3.ObjectUtils;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
@@ -14,6 +17,9 @@ import org.jeecg.modules.quartz.utils.HolidayUtil;
|
|
import org.jeecg.modules.system.app.dto.TeachingDayDTO;
|
|
import org.jeecg.modules.system.app.dto.TeachingDayDTO;
|
|
import org.jeecg.modules.system.app.entity.*;
|
|
import org.jeecg.modules.system.app.entity.*;
|
|
import org.jeecg.modules.system.app.mapper.AppDeviceMapper;
|
|
import org.jeecg.modules.system.app.mapper.AppDeviceMapper;
|
|
|
|
+import org.jeecg.modules.system.app.mapper.AppIsinMapper;
|
|
|
|
+import org.jeecg.modules.system.app.mapper.AppOrderMapper;
|
|
|
|
+import org.jeecg.modules.system.app.mapper.AppOrderProInfoMapper;
|
|
import org.jeecg.modules.system.app.service.IAppSitePlaceService;
|
|
import org.jeecg.modules.system.app.service.IAppSitePlaceService;
|
|
import org.jeecg.modules.system.app.service.IAppSitePriceRulesService;
|
|
import org.jeecg.modules.system.app.service.IAppSitePriceRulesService;
|
|
import org.jeecg.modules.system.app.service.IAppSiteService;
|
|
import org.jeecg.modules.system.app.service.IAppSiteService;
|
|
@@ -29,8 +35,11 @@ import java.util.ArrayList;
|
|
import java.util.Date;
|
|
import java.util.Date;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
+import static com.alibaba.dashscope.utils.JsonUtils.gson;
|
|
import static org.jeecg.modules.hikiot.HikiotTool.deleteExpiredVisitors;
|
|
import static org.jeecg.modules.hikiot.HikiotTool.deleteExpiredVisitors;
|
|
|
|
+import static org.jeecg.modules.hikiot.HikiotTool.queryOpenDoorRecord;
|
|
|
|
|
|
/**
|
|
/**
|
|
* @author wzq
|
|
* @author wzq
|
|
@@ -53,6 +62,13 @@ public class OrTeachingJobService {
|
|
@Resource
|
|
@Resource
|
|
private AppDeviceMapper appDeviceMapper;
|
|
private AppDeviceMapper appDeviceMapper;
|
|
|
|
|
|
|
|
+ @Resource
|
|
|
|
+ private AppIsinMapper appIsinMapper;
|
|
|
|
+ @Resource
|
|
|
|
+ private AppOrderProInfoMapper appOrderProInfoMapper;
|
|
|
|
+ @Resource
|
|
|
|
+ private AppOrderMapper appOrderMapper;
|
|
|
|
+
|
|
@Scheduled(cron = "0 0 0 1 12 *")
|
|
@Scheduled(cron = "0 0 0 1 12 *")
|
|
@Transactional(rollbackFor = Exception.class)
|
|
@Transactional(rollbackFor = Exception.class)
|
|
public void execute() throws ParseException {
|
|
public void execute() throws ParseException {
|
|
@@ -168,6 +184,13 @@ public class OrTeachingJobService {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * @Author SheepHy
|
|
|
|
+ * @Description 删除过期用户
|
|
|
|
+ * @Date 17:43 2025/9/1
|
|
|
|
+ * @Param
|
|
|
|
+ * @return
|
|
|
|
+ **/
|
|
@Scheduled(cron = "0 0 1 * * ?")
|
|
@Scheduled(cron = "0 0 1 * * ?")
|
|
public void deleteExpiredVisitorsExecute(){
|
|
public void deleteExpiredVisitorsExecute(){
|
|
try {
|
|
try {
|
|
@@ -211,4 +234,160 @@ public class OrTeachingJobService {
|
|
log.error("获取设备列表失败", e);
|
|
log.error("获取设备列表失败", e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * @Author SheepHy
|
|
|
|
+ * @Description 同步开关门记录
|
|
|
|
+ * @Date 17:44 2025/9/1
|
|
|
|
+ * @Param
|
|
|
|
+ * @return
|
|
|
|
+ **/
|
|
|
|
+ @Scheduled(fixedDelay = 30000)
|
|
|
|
+ public void synchronousDoorOpeningAndClosingRecords(){
|
|
|
|
+ try {
|
|
|
|
+ List<DoorRecordDTO> allRecords = fetchAllDoorRecords();
|
|
|
|
+ List<ExtractedData> extractedData = extractRequiredData(allRecords);
|
|
|
|
+
|
|
|
|
+ extractedData.forEach(data -> {
|
|
|
|
+ log.info("提取数据: {}", data);
|
|
|
|
+ AppIsin appIsin = appIsinMapper.selectOne(Wrappers.<AppIsin>lambdaQuery().eq(AppIsin::getOrderProInfoId, data.getEmployeeNo()));
|
|
|
|
+ if(null != appIsin){
|
|
|
|
+ appIsin.setUseTime(DateUtils.str2Date(data.getGmtCreate(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")));
|
|
|
|
+ appIsin.setUpdateTime(DateUtils.str2Date(data.getGmtCreate(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")));
|
|
|
|
+ appIsin.setIsinStatus(1);
|
|
|
|
+ appIsin.setUseImage(data.getPortraitUrl());
|
|
|
|
+ appIsinMapper.updateById(appIsin);
|
|
|
|
+ AppOrderProInfo orderProInfo = appOrderProInfoMapper.selectById(appIsin.getOrderProInfoId());
|
|
|
|
+ orderProInfo.setOrderStatus(2);
|
|
|
|
+ appOrderProInfoMapper.updateById(orderProInfo);
|
|
|
|
+ // 查询当前订单的所有 AppOrderProInfo 记录
|
|
|
|
+ List<AppOrderProInfo> orderProInfoList = appOrderProInfoMapper.selectList(
|
|
|
|
+ Wrappers.<AppOrderProInfo>lambdaQuery()
|
|
|
|
+ .eq(AppOrderProInfo::getOrderCode, orderProInfo.getOrderCode())
|
|
|
|
+ );
|
|
|
|
+ // 判断所有子订单的 orderStatus 是否都为 2
|
|
|
|
+ if (orderProInfoList != null && !orderProInfoList.isEmpty() &&
|
|
|
|
+ orderProInfoList.stream().allMatch(opi -> opi.getOrderStatus() == 2)) {
|
|
|
|
+ // 查询主订单
|
|
|
|
+ AppOrder appOrder = appOrderMapper.selectOne(
|
|
|
|
+ Wrappers.<AppOrder>lambdaQuery()
|
|
|
|
+ .eq(AppOrder::getOrderCode, orderProInfo.getOrderCode())
|
|
|
|
+ );
|
|
|
|
+ if (appOrder != null) {
|
|
|
|
+ // 更新主订单状态为 2
|
|
|
|
+ appOrder.setOrderStatus(2);
|
|
|
|
+ appOrderMapper.updateById(appOrder);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("处理门禁记录失败", e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 分页获取所有门禁记录
|
|
|
|
+ */
|
|
|
|
+ private List<DoorRecordDTO> fetchAllDoorRecords() {
|
|
|
|
+ List<DoorRecordDTO> allRecords = new ArrayList<>();
|
|
|
|
+ int pageNum = 1;
|
|
|
|
+ int pageSize = 10000;
|
|
|
|
+ AppIsin appIsin = appIsinMapper.selectOne(Wrappers.<AppIsin>lambdaQuery()
|
|
|
|
+ .eq(AppIsin::getIsinStatus, 0)
|
|
|
|
+ .eq(AppIsin::getOriginId, null)
|
|
|
|
+ .orderByDesc(AppIsin::getUpdateTime)
|
|
|
|
+ .last("limit 1"));
|
|
|
|
+ try {
|
|
|
|
+ while (true) {
|
|
|
|
+ JSONObject response;
|
|
|
|
+ if(null != appIsin && null != appIsin.getUpdateTime()){
|
|
|
|
+ response = gson.fromJson(queryOpenDoorRecord(pageNum, pageSize, appIsin.getUpdateTime()), JSONObject.class);
|
|
|
|
+ }else {
|
|
|
|
+ response = gson.fromJson(queryOpenDoorRecord(pageNum, pageSize,null), JSONObject.class);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 验证响应有效性
|
|
|
|
+ if (!isValidResponse(response)) {
|
|
|
|
+ log.warn("无效的响应数据,停止获取");
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ // 提取当前页数据
|
|
|
|
+ JSONArray dataList = response.getJSONArray("data");
|
|
|
|
+ List<DoorRecordDTO> currentRecords = JSON.parseArray(
|
|
|
|
+ dataList.toJSONString(),
|
|
|
|
+ DoorRecordDTO.class
|
|
|
|
+ );
|
|
|
|
+ allRecords.addAll(currentRecords);
|
|
|
|
+
|
|
|
|
+ // 分页判断
|
|
|
|
+ int totalCount = response.getIntValue("count");
|
|
|
|
+ if (pageNum * pageSize >= totalCount) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ pageNum++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("分页获取门禁记录失败", e);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return allRecords;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 提取和过滤数据
|
|
|
|
+ */
|
|
|
|
+ private List<ExtractedData> extractRequiredData(List<DoorRecordDTO> records) {
|
|
|
|
+ List<ExtractedData> result = new ArrayList<>();
|
|
|
|
+
|
|
|
|
+ if (records != null && !records.isEmpty()) {
|
|
|
|
+ result = records.stream()
|
|
|
|
+ .filter(record -> "ACE-5-75".equals(record.getSecMsgCode()))
|
|
|
|
+ .map(record -> new ExtractedData(
|
|
|
|
+ record.getEmployeeNo(),
|
|
|
|
+ record.getAuthResultMsg(),
|
|
|
|
+ record.getGmtCreate(),
|
|
|
|
+ record.getPortraitUrl() // 可能为null,不影响
|
|
|
|
+ ))
|
|
|
|
+ .filter(data -> data.getEmployeeNo() != null) // 可选:排除无效数据
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 验证响应是否有效
|
|
|
|
+ */
|
|
|
|
+ private boolean isValidResponse(JSONObject response) {
|
|
|
|
+ if (response == null) return false;
|
|
|
|
+ if (response.getIntValue("code") != 0) return false;
|
|
|
|
+ return response.containsKey("data");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * DTO类 - 原始门禁记录
|
|
|
|
+ */
|
|
|
|
+ @Data
|
|
|
|
+ private static class DoorRecordDTO {
|
|
|
|
+ private String employeeNo;
|
|
|
|
+ private String authResultMsg;
|
|
|
|
+ private String gmtCreate;
|
|
|
|
+ private String portraitUrl;
|
|
|
|
+ private String secMsgCode;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * DTO类 - 提取结果
|
|
|
|
+ */
|
|
|
|
+ @Data
|
|
|
|
+ @AllArgsConstructor
|
|
|
|
+ private static class ExtractedData {
|
|
|
|
+ private String employeeNo;
|
|
|
|
+ private String authResultMsg;
|
|
|
|
+ private String gmtCreate;
|
|
|
|
+ private String portraitUrl;
|
|
|
|
+ }
|
|
}
|
|
}
|