|
@@ -0,0 +1,388 @@
|
|
|
|
+package cn.com.ctop.oa.modules.service.impl;
|
|
|
|
+
|
|
|
|
+import cn.com.ctop.common.module.utils.Check;
|
|
|
|
+import cn.com.ctop.common.module.utils.HttpUtils;
|
|
|
|
+import cn.com.ctop.oa.modules.constant.QYWxConstant;
|
|
|
|
+import cn.com.ctop.oa.modules.entity.WechatAttendance;
|
|
|
|
+import cn.com.ctop.oa.modules.entity.WechatCheckinData;
|
|
|
|
+import cn.com.ctop.oa.modules.entity.WechatNoList;
|
|
|
|
+import cn.com.ctop.oa.modules.enums.SpNoEnum;
|
|
|
|
+import cn.com.ctop.oa.modules.mapper.WechatCheckinDataMapper;
|
|
|
|
+import cn.com.ctop.oa.modules.mapper.WechatNoListMapper;
|
|
|
|
+import cn.com.ctop.oa.modules.service.IWechatNoListService;
|
|
|
|
+import cn.com.ctop.oa.modules.service.IWechatTokenService;
|
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
|
+import com.github.pagehelper.PageHelper;
|
|
|
|
+import com.github.pagehelper.PageInfo;
|
|
|
|
+import com.xxl.job.core.enums.NoEn;
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
+import org.jeecg.common.util.DateUtils;
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
+
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
+import java.util.HashMap;
|
|
|
|
+import java.util.List;
|
|
|
|
+import java.util.Map;
|
|
|
|
+
|
|
|
|
+import static org.jeecg.common.constant.GeneralConstant.*;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 审批信息
|
|
|
|
+ *
|
|
|
|
+ * @author jeecg-boot
|
|
|
|
+ * @version V1.0
|
|
|
|
+ * @date 2020-09-23
|
|
|
|
+ */
|
|
|
|
+@Service
|
|
|
|
+@Slf4j
|
|
|
|
+public class WechatNoListServiceImpl extends ServiceImpl<WechatNoListMapper, WechatNoList> implements IWechatNoListService {
|
|
|
|
+ @Autowired
|
|
|
|
+ private IWechatTokenService tokenService;
|
|
|
|
+ @Autowired
|
|
|
|
+ private WechatNoListMapper wechatNoListMapper;
|
|
|
|
+ @Autowired
|
|
|
|
+ private WechatCheckinDataMapper wechatCheckinDataMapper;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取审批token
|
|
|
|
+ *
|
|
|
|
+ * @return java.lang.String
|
|
|
|
+ * @throws
|
|
|
|
+ * @author ZHAOXA
|
|
|
|
+ * @Param []
|
|
|
|
+ */
|
|
|
|
+ private String getToken() throws Exception {
|
|
|
|
+ Map<String, Object> approvaAccessToken = tokenService.getApprovaAccessToken();
|
|
|
|
+ if ((Integer) approvaAccessToken.get("code") != 0) {
|
|
|
|
+ log.error("企业微信获取token失败,返回信息:{}", approvaAccessToken.get("message"));
|
|
|
|
+ throw new Exception("企业微信获取token失败");
|
|
|
|
+ }
|
|
|
|
+ return approvaAccessToken.get("accessToken").toString();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public JSONObject getNoList(Integer page, String starttime, String endtime) {
|
|
|
|
+ try {
|
|
|
|
+ JSONObject params = new JSONObject();
|
|
|
|
+ params.put("starttime", starttime);
|
|
|
|
+ params.put("endtime", endtime);
|
|
|
|
+ params.put("cursor", page);
|
|
|
|
+ params.put("size", 100);
|
|
|
|
+ StringBuffer buf = new StringBuffer();
|
|
|
|
+ //批量获取审批单号 URL
|
|
|
|
+ buf.append(QYWxConstant.APP_ROVAL_INFO).append("?access_token=").append(getToken());
|
|
|
|
+ System.err.println(buf.toString());
|
|
|
|
+ String resultStr = HttpUtils.httpPostRequestTest(buf.toString(), params.toJSONString(), null);
|
|
|
|
+ JSONObject resultJson = JSONObject.parseObject(resultStr);
|
|
|
|
+ System.err.println(resultJson);
|
|
|
|
+ Integer errcode = resultJson.getInteger("errcode");
|
|
|
|
+ if (errcode == 0) {
|
|
|
|
+ return resultJson;
|
|
|
|
+ } else {
|
|
|
|
+ throw new Exception("批量获取审批单号");
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("批量获取审批单号异常", e);
|
|
|
|
+ }
|
|
|
|
+ return new JSONObject();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //递归获取审批数据
|
|
|
|
+ private JSONArray getAllNoList(Integer page, JSONArray spNoList, String starttime, String endtime) {
|
|
|
|
+ JSONObject data = getNoList(page, starttime, endtime);
|
|
|
|
+ spNoList.addAll(data.getJSONArray("sp_no_list"));
|
|
|
|
+ Integer nextCursor = data.getInteger("next_cursor");
|
|
|
|
+ if (!Check.isNull(nextCursor)) {
|
|
|
|
+ return getAllNoList(nextCursor, spNoList, starttime, endtime);
|
|
|
|
+ }
|
|
|
|
+ return spNoList;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void getNoDateByNo(String starttime, String endtime) {
|
|
|
|
+ Map<String, Object> returnMap = new HashMap<>();
|
|
|
|
+ try {
|
|
|
|
+ Integer page = 0;
|
|
|
|
+ JSONArray noList = getAllNoList(page, new JSONArray(), starttime, endtime);
|
|
|
|
+ boolean sleep = false;
|
|
|
|
+ if (noList.size() > 600) {
|
|
|
|
+ sleep = true;
|
|
|
|
+ }
|
|
|
|
+ if (!Check.isNull(noList)) {
|
|
|
|
+ StringBuffer buf = new StringBuffer();
|
|
|
|
+ //获取审批申请详情 URL;
|
|
|
|
+ buf.append(QYWxConstant.APP_ROVAL_DETAIL).append("?access_token=").append(getToken());
|
|
|
|
+ String userId = null;
|
|
|
|
+ Map<String, String> parameterMap = null;
|
|
|
|
+ for (Object spNo : noList) {
|
|
|
|
+ parameterMap = new HashMap<>();
|
|
|
|
+ //接口频率限制 600次/分钟
|
|
|
|
+ if (sleep) {
|
|
|
|
+ Thread.sleep(100);
|
|
|
|
+ }
|
|
|
|
+ JSONObject params = new JSONObject();
|
|
|
|
+ params.put("sp_no", spNo);
|
|
|
|
+ String resultStr = HttpUtils.httpPostRequestTest(buf.toString(), params.toJSONString(), null);
|
|
|
|
+ JSONObject resultJson = JSONObject.parseObject(resultStr);
|
|
|
|
+ Integer errcode = resultJson.getInteger("errcode");
|
|
|
|
+ if (errcode == 0) {
|
|
|
|
+ JSONObject info = resultJson.getJSONObject("info");
|
|
|
|
+ String spStatus = info.getString("sp_status");
|
|
|
|
+ String spName = info.getString("sp_name");
|
|
|
|
+ /**申请单状态:1-审批中;2-已通过,只记录这两种状态数据
|
|
|
|
+ * 而且只记录请假、打卡补卡类型
|
|
|
|
+ **/
|
|
|
|
+ boolean statusisOK = "2".equals(spStatus) || "1".equals(spStatus);
|
|
|
|
+ boolean typeisOK = spName.contains("打卡补卡") || spName.contains("请假") || spName.contains("外出") || spName.contains("出差");
|
|
|
|
+ if (statusisOK && typeisOK) {
|
|
|
|
+ JSONObject applyer = info.getJSONObject("applyer");
|
|
|
|
+ if (!Check.isNull(applyer)) {
|
|
|
|
+ userId = applyer.getString("userid");
|
|
|
|
+ if ("LiuJing".equals(userId)) {
|
|
|
|
+ System.out.println(info);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //审批申请数据
|
|
|
|
+ JSONObject applyData = info.getJSONObject("apply_data");
|
|
|
|
+ //获取审批状态数据
|
|
|
|
+ getParameterMap(applyData, parameterMap);
|
|
|
|
+ WechatNoList noEntity = new WechatNoList();
|
|
|
|
+ noEntity.setUserId(userId);
|
|
|
|
+ noEntity.setSpNo(spNo.toString());
|
|
|
|
+ noEntity.setStatus(spStatus);
|
|
|
|
+ if (!Check.isNull(parameterMap.get("newBegin"))) {
|
|
|
|
+ noEntity.setNewBegin(DateUtils.stampToTime(Long.valueOf(parameterMap.get("newBegin"))));
|
|
|
|
+ }
|
|
|
|
+ if (!Check.isNull(parameterMap.get("newEnd"))) {
|
|
|
|
+ noEntity.setNewEnd(DateUtils.stampToTime(Long.valueOf(parameterMap.get("newEnd"))));
|
|
|
|
+ }
|
|
|
|
+ noEntity.setType(parameterMap.get(TYPE));
|
|
|
|
+ noEntity.setNewDuration(parameterMap.get("newDuration"));
|
|
|
|
+ wechatNoListMapper.insert(noEntity);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ returnMap.put("code", -1);
|
|
|
|
+ returnMap.put("message", "系统错误");
|
|
|
|
+ log.error("审批异常", e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取审批状态数据
|
|
|
|
+ *
|
|
|
|
+ * @return void
|
|
|
|
+ * @throws
|
|
|
|
+ * @author ZHAOXA
|
|
|
|
+ * @Param [applyData, parameterMap]
|
|
|
|
+ */
|
|
|
|
+ private void getParameterMap(JSONObject applyData, Map<String, String> parameterMap) {
|
|
|
|
+ String control = null;
|
|
|
|
+ if (!Check.isNull(applyData)) {
|
|
|
|
+ //审批申请详情,由多个表单控件及其内容组成
|
|
|
|
+ JSONArray contents = applyData.getJSONArray("contents");
|
|
|
|
+ if (!Check.isNull(contents)) {
|
|
|
|
+ for (int i = 0; i < contents.size(); i++) {
|
|
|
|
+ //获取content 对象数据
|
|
|
|
+ JSONObject contentEntity = contents.getJSONObject(i);
|
|
|
|
+ if (!Check.isNull(contentEntity)) {
|
|
|
|
+ control = contentEntity.getString("control");
|
|
|
|
+ //如果补卡组件为PunchCorrection,直接判断为补卡
|
|
|
|
+ if (SpNoEnum.control3.getCode().equals(control)) {
|
|
|
|
+ JSONObject value = contentEntity.getJSONObject(VALUE);
|
|
|
|
+ if (!Check.isNull(value)) {
|
|
|
|
+ JSONObject punch = value.getJSONObject("punch_correction");
|
|
|
|
+ if (!Check.isNull(punch)) {
|
|
|
|
+ parameterMap.put(TYPE, SpNoEnum.type2.getName());
|
|
|
|
+ parameterMap.put("newBegin", punch.getString("time"));
|
|
|
|
+ parameterMap.put("newEnd", punch.getString("time"));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //假勤组件-请假组件 Vacation
|
|
|
|
+ } else if (SpNoEnum.control2.getCode().equals(control)) {
|
|
|
|
+ JSONObject value = contentEntity.getJSONObject(VALUE);
|
|
|
|
+ if (!Check.isNull(value)) {
|
|
|
|
+ JSONObject vacation = value.getJSONObject("vacation");
|
|
|
|
+ if (!Check.isNull(vacation)) {
|
|
|
|
+ JSONObject selector = vacation.getJSONObject("selector");
|
|
|
|
+ if (!Check.isNull(selector)) {
|
|
|
|
+ getVacation(selector, parameterMap);
|
|
|
|
+ }
|
|
|
|
+ JSONObject attendance = vacation.getJSONObject("attendance");
|
|
|
|
+ if (!Check.isNull(attendance)) {
|
|
|
|
+ getTimeData(attendance, parameterMap);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //假勤组件-出差/外出/加班组件Attendance
|
|
|
|
+ } else if (SpNoEnum.control1.getCode().equals(control)) {
|
|
|
|
+ JSONObject value = contentEntity.getJSONObject(VALUE);
|
|
|
|
+ if (!Check.isNull(value)) {
|
|
|
|
+ JSONObject attendance = value.getJSONObject("attendance");
|
|
|
|
+ if (!Check.isNull(attendance)) {
|
|
|
|
+ getTimeData(attendance, parameterMap);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取组件中的假勤类型,假勤开始、结束时间以及时长。
|
|
|
|
+ *
|
|
|
|
+ * @return void
|
|
|
|
+ * @throws
|
|
|
|
+ * @author ZHAOXA
|
|
|
|
+ * @Param [attendance, parameterMap]
|
|
|
|
+ */
|
|
|
|
+ private void getTimeData(JSONObject attendance, Map<String, String> parameterMap) {
|
|
|
|
+ String type = attendance.getString(TYPE);
|
|
|
|
+ //假勤类型,排除类型为1的请假,因为有具体的请假类型,例如:年假,事假等具体类型
|
|
|
|
+ if (!NoEn.NO1.valueStr().equals(type)) {
|
|
|
|
+ parameterMap.put(TYPE, SpNoEnum.getSpNoEnum(type).getName());
|
|
|
|
+ }
|
|
|
|
+ JSONObject dateRange = attendance.getJSONObject("date_range");
|
|
|
|
+ if (!Check.isNull(dateRange)) {
|
|
|
|
+ parameterMap.put("newBegin", dateRange.getString("new_begin"));
|
|
|
|
+ parameterMap.put("newEnd", dateRange.getString("new_end"));
|
|
|
|
+ BigDecimal duration = dateRange.getBigDecimal("new_duration");
|
|
|
|
+ if (!Check.isNull(duration)) {
|
|
|
|
+ //除以3600,取小时数
|
|
|
|
+ BigDecimal second = new BigDecimal(3600);
|
|
|
|
+ parameterMap.put("newDuration", String.valueOf(duration.divide(second, 1, 4)));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取假期类型
|
|
|
|
+ *
|
|
|
|
+ * @param
|
|
|
|
+ * @return void
|
|
|
|
+ * @throws
|
|
|
|
+ * @author ZHAOXA
|
|
|
|
+ */
|
|
|
|
+ private void getVacation(JSONObject selector, Map<String, String> parameterMap) {
|
|
|
|
+ JSONArray options = selector.getJSONArray("options");
|
|
|
|
+ if (!Check.isNull(options)) {
|
|
|
|
+ for (int j = 0; j < options.size(); j++) {
|
|
|
|
+ JSONObject option = options.getJSONObject(j);
|
|
|
|
+ JSONArray values = option.getJSONArray(VALUE);
|
|
|
|
+ if (!Check.isNull(values)) {
|
|
|
|
+ for (int k = 0; k < values.size(); k++) {
|
|
|
|
+ JSONObject val = values.getJSONObject(k);
|
|
|
|
+ parameterMap.put(TYPE, val.getString("text"));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public List<WechatAttendance> queryAttendanceData(Map<String, Object> paramsMap) {
|
|
|
|
+ finishingTime(paramsMap);
|
|
|
|
+ List<WechatAttendance> list = wechatNoListMapper.queryAttendanceData(paramsMap);
|
|
|
|
+ if (!Check.isNull(list)) {
|
|
|
|
+ checkOverTimeData(list);
|
|
|
|
+ }
|
|
|
|
+ return list;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 整理时间
|
|
|
|
+ *
|
|
|
|
+ * @param
|
|
|
|
+ * @return void
|
|
|
|
+ * @throws
|
|
|
|
+ * @author ZHAOXA
|
|
|
|
+ */
|
|
|
|
+ private void finishingTime(Map<String, Object> paramsMap) {
|
|
|
|
+ String startTime = (String) paramsMap.get(START_TIME);
|
|
|
|
+ if (!Check.isNull(startTime)) {
|
|
|
|
+ startTime += DAY_BEGIN;
|
|
|
|
+ paramsMap.put(START_TIME, startTime);
|
|
|
|
+ }
|
|
|
|
+ String stopTime = (String) paramsMap.get(STOP_TIME);
|
|
|
|
+ if (!Check.isNull(stopTime)) {
|
|
|
|
+ stopTime += DAY_END;
|
|
|
|
+ paramsMap.put(STOP_TIME, stopTime);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public List<WechatAttendance> queryOverTimeData(Map<String, Object> paramsMap) {
|
|
|
|
+ finishingTime(paramsMap);
|
|
|
|
+ return wechatNoListMapper.queryOverTimeData(paramsMap);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public PageInfo<WechatAttendance> selectNoListPage(Map<String, Object> paramsMap) {
|
|
|
|
+ finishingTime(paramsMap);
|
|
|
|
+ Integer pageNo = (Integer) paramsMap.get(PAGE_NO);
|
|
|
|
+ if (null == pageNo || pageNo == 0) {
|
|
|
|
+ pageNo = NoEn.NO1.valueInt();
|
|
|
|
+ }
|
|
|
|
+ Integer pageSize = (Integer) paramsMap.get(PAGE_SIZE);
|
|
|
|
+ if (null == pageSize || pageSize == 0) {
|
|
|
|
+ pageSize = NoEn.NO10.valueInt();
|
|
|
|
+ }
|
|
|
|
+ PageHelper.startPage(pageNo, pageSize);
|
|
|
|
+ List<WechatAttendance> list = wechatNoListMapper.queryAttendanceData(paramsMap);
|
|
|
|
+ if (!Check.isNull(list)) {
|
|
|
|
+ checkOverTimeData(list);
|
|
|
|
+ }
|
|
|
|
+ return new PageInfo<>(list);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 筛选10:30以后打卡的迟到数据,判断前一天是否加班,更新迟到时长
|
|
|
|
+ *
|
|
|
|
+ * @param
|
|
|
|
+ * @return void
|
|
|
|
+ * @throws
|
|
|
|
+ * @author ZHAOXA
|
|
|
|
+ */
|
|
|
|
+ private void checkOverTimeData(List<WechatAttendance> list) {
|
|
|
|
+ for (WechatAttendance attendance : list) {
|
|
|
|
+ if ("迟到".equals(attendance.getType())) {
|
|
|
|
+ Integer dur = Integer.valueOf(attendance.getStateDuration().replace(" min", ""));
|
|
|
|
+ if (dur - 60 >= 0) {
|
|
|
|
+ String checkinDate = attendance.getCheckinDate();
|
|
|
|
+ String lastDay = DateUtils.getLastDay(checkinDate);
|
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
|
+ map.put("userId", attendance.getUserId());
|
|
|
|
+ map.put("checkinDate", lastDay);
|
|
|
|
+ map.put("checkinType", "下班打卡");
|
|
|
|
+ WechatCheckinData data = wechatCheckinDataMapper.queryEntityByMap(map);
|
|
|
|
+ if (!Check.isNull(data) && 1 == data.getOvertimeOrNot()) {
|
|
|
|
+ attendance.setStateDuration((dur - 60) + " min");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public PageInfo<WechatAttendance> selectOverTimePage(Map<String, Object> paramsMap) {
|
|
|
|
+ finishingTime(paramsMap);
|
|
|
|
+ Integer pageNo = (Integer) paramsMap.get("pageNo");
|
|
|
|
+ if (null == pageNo || pageNo == 0) {
|
|
|
|
+ pageNo = 1;
|
|
|
|
+ }
|
|
|
|
+ Integer pageSize = (Integer) paramsMap.get("pageSize");
|
|
|
|
+ if (null == pageSize || pageSize == 0) {
|
|
|
|
+ pageSize = 10;
|
|
|
|
+ }
|
|
|
|
+ PageHelper.startPage(pageNo, pageSize);
|
|
|
|
+ List<WechatAttendance> list = wechatNoListMapper.queryOverTimeData(paramsMap);
|
|
|
|
+ return new PageInfo<>(list);
|
|
|
|
+ }
|
|
|
|
+}
|