|
|
@@ -78,10 +78,11 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
|
|
|
|
|
|
public static final String GET_APPROVAL_INSTANCE_INFO = "https://open.feishu.cn/open-apis/approval/v4/instances/:instance_id";
|
|
|
|
|
|
- public static final Map<Integer, String> EXPENSE_APPROVAL_CODE_MAP = new HashMap<>();
|
|
|
+ public static final Map<String, String> EXPENSE_APPROVAL_CODE_MAP = new HashMap<>();
|
|
|
static {
|
|
|
//医智锐科技
|
|
|
- EXPENSE_APPROVAL_CODE_MAP.put(8484, "E17B8057-1847-4BA2-8DDF-BBD28C57B909");
|
|
|
+ EXPENSE_APPROVAL_CODE_MAP.put("ExpenseSheet", "E17B8057-1847-4BA2-8DDF-BBD28C57B909");
|
|
|
+ EXPENSE_APPROVAL_CODE_MAP.put("PaymentApplication", "889F8775-C221-4E77-833D-BA0D8BD085EA");
|
|
|
}
|
|
|
|
|
|
@Resource
|
|
|
@@ -115,6 +116,12 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
|
|
|
private ExpenseTypeMapper expenseTypeMapper;
|
|
|
@Autowired
|
|
|
private ExpenseMainTypeMapper expenseMainTypeMapper;
|
|
|
+ @Resource
|
|
|
+ private PaymentApplicationMapper paymentApplicationMapper;
|
|
|
+ @Resource
|
|
|
+ private DepartmentMapper departmentMapper;
|
|
|
+ @Resource
|
|
|
+ private DepartmentFeishuMapper departmentFeishuMapper;
|
|
|
|
|
|
@Override
|
|
|
public String getAppAccessToken(FeishuInfo feishuInfo) {
|
|
|
@@ -981,7 +988,7 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public HttpRespMsg getExpenseFeeResult(FeishuInfo feishuInfo, User targetUser, String startDate, String endDate) throws Exception {
|
|
|
+ public HttpRespMsg refreshExpenseSheet(FeishuInfo feishuInfo, User targetUser, String startDate, String endDate,String refreshType) throws Exception {
|
|
|
HttpRespMsg msg = new HttpRespMsg();
|
|
|
|
|
|
if (feishuInfo == null) {
|
|
|
@@ -1010,14 +1017,14 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
|
|
|
toDate = end;
|
|
|
}
|
|
|
System.out.println("分批查询fromDate=" + fromDate + ", toDate=" + toDate);
|
|
|
- JSONArray tmpList = getApprovalInstanceList(feishuInfo.getCompanyId(), feishuInfo.getAppId(), formatter.format(fromDate), formatter.format(toDate), userId);
|
|
|
+ JSONArray tmpList = getApprovalInstanceList(feishuInfo.getCompanyId(), feishuInfo.getAppId(), formatter.format(fromDate), formatter.format(toDate), userId,refreshType);
|
|
|
if (tmpList != null && tmpList.size() > 0) {
|
|
|
instanceList.addAll(tmpList);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
} else{
|
|
|
- instanceList = getApprovalInstanceList(feishuInfo.getCompanyId(), feishuInfo.getAppId(), startDate, endDate, userId);
|
|
|
+ instanceList = getApprovalInstanceList(feishuInfo.getCompanyId(), feishuInfo.getAppId(), startDate, endDate, userId,refreshType);
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1104,6 +1111,116 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
|
|
|
|
|
|
return msg;
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public HttpRespMsg refreshPaymentApplication(FeishuInfo feishuInfo, User targetUser, String startDate, String endDate,String refreshType) throws Exception {
|
|
|
+ HttpRespMsg msg = new HttpRespMsg();
|
|
|
+
|
|
|
+ if (feishuInfo == null) {
|
|
|
+ msg.setError("飞书信息不能为空");
|
|
|
+ return msg;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 第一步:调用GET_APPROVAL_INSTANCE_LIST获取审批实例列表
|
|
|
+ System.out.println("========== 开始获取支付申请审批实例列表 ==========");
|
|
|
+ System.out.println("开始时间: " + startDate + ", 结束时间: " + endDate);
|
|
|
+ String userId = targetUser == null?null:targetUser.getJobNumber();
|
|
|
+
|
|
|
+ //日期间隔如果超过30天,需要分批查询
|
|
|
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
|
|
|
+ LocalDate start = LocalDate.parse(startDate, formatter);
|
|
|
+ LocalDate end = LocalDate.parse(endDate, formatter);
|
|
|
+ long daysBetween = ChronoUnit.DAYS.between(start, end);
|
|
|
+ JSONArray instanceList = null;
|
|
|
+ System.out.println("daysBetween==="+daysBetween);
|
|
|
+ if (daysBetween > 29) {
|
|
|
+ instanceList = new JSONArray();
|
|
|
+ for (LocalDate fromDate = start; !fromDate.isAfter(end); fromDate = fromDate.plusDays(30)) {
|
|
|
+ LocalDate toDate = fromDate.plusDays(29);
|
|
|
+ if (toDate.isAfter(end)) {
|
|
|
+ toDate = end;
|
|
|
+ }
|
|
|
+ System.out.println("分批查询fromDate=" + fromDate + ", toDate=" + toDate);
|
|
|
+ JSONArray tmpList = getApprovalInstanceList(feishuInfo.getCompanyId(), feishuInfo.getAppId(), formatter.format(fromDate), formatter.format(toDate), userId,refreshType);
|
|
|
+ if (tmpList != null && tmpList.size() > 0) {
|
|
|
+ instanceList.addAll(tmpList);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ } else{
|
|
|
+ instanceList = getApprovalInstanceList(feishuInfo.getCompanyId(), feishuInfo.getAppId(), startDate, endDate, userId,refreshType);
|
|
|
+ }
|
|
|
+ if (instanceList == null || instanceList.size() == 0) {
|
|
|
+ System.out.println("未查询到支付申请审批实例");
|
|
|
+ msg.setData(new JSONArray());
|
|
|
+ return msg;
|
|
|
+ }
|
|
|
+
|
|
|
+ System.out.println("查询到审批实例数量: " + instanceList.size());
|
|
|
+
|
|
|
+ // 第二步:遍历实例列表,调用GET_APPROVAL_INSTANCE_INFO获取每个实例的详情并解析存储
|
|
|
+ int successCount = 0;
|
|
|
+ int skipCount = 0;
|
|
|
+ int errorCount = 0;
|
|
|
+
|
|
|
+ List<String> instanceCodeList = new ArrayList<>();
|
|
|
+ for (int i = 0; i < instanceList.size(); i++) {
|
|
|
+ JSONObject instance = instanceList.getJSONObject(i).getJSONObject("instance");
|
|
|
+ String instanceCode = instance.getString("code");
|
|
|
+ instanceCodeList.add(instanceCode);
|
|
|
+ }
|
|
|
+ for (int i = 0; i < instanceList.size(); i++) {
|
|
|
+ JSONObject instance = instanceList.getJSONObject(i).getJSONObject("instance");
|
|
|
+ String instanceCode = instance.getString("code");
|
|
|
+
|
|
|
+// System.out.println("========== 处理第 " + (i + 1) + " 个实例 ==========");
|
|
|
+// System.out.println("实例ID: " + instanceCode);
|
|
|
+
|
|
|
+ try {
|
|
|
+
|
|
|
+ // 调用接口获取实例详情
|
|
|
+ JSONObject instanceDetail = getApprovalInstanceInfo(feishuInfo.getAppId(), instanceCode);
|
|
|
+
|
|
|
+ if (instanceDetail != null) {
|
|
|
+ // 解析并存储数据
|
|
|
+ boolean parseResult = parseAndSavePaymentData(instanceDetail, feishuInfo.getCompanyId());
|
|
|
+ if (parseResult) {
|
|
|
+ successCount++;
|
|
|
+ System.out.println("支付申请单处理成功。instance_code: " + instanceCode);
|
|
|
+ } else {
|
|
|
+ errorCount++;
|
|
|
+ System.out.println("支付申请单处理失败。instance_code: " + instanceCode);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ errorCount++;
|
|
|
+ System.out.println("获取实例详情失败,实例ID: " + instanceCode);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ errorCount++;
|
|
|
+ System.out.println("处理实例异常,实例ID: " + instanceCode + ", 异常信息: " + e.getMessage());
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ System.out.println("========== 支付申请单数据同步完成 ==========");
|
|
|
+ System.out.println("总数: " + instanceList.size() + ", 成功: " + successCount + ", 跳过: " + skipCount + ", 失败: " + errorCount);
|
|
|
+
|
|
|
+ JSONObject resultData = new JSONObject();
|
|
|
+ resultData.put("total", instanceList.size());
|
|
|
+ resultData.put("success", successCount);
|
|
|
+ resultData.put("skip", skipCount);
|
|
|
+ resultData.put("error", errorCount);
|
|
|
+ msg.setData(resultData);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ System.out.println("获取支付申请单数据异常: " + e.getMessage());
|
|
|
+ e.printStackTrace();
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+
|
|
|
+ return msg;
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
* 解析并保存报销单数据
|
|
|
@@ -1318,6 +1435,148 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析并保存支付申请单数据
|
|
|
+ * @param instanceDetail 实例详情
|
|
|
+ * @param companyId 公司ID
|
|
|
+ * @return 是否成功
|
|
|
+ */
|
|
|
+ private boolean parseAndSavePaymentData(JSONObject instanceDetail, Integer companyId) {
|
|
|
+ try {
|
|
|
+ // 解析基本信息
|
|
|
+ String instanceCode = instanceDetail.getString("instance_code");
|
|
|
+ String userId = instanceDetail.getString("user_id");
|
|
|
+ String departmentId = instanceDetail.getString("department_id");
|
|
|
+ String serialNumber = instanceDetail.getString("serial_number");
|
|
|
+ String status = instanceDetail.getString("status");
|
|
|
+ Long startTime = instanceDetail.getLong("start_time");
|
|
|
+ String formStr = instanceDetail.getString("form");
|
|
|
+ // 根据user_id查询用户信息
|
|
|
+ User user = userMapper.selectOne(
|
|
|
+ new QueryWrapper<User>()
|
|
|
+ .eq("job_number", userId)
|
|
|
+ .eq("company_id", companyId)
|
|
|
+ );
|
|
|
+
|
|
|
+ // 根据department_id查询部门信息
|
|
|
+ DepartmentFeishu departmentFeishu = departmentFeishuMapper.selectOne(new LambdaQueryWrapper<DepartmentFeishu>().eq(DepartmentFeishu::getFeishuDeptid, departmentId));
|
|
|
+ Department department = departmentMapper.selectOne(
|
|
|
+ new QueryWrapper<Department>()
|
|
|
+ .eq("feishu_deptid", departmentFeishu.getFeishuOpenDeptid())
|
|
|
+ .eq("company_id", companyId)
|
|
|
+ );
|
|
|
+
|
|
|
+ if (user == null) {
|
|
|
+ System.out.println("未找到用户,job_number: " + userId);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析form字段
|
|
|
+ JSONArray formArray = JSONArray.parseArray(formStr);
|
|
|
+
|
|
|
+ // 提取关键字段
|
|
|
+ String departmentName = null; // 提交人所属部门
|
|
|
+ String paymentReason = null; // 付款事由
|
|
|
+ Double paymentAmount = null; // 付款金额
|
|
|
+ String projectCode = null; // 项目编号
|
|
|
+ String paymentMethod = null; // 付款方式
|
|
|
+ String paymentDate = null; // 付款日期
|
|
|
+ String bankAccount = null; // 银行账户
|
|
|
+ DateTimeFormatter dateFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
|
|
|
+ for (int i = 0; i < formArray.size(); i++) {
|
|
|
+ JSONObject formItem = formArray.getJSONObject(i);
|
|
|
+ String name = formItem.getString("name");
|
|
|
+
|
|
|
+ if ("提交人所属部门".equals(name)) {
|
|
|
+ departmentName = formItem.getString("value");
|
|
|
+ } else if ("付款事由,需写明收款方的收款账户".equals(name)) {
|
|
|
+ paymentReason = formItem.getString("value");
|
|
|
+ } else if ("付款金额".equals(name)) {
|
|
|
+ Object valueObj = formItem.get("value");
|
|
|
+ if (valueObj instanceof Number) {
|
|
|
+ paymentAmount = ((Number) valueObj).doubleValue();
|
|
|
+ } else if (valueObj instanceof String) {
|
|
|
+ paymentAmount = Double.parseDouble((String) valueObj);
|
|
|
+ }
|
|
|
+ } else if ("项目编号".equals(name)) {
|
|
|
+ projectCode = formItem.getString("value");
|
|
|
+ } else if ("付款方式".equals(name)) {
|
|
|
+ paymentMethod = formItem.getString("value");
|
|
|
+ }else if ("付款日期".equals(name)) {
|
|
|
+ String dateValue = formItem.getString("value");
|
|
|
+ if (!StringUtils.isEmpty(dateValue)) {
|
|
|
+ try {
|
|
|
+ // 解析ISO 8601格式的日期时间
|
|
|
+ LocalDateTime dateTime = LocalDateTime.parse(dateValue, dateFormatter);
|
|
|
+ paymentDate = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
|
|
+ } catch (Exception e) {
|
|
|
+ System.out.println("日期解析失败: " + dateValue);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else if ("银行账户".equals(name)) {
|
|
|
+ JSONObject object = formItem.getJSONObject("value");
|
|
|
+ String widgetAccountBankName = object.getString("widgetAccountBankName");
|
|
|
+ bankAccount = object.getString("widgetAccountNumber");
|
|
|
+// JSONObject value = JSONObject.parseObject(widgetAccountBankName);
|
|
|
+// String text = value.getString("text");
|
|
|
+// bankAccount=String.valueOf(JSONObject.parseObject(text).get("bankNameZh"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ PaymentApplication paymentApplication = new PaymentApplication();
|
|
|
+ paymentApplication.setCompanyId(companyId);
|
|
|
+ paymentApplication.setSubmitterId(user.getId());
|
|
|
+ paymentApplication.setSubmitterName(user.getName());
|
|
|
+ paymentApplication.setInstanceCode(instanceCode);
|
|
|
+ paymentApplication.setSubmitterDept(department.getDepartmentName());
|
|
|
+ paymentApplication.setDeptId(department.getDepartmentId());
|
|
|
+ paymentApplication.setPaymentAmount(new BigDecimal(paymentAmount));
|
|
|
+ paymentApplication.setPaymentReason(paymentReason);
|
|
|
+ paymentApplication.setProjectCode(projectCode);
|
|
|
+ paymentApplication.setPaymentMethod(paymentMethod);
|
|
|
+ paymentApplication.setPaymentDate(LocalDate.parse(paymentDate));
|
|
|
+ paymentApplication.setBankAccount(bankAccount);
|
|
|
+
|
|
|
+ // 设置创建日期(从startTime转换)
|
|
|
+ if (startTime != null) {
|
|
|
+ LocalDateTime createAt = Instant.ofEpochMilli(startTime)
|
|
|
+ .atZone(ZoneId.of("Asia/Shanghai"))
|
|
|
+ .toLocalDateTime();
|
|
|
+ paymentApplication.setCreatedAt(createAt);
|
|
|
+ }
|
|
|
+ paymentApplication.setCode(serialNumber);
|
|
|
+ // 设置状态:根据飞书审批状态映射
|
|
|
+ // PENDING-待审核, APPROVED-审核通过, REJECTED-驳回, CANCELED-已撤回
|
|
|
+ Integer sheetStatus = 1; // 默认待审核
|
|
|
+ if ("APPROVED".equals(status)) {
|
|
|
+ sheetStatus = 0; // 审核通过
|
|
|
+ } else if ("REJECTED".equals(status)) {
|
|
|
+ sheetStatus = 2; // 驳回
|
|
|
+ } else if ("CANCELED".equals(status)) {
|
|
|
+ sheetStatus = 3; // 已撤回
|
|
|
+ } else if ("PENDING".equals(status)) {
|
|
|
+ sheetStatus = 1; // 待审核
|
|
|
+ }
|
|
|
+ paymentApplication.setStatus(sheetStatus);
|
|
|
+ // 插入ExpenseSheet
|
|
|
+ PaymentApplication oldPayment = paymentApplicationMapper.selectOne(new LambdaQueryWrapper<PaymentApplication>().eq(PaymentApplication::getCode, serialNumber));
|
|
|
+ if(null==oldPayment){
|
|
|
+ int insertResult = paymentApplicationMapper.insert(paymentApplication);
|
|
|
+ if (insertResult <= 0) {
|
|
|
+ System.out.println("插入PaymentApplication失败");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ System.out.println("解析并保存支付申请数据异常: " + e.getMessage());
|
|
|
+ e.printStackTrace();
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
* 获取审批实例列表
|
|
|
@@ -1326,7 +1585,7 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
|
|
|
* @param endDate 结束时间 格式:yyyyMMdd
|
|
|
* @return 审批实例列表
|
|
|
*/
|
|
|
- private JSONArray getApprovalInstanceList(Integer companyId, String appId, String startDate, String endDate, String userId) throws Exception {
|
|
|
+ private JSONArray getApprovalInstanceList(Integer companyId, String appId, String startDate, String endDate, String userId,String refreshType) throws Exception {
|
|
|
JSONArray result = new JSONArray();
|
|
|
|
|
|
// 将yyyyMMdd格式转换为时间戳(秒)
|
|
|
@@ -1339,7 +1598,7 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
|
|
|
|
|
|
String url = GET_APPROVAL_INSTANCE_LIST;
|
|
|
//审批表单的code
|
|
|
- String approvalCode = EXPENSE_APPROVAL_CODE_MAP.get(companyId);
|
|
|
+ String approvalCode = EXPENSE_APPROVAL_CODE_MAP.get(refreshType);
|
|
|
HttpHeaders headers = new HttpHeaders();
|
|
|
MediaType type = MediaType.parseMediaType("application/json; charset=utf-8");
|
|
|
headers.setContentType(type);
|