Commit a731f446 authored by hongguangwu's avatar hongguangwu

MVP1.6.2-企微出差主逻辑

parent 25198d01
...@@ -168,6 +168,9 @@ public interface CacheConstants { ...@@ -168,6 +168,9 @@ public interface CacheConstants {
String FUND_IMPORT_HANDLE_LOCK = "fund_import_handle_handle_lock"; String FUND_IMPORT_HANDLE_LOCK = "fund_import_handle_handle_lock";
// 项目报销token的key
String WX_REIMBURSEMENT_TOKEN = "WX_REIMBURSEMENT_TOKEN";
public static final String WX_ACCOSS_TOKEN = "WX_ACCOSS_TOKEN"; public static final String WX_ACCOSS_TOKEN = "WX_ACCOSS_TOKEN";
/** /**
......
...@@ -152,4 +152,9 @@ public interface SecurityConstants { ...@@ -152,4 +152,9 @@ public interface SecurityConstants {
**/ **/
String WX_GET_MESSAGE_AUTH_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_base&state=%s#wechat_redirect"; String WX_GET_MESSAGE_AUTH_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_base&state=%s#wechat_redirect";
// 获取审批单号list hgw 2024-4-12 14:45:25
String WX_GET_APPROVAL_LIST = "https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovalinfo?access_token={1}";
// 获取审核详情
String WX_GET_APPROVAL_DETAIL = "https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovaldetail?access_token={1}";
} }
...@@ -37,4 +37,19 @@ public class EkpPermissionTask { ...@@ -37,4 +37,19 @@ public class EkpPermissionTask {
log.info("-------------刷新EKP权限里的账号信息-定时任务结束------------"); log.info("-------------刷新EKP权限里的账号信息-定时任务结束------------");
} }
/**
* @return
* @Author hgw
* @Description 每天1点,定时同步企业微信审批出差数据
* @Date 2024-4-15 18:24:06
* @Param
**/
public void doSaveQiWeiChuChai() throws Exception {
log.info("-------------获取企业微信出差数据-定时任务开始------------");
HttpDaprUtil.invokeMethodPost(daprEkpPermissionProperties.getAppUrl(), daprEkpPermissionProperties.getAppId(),
"/qiWei/inner/everyDaySaveQiWeiChuChai", "", Object.class,
SecurityConstants.FROM_IN);
log.info("-------------获取企业微信出差数据-定时任务结束------------");
}
} }
\ No newline at end of file
package com.yifu.cloud.plus.v1.yifu.permission.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* 企业微信出差
*/
@TableName(value = "ekp_qiwei_chuchai")
@Data
@Schema(description = "企业微信出差")
public class EkpQiwiChuchai {
@TableField(exist = false)
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "主键", name = "fdId")
private String fdId;
@Schema(description = "审批编号")
@NotBlank(message = "审批编号不能为空")
private String spNo;
@Schema(description = "申请人姓名")
@NotBlank(message = "申请人姓名不能为空")
private String applyUserName;
@Schema(description = "申请人部门")
@NotBlank(message = "申请人部门不能为空")
private String applyUserDept;
@Schema(description = "申请日期")
@NotNull(message = "申请日期不能为空")
private LocalDateTime applyDate;
@Schema(description = "开始日期")
private LocalDate newBegin;
@Schema(description = "结束日期")
private LocalDate newEnd;
@Schema(description = "出差事由")
private String reason;
@Schema(description = "随行人员")
private String person;
@Schema(description = "出差地点")
private String address;
@Schema(description = "出行工具")
private String tools;
// status 0 初始;1已结算;
@Schema(description = "结算状态")
private String status;
@Schema(description = "关联结算ID")
private String settleFormId;
@Schema(description = "创建时间")
private LocalDateTime createTime;
}
\ No newline at end of file
package com.yifu.cloud.plus.v1.msg.config; package com.yifu.cloud.plus.v1.permission.config;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
...@@ -35,12 +35,15 @@ import java.util.concurrent.TimeUnit; ...@@ -35,12 +35,15 @@ import java.util.concurrent.TimeUnit;
@Slf4j @Slf4j
public class WxConfig { public class WxConfig {
@Value("${wx.corpid}") @Value("${wx.corpid}")
private String corpid; private String corpid;
@Value("${wx.corpsecret}") @Value("${wx.corpsecret}")
private String corpsecret; private String corpsecret;
@Value("${wx.agentid}") // 项目报销获取token专用
private String agentid; @Value("${wx.reimbursementCorpsecret}")
private String reimbursementCorpsecret;
@Value("${wx.agentid}")
private String agentid;
@Value("${wx.authUrl}") @Value("${wx.authUrl}")
private String authUrl; private String authUrl;
...@@ -50,140 +53,153 @@ public class WxConfig { ...@@ -50,140 +53,153 @@ public class WxConfig {
//未授权 //未授权
private String accossTokenInvliad = "40014"; private String accossTokenInvliad = "40014";
/** /**
* @param * @param restTemplate
* @Author: huyc * @Description: 获取项目报销的token
* @Date: 2023/7/28 * @Author: hgw
* @Description: 获取微信accos_token * @Date: 2021/3/24 14:42
* @return: java.lang.String * @return: java.lang.String
**/ **/
public String getAccessToken(RestTemplate restTemplate) { public String getReimbursementToken(RestTemplate restTemplate) {
if (Common.isNotNull(agentid)) { return this.getToken(restTemplate, CacheConstants.WX_REIMBURSEMENT_TOKEN, reimbursementCorpsecret);
return this.getToken(restTemplate, CacheConstants.WX_ACCOSS_TOKEN.concat(agentid), corpsecret); }
}
return this.getToken(restTemplate, CacheConstants.WX_ACCOSS_TOKEN, corpsecret);
}
public String getAccessToken(RestTemplate restTemplate,String corpsecret)throws AuthenticationServiceException { /**
if(Common.isEmpty(corpsecret)){ * @param
throw new AuthenticationServiceException("未找到对应的corpsecret请联系管理员配置"); * @Author: huyc
} * @Date: 2023/7/28
return this.getToken(restTemplate, CacheConstants.WX_ACCOSS_TOKEN.concat(agentid), corpsecret); * @Description: 获取微信accos_token
} * @return: java.lang.String
**/
public String getAccessToken(RestTemplate restTemplate) {
if (Common.isNotNull(agentid)) {
return this.getToken(restTemplate, CacheConstants.WX_ACCOSS_TOKEN.concat(agentid), corpsecret);
}
return this.getToken(restTemplate, CacheConstants.WX_ACCOSS_TOKEN, corpsecret);
}
public String getAccessToken(RestTemplate restTemplate, String corpsecret) throws AuthenticationServiceException {
if (Common.isEmpty(corpsecret)) {
throw new AuthenticationServiceException("未找到对应的corpsecret请联系管理员配置");
}
return this.getToken(restTemplate, CacheConstants.WX_ACCOSS_TOKEN.concat(agentid), corpsecret);
}
/** /**
* @param restTemplate * @param restTemplate
* @param tokenKey * @param tokenKey
* @param corpsecretKey * @param corpsecretKey
* @Description: 获取token * @Description: 获取token
* @Author: huyc * @Author: huyc
* @Date: 2023/7/28 14:46 * @Date: 2023/7/28 14:46
* @return: java.lang.String * @return: java.lang.String
**/ **/
public String getToken(RestTemplate restTemplate,String tokenKey, String corpsecretKey) { public String getToken(RestTemplate restTemplate, String tokenKey, String corpsecretKey) {
Object wxToken = redisTemplate.opsForValue().get(tokenKey); Object wxToken = redisTemplate.opsForValue().get(tokenKey);
if (null != wxToken) { if (null != wxToken) {
return String.valueOf(wxToken); return String.valueOf(wxToken);
} }
String requestTokenUrl = String.format(SecurityConstants.WX_GET_ACCOSS_TOKEN, corpid, corpsecretKey); String requestTokenUrl = String.format(SecurityConstants.WX_GET_ACCOSS_TOKEN, corpid, corpsecretKey);
String result = restTemplate.getForObject(requestTokenUrl, String.class); String result = restTemplate.getForObject(requestTokenUrl, String.class);
if (Common.isEmpty(result)) { if (Common.isEmpty(result)) {
throw new CheckedException("微信授权失败"); throw new CheckedException("微信授权失败");
} }
String token = JSON.parseObject(result).getString("access_token"); String token = JSON.parseObject(result).getString("access_token");
if (Common.isEmpty(token)) { if (Common.isEmpty(token)) {
log.info(result); log.info(result);
throw new CheckedException("获取微信token失败"); throw new CheckedException("获取微信token失败");
} }
redisTemplate.opsForValue().set(tokenKey, token); redisTemplate.opsForValue().set(tokenKey, token);
redisTemplate.expire(tokenKey, 3600, TimeUnit.SECONDS); redisTemplate.expire(tokenKey, 3600, TimeUnit.SECONDS);
return token; return token;
} }
/** /**
* @param * @param
* @Author: huyc * @Author: huyc
* @Date: 2023/7/28 14:43 * @Date: 2023/7/28 14:43
* @Description: 移除微信accossToken * @Description: 移除微信accossToken
* @return: java.lang.String * @return: java.lang.String
**/ **/
public void removeAccessToken() { public void removeAccessToken() {
redisTemplate.delete(CacheConstants.WX_ACCOSS_TOKEN); redisTemplate.delete(CacheConstants.WX_ACCOSS_TOKEN);
} }
/** /**
* @param restTemplate * @param restTemplate
* @param requestMap 请求内容 * @param requestMap 请求内容
* @Author: huyc * @Author: huyc
* @Date: 2023/7/28 14:48 * @Date: 2023/7/28 14:48
* @Description: 发送卡片消息 * @Description: 发送卡片消息
* @return: java.lang.String * @return: java.lang.String
**/ **/
public boolean sendTextCard(RestTemplate restTemplate, Map<String, Object> requestMap) { public boolean sendTextCard(RestTemplate restTemplate, Map<String, Object> requestMap) {
// 必须加上header说明 // 必须加上header说明
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8); headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
Gson gson = new Gson(); Gson gson = new Gson();
log.info(gson.toJson(requestMap)); log.info(gson.toJson(requestMap));
HttpEntity<String> requestEntity = new HttpEntity<>(gson.toJson(requestMap), headers); HttpEntity<String> requestEntity = new HttpEntity<>(gson.toJson(requestMap), headers);
String accessToken = getAccessToken(restTemplate); String accessToken = getAccessToken(restTemplate);
ResponseEntity<String> responseEntity = restTemplate.postForEntity(String.format(SecurityConstants.WX_SEND_MESSAGE, accessToken), requestEntity, String.class); ResponseEntity<String> responseEntity = restTemplate.postForEntity(String.format(SecurityConstants.WX_SEND_MESSAGE, accessToken), requestEntity, String.class);
log.info(JSON.toJSONString(responseEntity)); log.info(JSON.toJSONString(responseEntity));
JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(responseEntity)); JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(responseEntity));
JSONObject jsonBody = jsonObject.getJSONObject("body"); JSONObject jsonBody = jsonObject.getJSONObject("body");
if (jsonBody != null) { if (jsonBody != null) {
String errcode = jsonBody.getString("errcode"); String errcode = jsonBody.getString("errcode");
if (accossTokenInvliad.equals(errcode)) { if (accossTokenInvliad.equals(errcode)) {
//删除accossToken缓存 //删除accossToken缓存
removeAccessToken(); removeAccessToken();
return false; return false;
} }
if (!CommonConstants.ZERO_STRING.equals(errcode)) { //非正常,则打印错误日志 if (!CommonConstants.ZERO_STRING.equals(errcode)) { //非正常,则打印错误日志
log.info(jsonObject.toJSONString()); log.info(jsonObject.toJSONString());
} }
} else { } else {
log.info(jsonObject.toJSONString()); log.info(jsonObject.toJSONString());
} }
return true; return true;
} }
/** /**
* @param restTemplate * @param restTemplate
* @param requestMap 请求内容 * @param requestMap 请求内容
* @Author: huyc * @Author: huyc
* @Date: 2023/7/28 14:50 * @Date: 2023/7/28 14:50
* @Description: 发送卡片消息 * @Description: 发送卡片消息
* @return: java.lang.String * @return: java.lang.String
**/ **/
public boolean sendAppTextCard(RestTemplate restTemplate, Map<String, Object> requestMap) { public boolean sendAppTextCard(RestTemplate restTemplate, Map<String, Object> requestMap) {
// 必须加上header说明 // 必须加上header说明
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8); headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
Gson gson = new Gson(); Gson gson = new Gson();
log.info("发企业微信===请求:{}", gson.toJson(requestMap)); log.info("发企业微信===请求:{}", gson.toJson(requestMap));
HttpEntity<String> requestEntity = new HttpEntity<>(gson.toJson(requestMap), headers); HttpEntity<String> requestEntity = new HttpEntity<>(gson.toJson(requestMap), headers);
String accessToken = getAppAccessToken(restTemplate); String accessToken = getAppAccessToken(restTemplate);
ResponseEntity<String> responseEntity = restTemplate.postForEntity(String.format(SecurityConstants.WX_SEND_MESSAGE, accessToken), requestEntity, String.class); ResponseEntity<String> responseEntity = restTemplate.postForEntity(String.format(SecurityConstants.WX_SEND_MESSAGE, accessToken), requestEntity, String.class);
log.info("发企业微信===返回:{}",JSON.toJSONString(responseEntity)); log.info("发企业微信===返回:{}", JSON.toJSONString(responseEntity));
JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(responseEntity)); JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(responseEntity));
JSONObject jsonBody = jsonObject.getJSONObject("body"); JSONObject jsonBody = jsonObject.getJSONObject("body");
if (jsonBody != null) { if (jsonBody != null) {
String errcode = jsonBody.getString("errcode"); String errcode = jsonBody.getString("errcode");
if (accossTokenInvliad.equals(errcode)) { if (accossTokenInvliad.equals(errcode)) {
//删除accossToken缓存 //删除accossToken缓存
removeAccessToken(); removeAccessToken();
return false; return false;
} }
if (!CommonConstants.ZERO_STRING.equals(errcode)) { //非正常,则打印错误日志 if (!CommonConstants.ZERO_STRING.equals(errcode)) { //非正常,则打印错误日志
log.info(jsonObject.toJSONString()); log.info(jsonObject.toJSONString());
} }
} else { } else {
log.info(jsonObject.toJSONString()); log.info(jsonObject.toJSONString());
} }
return true; return true;
} }
/** /**
* 功能描述: 获取微信accos_token * 功能描述: 获取微信accos_token
*
* @Author: huyc * @Author: huyc
* @Date: 2023/7/28 14:50 * @Date: 2023/7/28 14:50
* @return: java.lang.String * @return: java.lang.String
......
package com.yifu.cloud.plus.v1.permission.controller;
import com.yifu.cloud.plus.v1.permission.service.QiWeiService;
import com.yifu.cloud.plus.v1.yifu.common.core.util.DateUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.security.annotation.Inner;
import com.yifu.cloud.plus.v1.yifu.permission.entity.EkpQiwiChuchai;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 工资服务-获取微信
*
* @author hgw
* @date 2024-4-10 11:26:50
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/qiWei")
@Tag(name = "工资服务-获取微信")
public class QiWeiController {
private final QiWeiService wxSalaryService;
/**
* @Description: 每日获取当日企业微信审批里的出差
* @Author: hgw
* @Date: 2024-4-11 11:03:34
* @return: com.yifu.cloud.v1.common.core.util.R<java.util.List < com.yifu.cloud.v1.hrms.api.entity.TEventFeeDetail>>
**/
@GetMapping("/inner/everyDaySaveQiWeiChuChai")
@Inner
public R<List<EkpQiwiChuchai>> everyDaySaveQiWeiChuChai() {
String startDay = DateUtil.addDay(-29);
String endDay = DateUtil.addDay(0);
return wxSalaryService.getQiWeiChuChaiAndSave(startDay, endDay);
}
/**
* @param startTime
* @param endTime
* @Description: 获取企业微信审批里的出差
* @Author: hgw
* @Date: 2024-4-11 11:03:30
* @return: com.yifu.cloud.v1.common.core.util.R<java.util.List < com.yifu.cloud.v1.hrms.api.entity.TStatisticsProjectReimburse>>
**/
@Operation(description = "获取企业微信审批里的出差数据:startTime格式:2024-04-10")
@PostMapping("/getQiWeiChuCHaiInfoAndSave")
//@PreAuthorize("@pms.hasPermission('wxhr:wxsalaryauth')")
public R<List<EkpQiwiChuchai>> getQiWeiChuCHaiInfoAndSave(@RequestParam String startTime, @RequestParam String endTime) {
return wxSalaryService.getQiWeiChuChaiAndSave(startTime, endTime);
}
}
package com.yifu.cloud.plus.v1.permission.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yifu.cloud.plus.v1.yifu.permission.entity.EkpQiwiChuchai;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 企业微信出差
*
* @Entity generator.domain.TStatisticsProjectReimburse
*/
@Mapper
public interface EkpQiweiChuchaiMapper extends BaseMapper<EkpQiwiChuchai> {
/**
* @param status 状态
* @Description: 获取全部的列表,用来: 拉取企业微信时,不覆盖数据
* @Author: hgw
* @Date: 2021/7/28 18:05
* @return: java.util.List<com.yifu.cloud.v1.hrms.api.entity.salary.TStatisticsProjectReimburse>
**/
List<EkpQiwiChuchai> getAllInfo(@Param("status") String status);
}
package com.yifu.cloud.plus.v1.permission.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.permission.entity.EkpQiwiChuchai;
import java.util.List;
/**
* 成本支出表
*
* @author hgw
* @date 2024-4-15 17:16:50
*/
public interface QiWeiService extends IService<EkpQiwiChuchai> {
/**
* @param startTime
* @param endTime
* @Description: 获取微信信息
* @Author: hgw
* @Date: 2021-7-28 17:46:01
* @return: com.yifu.cloud.v1.common.core.util.R<java.util.List < com.yifu.cloud.v1.hrms.api.entity.TStatisticsProjectReimburse>>
**/
R<List<EkpQiwiChuchai>> getQiWeiChuChaiAndSave(String startTime, String endTime);
}
package com.yifu.cloud.plus.v1.permission.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifu.cloud.plus.v1.permission.config.WxConfig;
import com.yifu.cloud.plus.v1.permission.mapper.EkpQiweiChuchaiMapper;
import com.yifu.cloud.plus.v1.permission.service.QiWeiService;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.SecurityConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.permission.entity.EkpQiwiChuchai;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
/**
* 获取微信信息
*
* @author hgw
* @date 2024-4-15 17:16:57
*/
@Service
@AllArgsConstructor
public class QiWeiServiceImpl extends ServiceImpl<EkpQiweiChuchaiMapper, EkpQiwiChuchai> implements QiWeiService {
private RestTemplate restTemplate = new RestTemplate();
private static final String VALUESTR = "value";
private static final String NEW_NEXT_CURSOR = "new_next_cursor";
private static final String NEW_CURSOR = "new_cursor";
private final WxConfig wxConfig;
/**
* @param startTime
* @param endTime
* @Description: 获取所有的出差
* @Author: hgw
* @Date: 2021/3/24 15:41
* @return: com.yifu.cloud.v1.common.core.util.R<java.util.List < com.yifu.cloud.v1.hrms.api.entity.TStatisticsProjectReimburse>>
**/
@Override
public synchronized R<List<EkpQiwiChuchai>> getQiWeiChuChaiAndSave(String startTime, String endTime) {
try {
// 起止时间
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime startDate = LocalDateTime.parse(startTime + " 00:00:00", df);
LocalDateTime endDate = LocalDateTime.parse(endTime + " 23:59:59", df);
Duration duration = Duration.between(startDate, endDate);
long days = duration.toDays(); //相差的天数
// 判断时间跨度:
if (days > 30) {
return R.failed("时间范围超过30天了:起:" + startTime + ";止:" + endTime);
}
// 获取起月份的起止时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date startTimeDate = sdf.parse(startTime + " 00:00:00");
Date endTimeDate = sdf.parse(endTime + " 23:59:59");
Calendar rightNow = Calendar.getInstance();
rightNow.setTime(startTimeDate);
startTime = String.valueOf(rightNow.getTime().getTime() / 1000);
rightNow.setTime(endTimeDate);
endTime = String.valueOf(rightNow.getTime().getTime() / 1000);
// 已被拉取的Map
Map<String, String> cpMap = this.getAllMap();
// 一个月的全量数据
List<EkpQiwiChuchai> cpAllList = new ArrayList<>();
List<EkpQiwiChuchai> returnCpList = new ArrayList<>();
this.getCostPaymentListByMonth(startTime, endTime, cpAllList);
if (!cpAllList.isEmpty()) {
for (EkpQiwiChuchai cp : cpAllList) {
if (cpMap.get(cp.getSpNo()) == null) {
returnCpList.add(cp);
}
}
}
// 填充详情
if (!returnCpList.isEmpty()) {
log.error("拉取企业微信出差数据:"+returnCpList.size()+" 条,开始循环拉取明细!");
this.getTStatisticsProjectReimburseDetail(returnCpList);
log.error("拉取企业微信出差数据结束");
}
// 填充基础数据并保存:
if (!returnCpList.isEmpty()) {
this.saveBatch(returnCpList);
}
return new R<>(returnCpList);
} catch (Exception e) {
e.printStackTrace();
log.error("拉取企业微信出差失败:", e);
return R.failed("时间转化失败,请选择合适的时间,例如:2021-07-29,且范围不超过30天。" + e.getMessage());
}
}
/**
* @param startTime
* @param endTime
* @param cpAllList
* @Description: 获取当月的list
* @Author: hgw
* @Date: 2021/3/24 17:50
* @return: void
**/
private void getCostPaymentListByMonth(String startTime, String endTime, List<EkpQiwiChuchai> cpAllList) {
// 当月的全量数据
R<List<EkpQiwiChuchai>> listR = this.getTStatisticsProjectReimburseListByWx(startTime, endTime);
if (listR.getCode() == CommonConstants.SUCCESS) {
cpAllList.addAll(listR.getData());
}
}
/**
* @Description: 从微信-获取所有的支出项
* @Author: hgw
* @Date: 2021/3/18 14:58
* @return: java.util.List<com.yifu.cloud.v1.hrms.api.entity.TStatisticsProjectReimburse>
**/
private R<List<EkpQiwiChuchai>> getTStatisticsProjectReimburseListByWx(String startTime, String endTime) {
String accessToken = wxConfig.getReimbursementToken(restTemplate);
JSONObject json = new JSONObject();
List<Map<String, String>> paramList = new ArrayList<>();
Map<String, String> paramMap = new HashMap<>();
// record_type - 审批单类型属性,1-请假;2-打卡补卡;3-出差;4-外出;5-加班; 6- 调班;7-会议室预定;8-退款审批;9-红包报销审批
paramMap.put("key", "record_type");
paramMap.put("value", "3");
paramList.add(paramMap);
paramMap = new HashMap<>();
// sp_status-审批单状态(1-审批中;2-已通过;3-已驳回;4-已撤销;6-通过后撤销;7-已删除;10-已支付
paramMap.put("key", "sp_status");
paramMap.put("value", "2");
paramList.add(paramMap);
json.put("starttime", startTime);
json.put("endtime", endTime);
json.put("filters", paramList);
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
headers.setContentType(type);
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
HttpEntity<String> formEntity = new HttpEntity<>(json.toString(), headers);
String dataResultList = restTemplate.postForEntity(SecurityConstants.WX_GET_APPROVAL_LIST, formEntity, String.class, accessToken).getBody();
if (Common.isEmpty(dataResultList)) {
throw new AuthenticationServiceException("获取企业微信审批数据失败");
}
JSONObject jsonObject = JSON.parseObject(dataResultList);
String errcode = jsonObject.getString("errcode");
String errmsg = jsonObject.getString("errmsg");
if (!"0".equals(errcode)) {
return R.failed(errmsg);
}
// 时间段内的总审批单个数
String nextCode = jsonObject.getString(NEW_NEXT_CURSOR);
List<EkpQiwiChuchai> cpList = new ArrayList<>();
this.setTStatisticsProjectReimburseInfo(jsonObject, cpList);
// 如果一次没取全,循环取
while (Common.isNotNull(nextCode)) {
json.put(NEW_CURSOR, nextCode);
formEntity = new HttpEntity<>(json.toString(), headers);
dataResultList = restTemplate.postForEntity(SecurityConstants.WX_GET_APPROVAL_LIST, formEntity, String.class, accessToken).getBody();
if (Common.isEmpty(dataResultList)) {
throw new AuthenticationServiceException("获取企业微信审批数据失败");
}
jsonObject = JSON.parseObject(dataResultList);
this.setTStatisticsProjectReimburseInfo(jsonObject, cpList);
nextCode = jsonObject.getString(NEW_NEXT_CURSOR);
}
return new R<>(cpList);
}
/**
* @Description: 从企业微信-获取详情
* @Author: hgw
* @Date: 2024-4-12 16:55:00
* @return: java.util.List<com.yifu.cloud.v1.hrms.api.entity.TStatisticsProjectReimburse>
**/
private R<List<EkpQiwiChuchai>> getTStatisticsProjectReimburseDetail(List<EkpQiwiChuchai> list) {
String accessToken = wxConfig.getReimbursementToken(restTemplate);
int i = 1;
JSONObject jsonDetail;
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
headers.setContentType(type);
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
HttpEntity<String> formEntityDetail;
String dataResultDetail;
JSONObject jsonObject;
String errcode;
String errmsg;
String info;
for (EkpQiwiChuchai r : list) {
log.error("企业微信出差【"+i+"/"+""+list.size()+"】条");
jsonDetail = new JSONObject();
jsonDetail.put("sp_no", r.getSpNo());
formEntityDetail = new HttpEntity<>(jsonDetail.toString(), headers);
dataResultDetail = restTemplate.postForEntity(SecurityConstants.WX_GET_APPROVAL_DETAIL, formEntityDetail, String.class, accessToken).getBody();
if (Common.isEmpty(dataResultDetail)) {
throw new AuthenticationServiceException("获取企业微信审批详情失败!");
}
jsonObject = JSON.parseObject(dataResultDetail);
errcode = jsonObject.getString("errcode");
errmsg = jsonObject.getString("errmsg");
if (!"0".equals(errcode)) {
return R.failed(errmsg);
}
// 详细信息
info = jsonObject.getString("info");
this.setTStatisticsProjectReimburseDetail(info, r);
if (i++ >= 600) {
// 企业微信频率限制:接口频率限制 600次/分钟
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return new R<>(list);
}
/**
* @Description: 获取全部的列表,用来: 拉取企业微信时,不覆盖数据
* @Author: hgw
* @Date: 2021-7-28 18:14:59
* @return: java.util.Map<java.lang.String, java.lang.String>
**/
private Map<String, String> getAllMap() {
List<EkpQiwiChuchai> cpHistoryList = baseMapper.getAllInfo(null);
Map<String, String> cpMap = new HashMap<>();
for (EkpQiwiChuchai cpHis : cpHistoryList) {
cpMap.put(cpHis.getSpNo(), "0");
}
return cpMap;
}
/**
* @param jsonObject
* @param cpList
* @Description: 向支出list里塞值
* @Author: hgw
* @Date: 2021/3/18 14:58
* @return: void
**/
private void setTStatisticsProjectReimburseInfo(JSONObject jsonObject, List<EkpQiwiChuchai> cpList) {
EkpQiwiChuchai cp;
String data = jsonObject.getString("sp_no_list");
if (Common.isNotNull(data)) {
List<String> dataList = JSON.parseArray(data, String.class);
for (String datas : dataList) {
cp = new EkpQiwiChuchai();
cp.setApplyDate(LocalDateTime.now());
cp.setApplyUserName("张三");
cp.setSpNo(datas);
cp.setStatus(CommonConstants.ZERO_STRING);
cpList.add(cp);
}
}
}
/**
* @param reimburse
* @Description: 向详情里塞值
* @Author: hgw
* @Date: 2024-4-12 17:01:35
* @return: void
**/
private void setTStatisticsProjectReimburseDetail(String info, EkpQiwiChuchai reimburse) {
JSONObject jsonObject = JSON.parseObject(info);
if (Common.isNotNull(info)) {
reimburse.setCreateTime(LocalDateTime.now());
reimburse.setApplyUserName(((JSONObject) jsonObject.get("applyer")).getString("userid"));
reimburse.setApplyUserDept(((JSONObject) jsonObject.get("applyer")).getString("partyid"));
reimburse.setSpNo(jsonObject.getString("sp_no"));
reimburse.setApplyDate(LocalDateTime.ofInstant(Instant.ofEpochSecond(Long.parseLong(String.valueOf(jsonObject.get("apply_time")))), ZoneId.systemDefault()));
// 核心数据
JSONObject applyData = (JSONObject) jsonObject.get("apply_data");
String contents = applyData.getString("contents");
List<HashMap> contentList = JSON.parseArray(contents, HashMap.class);
JSONArray title;
JSONObject value;
JSONObject attendance;
JSONObject dateRange;
//JSONObject selector;
//JSONArray options;
// 开始时间
LocalDate newBegin = null;
// 结束时间
LocalDate newEnd = null;
// 出差时长
//String newDuration;
// 岗位级别
//String post;
// 业务条线归属
//String lineType;
// 出差事由
String reason = null;
// 随行人员
String person = null;
// 出差地点
String address = null;
// 出行工具
String tools = null;
for (HashMap content : contentList) {
title = (JSONArray) content.get("title");
if ("出差".equals(((JSONObject) title.get(0)).get("text"))) {
value = (JSONObject) content.get(VALUESTR);
attendance = (JSONObject) value.get("attendance");
dateRange = (JSONObject) attendance.get("date_range");
// 28801 是时区+8小时1秒
newBegin = LocalDate.ofEpochDay((Long.parseLong(dateRange.getString("new_begin")) + 28801) / 86400);
newEnd = LocalDate.ofEpochDay((Long.parseLong(dateRange.getString("new_end")) + 28801) / 86400);
//newEnd = LocalDateTime.ofInstant(Instant.ofEpochSecond(Long.valueOf(dateRange.getString("new_end"))), ZoneId.systemDefault());
//newDuration = dateRange.getString("new_duration");
}
/*else if ("岗位级别".equals(((JSONObject)title.get(0)).get("text"))) {
value = (JSONObject) content.get(VALUESTR);
selector = (JSONObject) value.get("selector");
options = (JSONArray) selector.get("options");
post = ((JSONObject) ((JSONArray) ((JSONArray) ((JSONObject) options.get(0)).get(VALUESTR)).get(0)).get(0)).getString("text");
} else if ("业务条线归属".equals(((JSONObject)title.get(0)).get("text"))) {
value = (JSONObject) content.get(VALUESTR);
selector = (JSONObject) value.get("selector");
options = (JSONArray) selector.get("options");
lineType = ((JSONObject) ((JSONArray) ((JSONArray) ((JSONObject) options.get(0)).get(VALUESTR)).get(0)).get(0)).getString("text");
}*/
else if ("出差事由".equals(((JSONObject) title.get(0)).get("text"))) {
value = (JSONObject) content.get(VALUESTR);
reason = value.getString("text");
} else if ("随行人员".equals(((JSONObject) title.get(0)).get("text"))) {
value = (JSONObject) content.get(VALUESTR);
person = value.getString("text");
} else if ("出差地点".equals(((JSONObject) title.get(0)).get("text"))) {
value = (JSONObject) content.get(VALUESTR);
address = value.getString("text");
} else if ("出行工具".equals(((JSONObject) title.get(0)).get("text"))) {
value = (JSONObject) content.get(VALUESTR);
tools = value.getString("text");
}
}
reimburse.setNewBegin(newBegin);
reimburse.setNewEnd(newEnd);
reimburse.setReason(reason);
reimburse.setPerson(person);
reimburse.setAddress(address);
reimburse.setTools(tools);
}
}
}
...@@ -8,6 +8,8 @@ spring: ...@@ -8,6 +8,8 @@ spring:
on-profile: dev on-profile: dev
redis: redis:
host: 127.0.0.1 host: 127.0.0.1
port: 6379
password: '@yf_2017'
datasource: datasource:
type: com.zaxxer.hikari.HikariDataSource type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
......
...@@ -83,3 +83,9 @@ springdoc: ...@@ -83,3 +83,9 @@ springdoc:
- group: permission - group: permission
#按包路径匹配 #按包路径匹配
packagesToScan: com.yifu.cloud.plus.v1.permission.controller packagesToScan: com.yifu.cloud.plus.v1.permission.controller
wx:
corpid: wwbcb090af0dfe50e5
corpsecret: o3fLn0u9SFHh5_htpIRBSp2bOibTa8pZGcOJIJqvidQ
agentid: 1000019
authUrl: https://wmp.worfu.com/api
reimbursementCorpsecret: R0nKkvsY-oF41fuQvUXZ-kFG3_g_Ce0bpZt6mByx524
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yifu.cloud.plus.v1.permission.mapper.EkpQiweiChuchaiMapper">
<resultMap id="BaseResultMap" type="com.yifu.cloud.plus.v1.yifu.permission.entity.EkpQiwiChuchai">
<id property="fdId" column="fd_ID" />
<result property="spNo" column="SP_NO"/>
<result property="applyUserName" column="APPLY_USER_NAME"/>
<result property="applyUserDept" column="APPLY_USER_DEPT"/>
<result property="applyDate" column="APPLY_DATE"/>
<result property="newBegin" column="NEW_BEGIN"/>
<result property="newEnd" column="NEW_END"/>
<result property="reason" column="REASON"/>
<result property="person" column="PERSON"/>
<result property="address" column="ADDRESS"/>
<result property="tools" column="TOOLS"/>
<result property="status" column="STATUS"/>
<result property="settleFormId" column="SETTLE_FORM_ID"/>
</resultMap>
<sql id="Base_Column_List">
a.FD_ID,
a.SP_NO,
a.APPLY_USER_NAME,
a.APPLY_USER_DEPT,
a.APPLY_DATE,
a.NEW_BEGIN,
a.NEW_END,
a.REASON,
a.PERSON,
a.ADDRESS,
a.TOOLS,
a.STATUS,
a.SETTLE_FORM_ID
</sql>
<!--获取全部的,用来: 拉取企业微信时,不覆盖数据 -->
<select id="getAllInfo" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List"/>
FROM ekp_qiwei_chuchai a
<where>
1=1
<if test="status != null and status.trim() != ''">
AND a.STATUS = #{status}
</if>
</where>
</select>
</mapper>
...@@ -131,11 +131,15 @@ public class TSalaryStandardOriginalServiceImpl extends ServiceImpl<TSalaryStand ...@@ -131,11 +131,15 @@ public class TSalaryStandardOriginalServiceImpl extends ServiceImpl<TSalaryStand
vo = readXls(inputStream, specialIdCardList, true, sheetName); vo = readXls(inputStream, specialIdCardList, true, sheetName);
} }
//数据保存 //数据保存
if (Common.isNotNull(vo.getErrorInfo())) {
return R.failed(vo);
}
return R.ok(vo); return R.ok(vo);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
log.error("解析表头失败!"+ e.getMessage());
} }
return null; return R.failed("解析表头失败");
} }
/** /**
...@@ -210,7 +214,11 @@ public class TSalaryStandardOriginalServiceImpl extends ServiceImpl<TSalaryStand ...@@ -210,7 +214,11 @@ public class TSalaryStandardOriginalServiceImpl extends ServiceImpl<TSalaryStand
} else if (CellType.BOOLEAN == cell.getCellType()) { } else if (CellType.BOOLEAN == cell.getCellType()) {
cellValue = String.valueOf(row.getCell(cellNum).getBooleanCellValue()); cellValue = String.valueOf(row.getCell(cellNum).getBooleanCellValue());
} else { } else {
cellValue = row.getCell(cellNum).getStringCellValue(); try {
cellValue = row.getCell(cellNum).getStringCellValue();
} catch (Exception e) {
cellValue = String.valueOf(row.getCell(cellNum).getNumericCellValue());
}
} }
} catch (Exception e) { } catch (Exception e) {
sheetVo.setErrorInfo("请注意单元格格式,第" + (i + 1) + "个sheet,第" + (rowNum + 1) + "行第" + (cellNum + 1) + "列。" + e.getMessage()); sheetVo.setErrorInfo("请注意单元格格式,第" + (i + 1) + "个sheet,第" + (rowNum + 1) + "行第" + (cellNum + 1) + "列。" + e.getMessage());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment