Ver Fonte

修改财务审核

zhouyy há 6 meses atrás
pai
commit
8c128eac43

+ 16 - 9
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java

@@ -1,7 +1,6 @@
 package com.management.platform.controller;
 
 
-import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -16,13 +15,7 @@ import com.management.platform.mapper.*;
 import com.management.platform.service.*;
 import com.management.platform.service.impl.WxCorpInfoServiceImpl;
 import com.management.platform.util.*;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.WebSocket;
-import org.apache.ibatis.annotations.Param;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.*;
-import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.client.RestTemplate;
@@ -30,8 +23,6 @@ import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
-import java.io.File;
-import java.io.IOException;
 import java.lang.reflect.Method;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
@@ -117,6 +108,9 @@ public class ReportController {
     @Resource
     private UserGroupMapper userGroupMapper;
 
+    @Resource
+    private FinancialAuditMapper financialAuditMapper;
+
     //获取任务相关的日报列表
     @RequestMapping("/getTaskReportList")
     public HttpRespMsg getTaskReportList(Integer taskId) {
@@ -444,6 +438,19 @@ public class ReportController {
             msg.setError("请设置任务分组");
             return msg;
         }
+
+
+        //添加财务审核该月后无法再次填报该月日报
+        if(null != createDate && 1== createDate.length){
+            String reportYM = createDate[0].substring(0,7);
+            Integer count = financialAuditMapper.checkFinanceReview(user.getCompanyId(),reportYM);
+            if(0 < count){
+                HttpRespMsg msg = new HttpRespMsg();
+                msg.setError(MessageUtils.message("report.financial_report",reportYM));
+                return msg;
+            }
+        }
+
         if (customData == null) {
             customData = new Double[projectId.length];
             for(int i=0;i<customData.length; i++) {

+ 2 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/FinancialAuditMapper.java

@@ -2,6 +2,7 @@ package com.management.platform.mapper;
 
 import com.management.platform.entity.FinancialAudit;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * <p>
@@ -12,5 +13,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  * @since 2024-06-05
  */
 public interface FinancialAuditMapper extends BaseMapper<FinancialAudit> {
-
+    Integer checkFinanceReview(@Param("companyId") Integer companyId, @Param("reportYM") String reportYM);
 }

+ 2 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/WxCorpInfoService.java

@@ -48,6 +48,8 @@ public interface WxCorpInfoService extends IService<WxCorpInfo> {
 
     public String getTranslationMediaId(String fileName) throws Exception;
 
+    public String getTranslationJobId(String fileName,WxCorpInfo wxCorpInfo) throws Exception;
+
     public String syncTranslation(String authCorpid,String mediaId,String outPutFileName,String outputFileFormat) throws Exception;
 
     public String getSyncTranslationResult(String jobId) throws Exception;

+ 112 - 7
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExcelExportServiceImpl.java

@@ -12,11 +12,6 @@ import com.management.platform.service.WxCorpInfoService;
 import com.management.platform.util.ExcelUtil;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.MessageUtils;
-import org.apache.poi.hssf.usermodel.*;
-import org.apache.poi.ss.usermodel.BorderStyle;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.FillPatternType;
-import org.apache.poi.ss.usermodel.HorizontalAlignment;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Isolation;
@@ -24,8 +19,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
-import java.io.File;
-import java.io.FileOutputStream;
 import java.time.LocalDateTime;
 import java.util.HashMap;
 import java.util.List;
@@ -89,6 +82,116 @@ public class ExcelExportServiceImpl implements ExcelExportService {
         String resp = ExcelUtil.exportGeneralExcelByTitleAndList(title, list, downloadPath);
         String fileUrlSuffix = title + ".xlsx";
         if(wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1){
+//            FileSystemResource fileSystemResource = new FileSystemResource(path+fileUrlSuffix);
+//            Long checkSize = 20L*1024*1024;
+            String jobId = "";
+            String mediaId = wxCorpInfoService.getTranslationMediaId(fileUrlSuffix);
+            jobId = wxCorpInfoService.syncTranslation(wxCorpInfo.getCorpid(),mediaId,fileUrlSuffix, null);
+//            if(fileSystemResource.getFile().length() >= checkSize){
+//                jobId = wxCorpInfoService.getTranslationJobId(fileUrlSuffix,wxCorpInfo);
+//            }else{
+//                String mediaId = wxCorpInfoService.getTranslationMediaId(fileUrlSuffix);
+//                jobId = wxCorpInfoService.syncTranslation(wxCorpInfo.getCorpid(),mediaId,fileUrlSuffix, null);
+//            }
+
+            System.out.println("上传待转译文件到企业微信, jobId==" + jobId);
+            int i = 0;
+            String syncTranslationResult = null;
+            /**
+             * 异步上传转译文件的任务完成时会触发回调,在WeiXinCorpController中的commonDevCallbackPost实现了对回调的处理,存储到corpwxJobResult表中
+             * 此处轮询查询本地数据库,检测到有任务的回调数据时继续执行查询操作
+             */
+            long t = System.currentTimeMillis();
+            while (i < 40) {
+                if (i < 10) {
+                    Thread.sleep(300);
+                } else if (i < 20){
+                    Thread.sleep(1000);
+                } else {
+                    Thread.sleep(3000);
+                }
+                System.out.println("i=="+i+", "+LocalDateTime.now());
+                CorpwxJobResult corpwxJobResult = corpwxJobCenter.get(jobId);
+                if (corpwxJobResult != null) {
+                    if (corpwxJobResult.getErrCode() == 0) {
+                        syncTranslationResult = wxCorpInfoService.getSyncTranslationResult(jobId);
+                        corpwxJobCenter.remove(jobId);
+                    } else {
+                        long t2 = System.currentTimeMillis();
+                        System.out.println("222企业微信转译报错:"+corpwxJobResult.getErrMsg()+",耗时:" + (t2 - t) + "ms");
+                        httpRespMsg.setError(corpwxJobResult.getErrMsg());
+                        return httpRespMsg;
+                    }
+                    break;
+                }
+                i++;
+            }
+            if (syncTranslationResult != null) {
+                long t2 = System.currentTimeMillis();
+                System.out.println("企业微信转译文件后地址是:"+syncTranslationResult+",耗时:" + (t2 - t) + "ms");
+                httpRespMsg.data = syncTranslationResult;
+            } else {
+                //httpRespMsg.setError("处理超时...");
+                httpRespMsg.setError(MessageUtils.message("request.outTime"));
+            }
+        }else if(dingding != null && dingding.getContactNeedTranslate() == 1){
+            User user = userMapper.selectById(request.getHeader("token"));
+            String mediaId = dingDingService.getTranslationMediaId(fileUrlSuffix,dingding);
+            String jobId = dingDingService.syncTranslation(mediaId,fileUrlSuffix, user.getDingdingUnionid(),dingding);
+            System.out.println("上传待转译文件到钉钉, jobId==" + jobId);
+            int i = 0;
+            String syncTranslationResult = null;
+            /**
+             * 异步上传转译文件的任务完成时会触发回调,在DingDingController中的callback实现了对回调的处理,存储到corpddJobCenter缓存中
+             * 此处轮询查询本地数据库,检测到有任务的回调数据时继续执行查询操作
+             */
+            long t = System.currentTimeMillis();
+            while (i < 30) {
+                if (i < 10) {
+                    Thread.sleep(300);
+                } else if (i < 20){
+                    Thread.sleep(1000);
+                } else {
+                    Thread.sleep(3000);
+                }
+                System.out.println("i=="+i+", "+LocalDateTime.now());
+                Integer status = corpddJobCenter.get(jobId);
+                if (status != null) {
+                    if (status == 1) {
+                        syncTranslationResult = dingDingService.getSyncTranslationResult(jobId,dingding);
+                        corpddJobCenter.remove(jobId);
+                    }
+                    break;
+                }
+                i++;
+            }
+            if (syncTranslationResult != null) {
+                long t2 = System.currentTimeMillis();
+                System.out.println("钉钉转译文件后地址是:"+syncTranslationResult+",耗时:" + (t2 - t) + "ms");
+                httpRespMsg.data = syncTranslationResult;
+            } else {
+                //httpRespMsg.setError("处理超时...");
+                httpRespMsg.setError(MessageUtils.message("request.outTime"));
+            }
+        }else {
+            httpRespMsg.data = resp;
+        }
+        return httpRespMsg;
+    }
+
+    public HttpRespMsg exportGeneralExcelByTitleAndListNew(String userId,WxCorpInfo wxCorpInfo, CompanyDingding dingding, String title, List<List<String>> list, String downloadPath) throws Exception {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        if (title.contains("/")) {
+            //文件名不能含有路径,得替换掉
+            title = title.replace("/", "@");
+        }
+        if (title.contains("\\")) {
+            //文件名不能含有路径,得替换掉
+            title = title.replace("\\", "@");
+        }
+        String resp = ExcelUtil.exportGeneralExcelByTitleAndList(title, list, downloadPath);
+        String fileUrlSuffix = title + ".xlsx";
+        if(wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1){
             String mediaId = wxCorpInfoService.getTranslationMediaId(fileUrlSuffix);
             String jobId = wxCorpInfoService.syncTranslation(wxCorpInfo.getCorpid(),mediaId,fileUrlSuffix, null);
             System.out.println("上传待转译文件到企业微信, jobId==" + jobId);
@@ -127,6 +230,7 @@ public class ExcelExportServiceImpl implements ExcelExportService {
                 long t2 = System.currentTimeMillis();
                 System.out.println("企业微信转译文件后地址是:"+syncTranslationResult+",耗时:" + (t2 - t) + "ms");
                 httpRespMsg.data = syncTranslationResult;
+                wxCorpInfoService.sendWXCorpMsg(wxCorpInfo,userId,syncTranslationResult, null, WxCorpInfoServiceImpl.TEXT_CARD_MSG__ASYNC_DWONLOAD);
             } else {
                 //httpRespMsg.setError("处理超时...");
                 httpRespMsg.setError(MessageUtils.message("request.outTime"));
@@ -176,6 +280,7 @@ public class ExcelExportServiceImpl implements ExcelExportService {
         return httpRespMsg;
     }
 
+
     public HttpRespMsg exportGeneralExcelForExpense(WxCorpInfo wxCorpInfo, CompanyDingding dingding, String title, List<List<String>> list, List<Map> mapList, String downloadPath) throws Exception {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         if (title.contains("/")) {

+ 3 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -5837,6 +5837,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         long t0 = System.currentTimeMillis();
         long fetchDataTime = 0;
         try {
+            long downloadCountStart = System.currentTimeMillis();
             String userId = request.getHeader("Token");
             User user = userMapper.selectById(userId);
             //检查模式,是否是一个项目多个工作事项的情况
@@ -6579,6 +6580,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 dataList.add(item);
                 rowNum++;
             }
+            long downloadCountEnd = System.currentTimeMillis();
+
             //生成Excel文件
             String fileUrlSuffix = (startDate==null?"":(startDate+MessageUtils.message("leave.to")+endDate))+MessageUtils.message("excel.workReport") + System.currentTimeMillis();
             httpRespMsg = excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo,dingding,fileUrlSuffix,dataList,path);

+ 49 - 5
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java

@@ -4,11 +4,11 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.management.platform.controller.WeiXinCorpController;
 import com.management.platform.entity.*;
 import com.management.platform.mapper.*;
 import com.management.platform.service.TimeTypeService;
-import com.management.platform.service.UserService;
 import com.management.platform.service.WxCorpInfoService;
 import com.management.platform.service.WxCorpTemplateService;
 import com.management.platform.task.SFTPAsyncUploader;
@@ -28,7 +28,8 @@ import org.springframework.web.util.UriComponentsBuilder;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
-import java.io.*;
+import java.io.File;
+import java.io.FileOutputStream;
 import java.math.BigDecimal;
 import java.net.URI;
 import java.text.SimpleDateFormat;
@@ -108,6 +109,8 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
     public static final int TEXT_CARD_MSG_EXPENSE_AGREE = 21;//费用报销审核通过
     public static final int TEXT_CARD_MSG_EXPENSE_DENY = 22;//费用报销审核驳回
 
+    public static final int TEXT_CARD_MSG__ASYNC_DWONLOAD = 23;//文件异步下载
+
     private static Object userLock = new Object();
 
     @Value("${suitId}")
@@ -195,15 +198,16 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
     //获取上传转移文件 获得的media_ia
     @Override
     public String getTranslationMediaId(String fileName) throws Exception {
+        System.out.println("in getTranslationMediaId method");
         String media_id="";
         URI url = UriComponentsBuilder.fromHttpUrl("https://qyapi.weixin.qq.com/cgi-bin/service/media/upload")
                 .queryParam("provider_access_token", getProviderAccessToken())
                 .queryParam("type", "file")
                 .build().toUri();
-        HttpHeaders headers = new HttpHeaders();
-        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
         //然后处理文件 通讯录id转译
         FileSystemResource fileSystemResource = new FileSystemResource(path+fileName);
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
         ContentDisposition build = ContentDisposition.builder("form-data").filename(fileSystemResource.getFilename()).build();
         headers.setContentDisposition(build);
         MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
@@ -220,9 +224,44 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                 throw new Exception(json.toJSONString());
             }
         }
+
+        System.out.println("end getTranslationMediaId method");
         return media_id;
     }
 
+    @Override
+    public String getTranslationJobId(String fileName, WxCorpInfo wxCorpInfo) throws Exception {
+        System.out.println("in getTranslationJobId method");
+        String jobId="";
+        //然后处理文件 通讯录id转译
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        Map<String,Object> params = new HashMap<>();
+        params.put("scene",1);
+        params.put("type","file");
+        params.put("filename",fileName);
+        params.put("url","https://worktime.ttkuaiban.com/upload/"+fileName);
+        params.put("md5","MD5");
+        String requestBody = JSONObject.toJSONString(params);
+        HttpEntity<String> entity = new HttpEntity<>(requestBody, headers);
+        String apiUrl = "https://qyapi.weixin.qq.com/cgi-bin/media/upload_by_url?access_token="+getCorpAccessToken(wxCorpInfo);
+        ResponseEntity<String> responseEntity = restTemplate.exchange(apiUrl, HttpMethod.POST, entity, String.class);
+
+        String responseBody = responseEntity.getBody();
+        System.out.println("getTranslationJobId Response from API: " + responseBody);
+        ObjectMapper objectMapper = new ObjectMapper();
+        Map responseObj = objectMapper.readValue(responseBody, Map.class);
+        if (responseEntity.getStatusCode() == HttpStatus.OK){
+            if(null != responseObj.get("errcode") && 0 == Integer.parseInt(responseObj.get("errcode").toString())){
+                jobId = responseObj.get("job_id").toString();
+            }else{
+                System.out.println("error Trans====== "+responseObj.get("errmsg").toString());
+            }
+        }
+        System.out.println("end getTranslationJobId method");
+        return jobId;
+    }
+
     //异步通讯录id转译
     @Override
     public String syncTranslation(String authCorpid, String mediaId,String outPutFileName,String outputFileFormat) throws Exception {
@@ -509,6 +548,7 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
 
     //获取第三方应用临时凭证
     private String getSuiteAccessToken() {
+        System.out.println("in getSuiteAccessToken=== ");
         if (WeiXinCorpController.SUITE_ACCESS_TOKEN == null || WeiXinCorpController.suiteTokenExpireTime < System.currentTimeMillis()) {
             //失效了,需要重新获取
             HttpHeaders headers = new HttpHeaders();
@@ -526,7 +566,7 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                     HttpMethod.POST, requestEntity, String.class);
             if (responseEntity.getStatusCode() == HttpStatus.OK) {
                 String resp = responseEntity.getBody();
-                System.out.println(resp);
+                System.out.println("getSuiteAccessToken resp ==="+resp);
                 JSONObject obj = JSONObject.parseObject(resp);
                 if (obj.getIntValue("errcode") == 0) {
                     WeiXinCorpController.SUITE_ACCESS_TOKEN = obj.getString("suite_access_token");
@@ -571,6 +611,7 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
 
     //获取企业AccessToken
     private String getCorpAccessToken(WxCorpInfo corpInfo) throws Exception {
+        System.out.println("in getCorpAccessToken=== ");
         if (corpInfo.getExpireTime().isBefore(LocalDateTime.now())) {
             String url = WeiXinCorpController.GET_CORP_ACCESSTOKEN_URL.replace("SUITE_ACCESS_TOKEN", getSuiteAccessToken());
             HttpHeaders headers = new HttpHeaders();
@@ -582,12 +623,15 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
 //            System.out.println("CompanyId为:"+corpInfo.getCompanyId());
 //            System.out.println("Corpid为:"+corpInfo.getCorpid());
 //            System.out.println("PermanentCode为:"+corpInfo.getPermanentCode());
+
+            System.out.println("getCorpAccessToken url=== "+url);
             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();
                 JSONObject json = JSONObject.parseObject(resp);
+                System.out.println("getCorpAccessToken Response from API: " + resp);
                 if (json.getIntValue("errcode") == 0) {
                     String access_token = json.getString("access_token");
                     corpInfo.setAccessToken(access_token);

+ 1 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/i18n/messages.properties

@@ -336,6 +336,7 @@ report.reportApp=审核通过了日报
 report.hourReportNoFilled=您{0}的工时报告还未填写
 report.lackCardTime=缺少考勤时长: {0}
 report.timeReachLimitError=填报工时不可超过考勤时长: {0}
+report.financial_report=财务已完成对{0}月日报的审核,无法提交。
 #模板相关
 Template.subProject=子项目
 Template.AlreadyExists=该模板名称已存在

+ 1 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/i18n/messages_en_US.properties

@@ -336,6 +336,7 @@ report.reportApp=Daily report approved
 report.hourReportNoFilled=Your work hour report for {0} has not been completed.
 report.lackCardTime=Lack attendance record: {0}
 report.timeReachLimitError=Report working time cannot be larger than attendance time: {0}
+report.financial_report=The financial department has completed the review of reports in {0}, it cannot be submitted.
 #模板相关
 Template.subProject=subproject
 Template.AlreadyExists=The template name already exists.

+ 7 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/FinancialAuditMapper.xml

@@ -18,4 +18,11 @@
         id, report_yrMnth, reviewer_id, reviewer_name, review_time, review_status, company_id
     </sql>
 
+    <select id="checkFinanceReview" resultType="java.lang.Integer">
+        select count(*)
+        from financial_audit
+        where company_id = #{companyId}
+          and instr(report_yrMnth,#{reportYM})>0
+          and review_status = 2
+    </select>
 </mapper>