|
@@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONArray;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
|
+import com.google.gson.JsonArray;
|
|
import com.google.gson.JsonObject;
|
|
import com.google.gson.JsonObject;
|
|
import com.management.platform.controller.WeiXinCorpController;
|
|
import com.management.platform.controller.WeiXinCorpController;
|
|
import com.management.platform.entity.*;
|
|
import com.management.platform.entity.*;
|
|
@@ -14,6 +15,7 @@ import com.management.platform.util.*;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.apache.http.client.utils.HttpClientUtils;
|
|
import org.apache.http.client.utils.HttpClientUtils;
|
|
|
|
+import org.apache.tomcat.jni.Local;
|
|
import org.json.HTTP;
|
|
import org.json.HTTP;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
@@ -22,6 +24,7 @@ import org.springframework.http.*;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.util.LinkedMultiValueMap;
|
|
import org.springframework.util.LinkedMultiValueMap;
|
|
import org.springframework.util.MultiValueMap;
|
|
import org.springframework.util.MultiValueMap;
|
|
|
|
+import org.springframework.util.unit.DataUnit;
|
|
import org.springframework.web.client.RestTemplate;
|
|
import org.springframework.web.client.RestTemplate;
|
|
import org.springframework.web.util.UriComponentsBuilder;
|
|
import org.springframework.web.util.UriComponentsBuilder;
|
|
import sun.net.www.http.HttpClient;
|
|
import sun.net.www.http.HttpClient;
|
|
@@ -29,6 +32,7 @@ import sun.net.www.http.HttpClient;
|
|
import javax.annotation.Resource;
|
|
import javax.annotation.Resource;
|
|
import java.io.*;
|
|
import java.io.*;
|
|
import java.lang.reflect.Array;
|
|
import java.lang.reflect.Array;
|
|
|
|
+import java.math.BigDecimal;
|
|
import java.net.URI;
|
|
import java.net.URI;
|
|
import java.text.SimpleDateFormat;
|
|
import java.text.SimpleDateFormat;
|
|
import java.time.*;
|
|
import java.time.*;
|
|
@@ -55,6 +59,10 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
|
|
|
|
|
|
public static final String GET_CHECKIN_DAYDATA = "https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckin_daydata?access_token=ACCESS_TOKEN";
|
|
public static final String GET_CHECKIN_DAYDATA = "https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckin_daydata?access_token=ACCESS_TOKEN";
|
|
|
|
|
|
|
|
+ public static final String GET_CHECKIN_DATA = "https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckindata?access_token=ACCESS_TOKEN";
|
|
|
|
+
|
|
|
|
+ public static final String GET_CHECKIN_OPTION = "https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckinoption?access_token=ACCESS_TOKEN";
|
|
|
|
+
|
|
|
|
|
|
@Value("${suitId}")
|
|
@Value("${suitId}")
|
|
private String suitId;
|
|
private String suitId;
|
|
@@ -452,6 +460,153 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
|
|
return msg;
|
|
return msg;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
+ public HttpRespMsg getUserPunchRecord(int companyId, String userId, LocalDateTime startDateTime, LocalDateTime endDateTime, boolean showLog) {
|
|
|
|
+ HttpRespMsg msg = new HttpRespMsg();
|
|
|
|
+ WxCorpInfo corpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", companyId));
|
|
|
|
+ if (corpInfo == null) {
|
|
|
|
+ //msg.setError("该企业未对接企业微信");
|
|
|
|
+ msg.setError(MessageUtils.message("wx.dockError"));
|
|
|
|
+ return msg;
|
|
|
|
+ }
|
|
|
|
+ String url = null;
|
|
|
|
+ try {
|
|
|
|
+ startDateTime = startDateTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
|
|
|
|
+ long startTime = startDateTime.toEpochSecond(ZoneOffset.of("+8"));
|
|
|
|
+ endDateTime = endDateTime.withHour(23).withMinute(59).withSecond(0).withNano(0);
|
|
|
|
+ long endTime = endDateTime.toEpochSecond(ZoneOffset.of("+8"));
|
|
|
|
+ System.out.println("startTime=" + startTime + ",endTime=" + endTime);
|
|
|
|
+
|
|
|
|
+ int batchCount = 1;
|
|
|
|
+ int batchSize = 100;
|
|
|
|
+ int totalLength = 1;
|
|
|
|
+ List<String> corpwxUserIds = new ArrayList<>();
|
|
|
|
+ if (userId == null) {
|
|
|
|
+ //获取企业下的全部员工
|
|
|
|
+ List<User> users = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId).isNotNull("corpwx_userid").eq("is_active", 1));
|
|
|
|
+ System.out.println("获取考勤记录users size==" + users.size());
|
|
|
|
+ corpwxUserIds = users.stream().map(User::getCorpwxUserid).collect(Collectors.toList());
|
|
|
|
+ totalLength = corpwxUserIds.size();
|
|
|
|
+ batchCount = totalLength / batchSize + (totalLength % batchSize == 0 ? 0 : 1);
|
|
|
|
+ } else {
|
|
|
|
+ //指定获取员工
|
|
|
|
+ User user = userMapper.selectById(userId);
|
|
|
|
+ corpwxUserIds.add(user.getCorpwxUserid());
|
|
|
|
+ System.out.println("获取corpwxuserid==" + user.getCorpwxUserid() + "的考勤记录");
|
|
|
|
+ }
|
|
|
|
+ //按批调用
|
|
|
|
+ for (int i = 0; i < batchCount; i++) {
|
|
|
|
+ int fromIndex = i * batchSize;
|
|
|
|
+ int toIndex = (i + 1) * batchSize;
|
|
|
|
+ if (toIndex > totalLength) toIndex = totalLength;
|
|
|
|
+ Object[] objects = corpwxUserIds.subList(fromIndex, toIndex).toArray(new String[0]);
|
|
|
|
+ reqPunchRecord(corpInfo, startTime, endTime, objects, showLog);
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception exception) {
|
|
|
|
+ exception.printStackTrace();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return msg;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public void reqPunchRecord(WxCorpInfo corpInfo, long startTime, long endTime, Object[] objects, boolean showLog)throws Exception {
|
|
|
|
+ DateTimeFormatter mdFormat = DateTimeFormatter.ofPattern("yyyy/M/d");
|
|
|
|
+ LocalDateTime needDataTime = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
|
|
|
|
+ long dataTime = needDataTime.toEpochSecond(ZoneOffset.of("+8"));
|
|
|
|
+ String checkinOption = getCheckinOption(corpInfo, dataTime, objects);
|
|
|
|
+ JSONObject optionObject = JSONObject.parseObject(checkinOption);
|
|
|
|
+ JSONArray optionDatas= optionObject.getJSONArray("info");
|
|
|
|
+ String url = GET_CHECKIN_DATA.replace("ACCESS_TOKEN", getCorpAccessToken(corpInfo));
|
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
|
+ headers.setContentType(MediaType.APPLICATION_JSON);
|
|
|
|
+ System.out.println("" + objects.toString());
|
|
|
|
+ JSONObject reqParam = new JSONObject();
|
|
|
|
+ reqParam.put("starttime", startTime);
|
|
|
|
+ reqParam.put("endtime", endTime);
|
|
|
|
+ reqParam.put("useridlist", objects);
|
|
|
|
+ reqParam.put("opencheckindatatype", 3);
|
|
|
|
+ HttpEntity<String> requestEntity = new HttpEntity<String>(reqParam.toJSONString(), headers);
|
|
|
|
+ ResponseEntity<String> responseEntity = this.restTemplate.exchange(url,
|
|
|
|
+ HttpMethod.POST, requestEntity, String.class);
|
|
|
|
+
|
|
|
|
+ if (responseEntity.getStatusCode() == HttpStatus.OK) {
|
|
|
|
+ String resp = responseEntity.getBody();
|
|
|
|
+ if (showLog) System.out.println(resp);
|
|
|
|
+ JSONObject json = JSONObject.parseObject(resp);
|
|
|
|
+ DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
|
|
|
+ if (json.getIntValue("errcode") == 0) {
|
|
|
|
+ JSONArray checkindata = json.getJSONArray("checkindata");
|
|
|
|
+ System.out.println(checkindata);
|
|
|
|
+ for (int i = 0; i < objects.length; i++) {
|
|
|
|
+ List<Integer> upList=new ArrayList<>();
|
|
|
|
+ List<Integer> downList=new ArrayList<>();
|
|
|
|
+ for (int j = 0; j < checkindata.size(); j++) {
|
|
|
|
+ JSONObject jsonObject = checkindata.getJSONObject(j);
|
|
|
|
+ if (jsonObject.get("userid").equals(objects[i])) {
|
|
|
|
+ //todo: 获取最早上班打卡时间以及最晚下班打卡时间
|
|
|
|
+ Integer time = (Integer) jsonObject.get("checkin_time");
|
|
|
|
+ if (jsonObject.get("checkin_type").equals("上班打卡")) {
|
|
|
|
+ upList.add(time);
|
|
|
|
+ } else if(jsonObject.get("checkin_type").equals("下班打卡")) downList.add(time);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ double restTime = 0.0;//小时为单位
|
|
|
|
+ for (int k = 0; k < optionDatas.size(); k++) {
|
|
|
|
+ if(optionDatas.getJSONObject(k).get("userid").equals(objects[i])){
|
|
|
|
+ JSONObject group = optionDatas.getJSONObject(k).getJSONObject("group");
|
|
|
|
+ JSONArray workRules = group.getJSONArray("checkindate").getJSONObject(0).getJSONArray("checkintime");
|
|
|
|
+ if (workRules.size() <= 1) {
|
|
|
|
+ restTime = 1.0;//一个小时午休
|
|
|
|
+ } else {
|
|
|
|
+ restTime = 1.0 * (workRules.getJSONObject(1).getIntValue("work_sec") - workRules.getJSONObject(0).getIntValue("off_work_sec")) / 3600;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ UserCorpwxTime userCorpwxTime=new UserCorpwxTime();
|
|
|
|
+ userCorpwxTime.setCorpwxUserid((String) objects[i]);
|
|
|
|
+ userCorpwxTime.setCompanyId(corpInfo.getCompanyId());
|
|
|
|
+ for (Integer integer : upList) {
|
|
|
|
+ if(objects[i].equals("woy9TkCAAArkpTq76GOJYsbYGgzk1g1w")){
|
|
|
|
+ System.out.println("上班"+DateTimeUtil.getTimeFromSeconds(integer));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ for (Integer integer : downList) {
|
|
|
|
+ if(objects[i].equals("woy9TkCAAArkpTq76GOJYsbYGgzk1g1w")){
|
|
|
|
+ System.out.println("下班"+DateTimeUtil.getTimeFromSeconds(integer));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(upList.isEmpty()||downList.isEmpty()){
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ Integer min = Collections.min(upList);
|
|
|
|
+ Integer max = Collections.max(downList);
|
|
|
|
+ String minTime = DateTimeUtil.getTimeFromSeconds(min);
|
|
|
|
+ String maxTime = DateTimeUtil.getTimeFromSeconds(max);
|
|
|
|
+ DateTimeFormatter df = DateTimeFormatter.ofPattern("HH:mm");
|
|
|
|
+ userCorpwxTime.setStartTime(LocalTime.parse(minTime,df).plusHours(8).format(df));
|
|
|
|
+ userCorpwxTime.setEndTime(LocalTime.parse(maxTime,df).plusHours(8).format(df));
|
|
|
|
+ userCorpwxTime.setCreateDate(LocalDate.now());
|
|
|
|
+ userCorpwxTime.setWxCorpid(corpInfo.getCorpid());
|
|
|
|
+ userCorpwxTime.setWeekDay(LocalDate.now().getDayOfWeek().getValue());
|
|
|
|
+ userCorpwxTime.setWeekDayTxt(DateTimeUtil.getWeekDayTxt(userCorpwxTime.getWeekDay()));
|
|
|
|
+ BigDecimal bigDecimal=new BigDecimal(Duration.between(LocalTime.parse(minTime,df).plusHours(8),LocalTime.parse(maxTime,df).plusHours(8)).toMinutes());
|
|
|
|
+ bigDecimal=bigDecimal.divide(BigDecimal.valueOf(60),1,BigDecimal.ROUND_HALF_UP).subtract(new BigDecimal(restTime));
|
|
|
|
+ userCorpwxTime.setWorkHours(bigDecimal.doubleValue());
|
|
|
|
+ System.out.println(userCorpwxTime);
|
|
|
|
+ UserCorpwxTime item = userCorpwxTimeMapper.selectOne(new QueryWrapper<UserCorpwxTime>().eq("corpwx_userid", (String) objects[i])
|
|
|
|
+ .eq("create_date", LocalDate.now()));
|
|
|
|
+ if (item != null) {
|
|
|
|
+ userCorpwxTime.setId(item.getId());
|
|
|
|
+ //已存在记录,进行更新
|
|
|
|
+ userCorpwxTimeMapper.updateById(userCorpwxTime);
|
|
|
|
+ } else {
|
|
|
|
+ userCorpwxTimeMapper.insert(userCorpwxTime);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public HttpRespMsg syncMembByCardTime(WxCorpInfo wxCorpInfo) {
|
|
public HttpRespMsg syncMembByCardTime(WxCorpInfo wxCorpInfo) {
|
|
HttpRespMsg msg = new HttpRespMsg();
|
|
HttpRespMsg msg = new HttpRespMsg();
|
|
@@ -527,6 +682,25 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
|
|
return msg;
|
|
return msg;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private String getCheckinOption(WxCorpInfo corpInfo,long dataTime,Object[] objects) throws Exception{
|
|
|
|
+ String url = GET_CHECKIN_OPTION.replace("ACCESS_TOKEN", getCorpAccessToken(corpInfo));
|
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
|
+ headers.setContentType(MediaType.APPLICATION_JSON);
|
|
|
|
+ System.out.println("" + objects.toString());
|
|
|
|
+ JSONObject reqParam = new JSONObject();
|
|
|
|
+ reqParam.put("datetime", dataTime);
|
|
|
|
+ reqParam.put("useridlist", objects);
|
|
|
|
+ HttpEntity<String> requestEntity = new HttpEntity<String>(reqParam.toJSONString(), headers);
|
|
|
|
+ ResponseEntity<String> responseEntity = this.restTemplate.exchange(url,
|
|
|
|
+ HttpMethod.POST, requestEntity, String.class);
|
|
|
|
+
|
|
|
|
+ if (responseEntity.getStatusCode() == HttpStatus.OK) {
|
|
|
|
+ String resp = responseEntity.getBody();
|
|
|
|
+ return resp;
|
|
|
|
+ }
|
|
|
|
+ return "";
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
|
|
private void reqOnceCardTime(WxCorpInfo corpInfo, long startTime, long endTime, Object[] objects, boolean showLog) throws Exception {
|
|
private void reqOnceCardTime(WxCorpInfo corpInfo, long startTime, long endTime, Object[] objects, boolean showLog) throws Exception {
|
|
DateTimeFormatter mdFormat = DateTimeFormatter.ofPattern("yyyy/M/d");
|
|
DateTimeFormatter mdFormat = DateTimeFormatter.ofPattern("yyyy/M/d");
|