Quellcode durchsuchen

Merge branch 'master' of http://47.100.37.243:10191/wutt/manHourHousekeeper

Lijy vor 2 Jahren
Ursprung
Commit
84d53df0ad

+ 11 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java

@@ -123,6 +123,17 @@ public class ReportController {
             worktimeItem.setEndTime(object.getString("endTime"));
             worktimeItemList.add(worktimeItem);
         }
+        //检查worktimeItemList是否有交叉
+        for (int i = 0; i < worktimeItemList.size(); i++) {
+            WorktimeItem worktimeItem = worktimeItemList.get(i);
+            for (int j = i + 1; j < worktimeItemList.size(); j++) {
+                WorktimeItem worktimeItem1 = worktimeItemList.get(j);
+                if (!(worktimeItem1.getEndTime().compareTo(worktimeItem.getStartTime()) < 0 || worktimeItem1.getStartTime().compareTo(worktimeItem.getEndTime()) > 0)) {
+                    msg.setError("时间段有交叉:"+worktimeItem1.getStartTime()+"-"+worktimeItem1.getEndTime()+"和"+worktimeItem.getStartTime()+"-"+worktimeItem.getEndTime());
+                    return msg;
+                }
+            }
+        }
         User user = userMapper.selectById(token);
         //按当前填报人所属部门或者全公司来匹配
         List<TimeAutoExclude> excludeTimeList = timeAutoExcludeMapper.selectList(new QueryWrapper<TimeAutoExclude>().eq("company_id", user.getCompanyId()));

+ 211 - 15
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserCorpwxTimeController.java

@@ -6,34 +6,34 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.management.platform.entity.*;
 import com.management.platform.entity.vo.SysRichFunction;
+import com.management.platform.entity.vo.WorktimeItem;
 import com.management.platform.mapper.*;
-import com.management.platform.service.DepartmentService;
-import com.management.platform.service.ExcelExportService;
-import com.management.platform.service.ReportService;
-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 com.management.platform.util.WorkDayCalculateUtils;
+import com.management.platform.service.*;
+import com.management.platform.util.*;
+import org.apache.commons.io.FileUtils;
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.ss.usermodel.*;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.format.annotation.DateTimeFormat;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
+import java.io.*;
 import java.math.BigDecimal;
 import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.time.format.TextStyle;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -76,6 +76,8 @@ public class UserCorpwxTimeController {
     ExcelExportService excelExportService;
     @Resource
     WxCorpInfoService wxCorpInfoService;
+    @Resource
+    UserCorpwxTimeService userCorpwxTimeService;
 
     @RequestMapping("/getMyDeptMembsData")
     public HttpRespMsg getMyDeptMembsData(String startDate, String endDate) {
@@ -349,6 +351,7 @@ public class UserCorpwxTimeController {
         allData.add(titles);
 
         //数据填充
+        DecimalFormat decimalFormat = new DecimalFormat("#0.0%");
         for (Map dataItem : list) {
             List<String> dataList = new ArrayList<>();
             dataList.add(ymonth);
@@ -361,8 +364,12 @@ public class UserCorpwxTimeController {
             double pt = (Double)dataItem.get("projectTime");
             dataList.add(""+wt);
             dataList.add(""+pt);
-            DecimalFormat decimalFormat = new DecimalFormat("#0.0%");
-            dataList.add(decimalFormat.format(pt/wt));
+            if (wt == 0) {
+                dataList.add(decimalFormat.format(0));
+            } else {
+                dataList.add(decimalFormat.format(pt/wt));
+            }
+
             allData.add(dataList);
         }
         String fileName = companyMapper.selectById(user.getCompanyId()).getCompanyName();
@@ -373,7 +380,7 @@ public class UserCorpwxTimeController {
         }
         //fileName += "_人员工时统计模板"+startDate+"至"+endDate;
         fileName = ymonth + fileName;
-        fileName += "项目工时占比";
+        fileName += "项目工时占比_" + System.currentTimeMillis();
         return excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo, fileName, allData, path);
     }
     @RequestMapping("/getPunchRecordBySelf")
@@ -410,5 +417,194 @@ public class UserCorpwxTimeController {
         msg.data=resultMap;
         return msg;
     }
+
+    @RequestMapping("/importCardTime")
+    public HttpRespMsg importCardTime(Integer companyId, MultipartFile multipartFile, HttpServletRequest request){
+        HttpRespMsg msg=new HttpRespMsg();
+        String token = request.getHeader("TOKEN");
+        User user = userMapper.selectById(token);
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
+        //然后处理文件
+        String fileName = multipartFile.getOriginalFilename();
+        File file = new File(fileName == null ? "file" : fileName);
+        InputStream inputStream = null;
+        OutputStream outputStream = null;
+        try {
+            inputStream = multipartFile.getInputStream();
+            outputStream = new FileOutputStream(file);
+            byte[] buffer = new byte[4096];
+            int temp = 0;
+            while ((temp = inputStream.read(buffer, 0, 4096)) != -1) {
+                outputStream.write(buffer, 0, temp);
+            }
+            inputStream.close();
+            outputStream.close();
+            //然后解析表格
+            Workbook workbook = WorkbookFactory.create(new FileInputStream(file));
+
+            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/M/d");
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/M/d");
+            //获取公司全部成员
+            List<User> allUserList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
+
+            Sheet sheet = workbook.getSheetAt(0);
+            //由于第一行需要指明列对应的标题
+            int rowNum = sheet.getLastRowNum();
+            if (rowNum == 0) {
+                //msg.setError("请填写工时数据");
+                msg.setError(MessageUtils.message("report.data"));
+                return msg;
+            }
+            List<String> userNameList=new ArrayList<>();
+            for (int rowIndex = 0; rowIndex <= rowNum; rowIndex++) {
+                Row row = sheet.getRow(rowIndex);
+                if (row == null) {
+                    continue;
+                }
+                if (ExcelUtil.isRowEmpty(row)) {
+                    continue;
+                }
+                String username = row.getCell(2).getStringCellValue().trim();
+                if(username.equals("员工")){
+                    continue;
+                }
+                if(!userNameList.contains(username)&&!username.equals("")){
+                    userNameList.add(username);
+                }
+            }
+            HttpRespMsg respMsg=new HttpRespMsg();
+            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1&&userNameList.size()>0){
+                System.out.println("参与搜素的人员列表"+userNameList);
+                respMsg = wxCorpInfoService.getBatchSearchUserInfo(wxCorpInfo, userNameList,null);
+                if(respMsg.code.equals("0")){
+                    msg.setError("姓名为["+String.valueOf(respMsg.data)+"]的人员存在重复,请使用工号!");
+                    return msg;
+                }
+            }
+            List<User> targetUserList= (List<User>) respMsg.data;
+            List<UserCorpwxTime> userCorpwxTimeList = new ArrayList<>();
+            int dataCount = 0;
+            for (int rowIndex = 0; rowIndex <= rowNum; rowIndex++) {
+                Row row = sheet.getRow(rowIndex);
+                if (row == null) {
+                    continue;
+                }
+                if (ExcelUtil.isRowEmpty(row)) {
+                    continue;
+                }
+                if (rowIndex == 0) {
+                    //第一行是标题,获取项目名称
+                    row.getCell(0).setCellType(CellType.STRING);
+
+                } else {
+                    dataCount++;
+                    //数据行
+                    for (int i=1;i<=5; i++) {
+                        if (row.getCell(i) != null) {
+                            row.getCell(i).setCellType(CellType.STRING);
+                        }
+                    }
+
+                    if (row.getCell(0) == null) {
+                        //msg.setError("第"+dataCount+"行缺少日期");
+                        msg.setError(MessageUtils.message("data.NullErrorByRow",dataCount));
+                        return msg;
+                    }
+                    boolean isDateFormat = row.getCell(0).getCellTypeEnum() == CellType.NUMERIC;
+                    String reportDate = isDateFormat?sdf.format(row.getCell(0).getDateCellValue()):row.getCell(0).getStringCellValue();
+                    if (StringUtils.isEmpty(reportDate)) {
+                        msg.setError(MessageUtils.message("data.NullErrorByRow",dataCount));
+                        return msg;
+                    }
+                    String username =row.getCell(2).getStringCellValue().trim();
+                    //检查人员是否存在
+                    Optional<User> any;
+                    if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                        Optional<User> optional = targetUserList.stream().filter(tl -> tl.getName().equals(username)).findFirst();
+                        any = allUserList.stream().filter(u -> u.getName().equals(username)||(u.getJobNumber()!=null&&u.getJobNumber().equals(username))||(optional.isPresent()&&u.getCorpwxUserid()!=null&&u.getCorpwxUserid().equals(optional.get().getCorpwxUserid()))).findAny();
+                    }else {
+                        any = allUserList.stream().filter(u -> u.getName().equals(username)||(u.getJobNumber()!=null&&u.getJobNumber().equals(username))).findAny();
+                    }
+                    if (!any.isPresent()) {
+                        //msg.setError("人员["+username+"]不存在,请先在组织结构中添加或者通过钉钉同步导入");
+                        msg.setError(MessageUtils.message("staff.peopleNullAndAdd",username));
+                        return msg;
+                    }
+                    User reportCreator = any.get();
+                    String startTime = row.getCell(3).getStringCellValue().trim();
+                    String endTime = row.getCell(4).getStringCellValue().trim();
+                    if (!startTime.contains(":")) {
+                        double t1 = Double.valueOf(startTime) * 24;
+                        //把以小时为单位的时间转化为时分格式, 类似09:00
+                        startTime = String.format("%02d:%02d", (int) t1, (int) ((t1 - (int) t1) * 60));
+                        double t2 = Double.valueOf(endTime) * 24;
+                        endTime = String.format("%02d:%02d", (int) t2, (int) ((t2 - (int) t2) * 60));
+                    }
+
+                    String workHours = row.getCell(5).getStringCellValue().trim();
+                    double workHoursDouble = Double.valueOf(workHours);
+                    UserCorpwxTime corpwxTime = new UserCorpwxTime();
+                    corpwxTime.setCorpwxUserid(reportCreator.getCorpwxUserid());
+                    corpwxTime.setName(reportCreator.getName());
+                    corpwxTime.setCreateDate(LocalDate.parse(reportDate, dtf));
+                    corpwxTime.setWorkHours(workHoursDouble);
+                    corpwxTime.setCardTime(workHoursDouble);
+                    corpwxTime.setStartTime(startTime);
+                    corpwxTime.setEndTime(endTime);
+                    corpwxTime.setCompanyId(reportCreator.getCompanyId());
+                    corpwxTime.setWxCorpid(wxCorpInfo.getCorpid());
+                    //计算周几
+                    corpwxTime.setWeekDay(corpwxTime.getCreateDate().getDayOfWeek().getValue());
+                    corpwxTime.setWeekDayTxt(DateTimeUtil.getWeekDayTxt(corpwxTime.getWeekDay()));
+                    userCorpwxTimeList.add(corpwxTime);
+                }
+            }
+            if (userCorpwxTimeList.size() > 0) {
+                userCorpwxTimeList.forEach(u->{
+                    userCorpwxTimeMapper.delete(new QueryWrapper<UserCorpwxTime>().eq("corpwx_userid", u.getCorpwxUserid())
+                            .eq("create_date", u.getCreateDate())
+                            .eq("wx_corpid", wxCorpInfo.getCorpid()));
+                });
+                userCorpwxTimeService.saveBatch(userCorpwxTimeList);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+            //msg.setError("文件处理出错");
+            msg.setError(MessageUtils.message("file.error"));
+            return msg;
+        } catch (NullPointerException e) {
+            e.printStackTrace();
+            //msg.setError("数据格式有误或存在空数据 导入失败");
+            msg.setError(MessageUtils.message("file.dataFormatError"));
+            return msg;
+        }catch (InvalidFormatException e) {
+            e.printStackTrace();
+            //msg.setError("文件格式错误,如果安装了加密软件需要先解密再上传");
+            msg.setError(MessageUtils.message("file.FormatErrorAndDecrypt"));
+            return msg;
+        }catch (EncryptedDocumentException e) {
+            e.printStackTrace();
+            //msg.setError("文件加密状态,需要先解除加密状态再上传");
+            msg.setError(MessageUtils.message("file.encryption"));
+            return msg;
+        } catch (Exception e) {
+            e.printStackTrace();
+            //msg.setError("发生其他错误:"+e.getMessage());
+            msg.setError(MessageUtils.message("other.errorByParameter",e.getMessage()));
+            return msg;
+        } finally {
+            //关闭流
+            try {
+                if (outputStream != null && inputStream != null) {
+                    outputStream.close();
+                    inputStream.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            file.delete();
+        }
+        return msg;
+    }
 }
 

+ 12 - 4
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java

@@ -1153,10 +1153,18 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                     double baseMorningWorkTime = 0;
                     double baseAfternoonWorkTime = 0;
                     if (corpInfo.getCorpid().equals("wpy9TkCAAAgNp4jvqxKTpXrhvwFvyFHg")) {
-                        JSONObject morTime = workRules.getJSONObject(0);
-                        baseMorningWorkTime = DateTimeUtil.getHoursFromSeconds(morTime.getIntValue("off_work_sec") - morTime.getIntValue("work_sec"));
-                        JSONObject aftTime = workRules.getJSONObject(1);
-                        baseAfternoonWorkTime = DateTimeUtil.getHoursFromSeconds(aftTime.getIntValue("off_work_sec") - aftTime.getIntValue("work_sec"));
+                        if (workRules.size() > 0) {
+                            JSONObject morTime = workRules.getJSONObject(0);
+                            baseMorningWorkTime = DateTimeUtil.getHoursFromSeconds(morTime.getIntValue("off_work_sec") - morTime.getIntValue("work_sec"));
+                        } else {
+                            baseMorningWorkTime = 3.0;
+                        }
+                        if (workRules.size() > 1) {
+                            JSONObject aftTime = workRules.getJSONObject(1);
+                            baseAfternoonWorkTime = DateTimeUtil.getHoursFromSeconds(aftTime.getIntValue("off_work_sec") - aftTime.getIntValue("work_sec"));
+                        } else {
+                            baseAfternoonWorkTime = 5.0;
+                        }
                     }
                     if (workRules.size() == 0) {
                         baseMorningStart = "09:00";

+ 8 - 7
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserCorpwxTimeMapper.xml

@@ -38,19 +38,20 @@
     </select>
 
     <select id="getUserDataRatioList" resultType="java.util.HashMap" >
-        SELECT user.id AS userId, user.`name` as username, user.`corpwx_userid` as corpwxUserid, SUM(a.work_hours) AS workHours, IFNULL(SUM(r.working_time), 0) AS projectTime
-        FROM user_corpwx_time a LEFT JOIN user ON user.`corpwx_userid` = a.corpwx_userid
-        left join report r on r.creator_id = user.id and r.create_date = a.create_date
-        WHERE DATE_FORMAT(a.create_date, '%Y%m') = #{ymonth}
-        AND (user.`is_active` = 1 OR (user.`is_active` = 0 AND DATE_FORMAT(user.`inactive_date`, '%Y%m') >= #{ymonth}))
-        AND a.company_id = #{companyId}
+        SELECT user.id AS userId, user.`name` as username, user.`corpwx_userid` as corpwxUserid, IFNULL(card_time.workHours, 0) as workHours, IFNULL(report_time.projectTime, 0)  AS projectTime FROM
+        user LEFT JOIN
+        (SELECT a.corpwx_userid, SUM(a.work_hours) AS workHours FROM user_corpwx_time a WHERE a.company_id = #{companyId} AND  DATE_FORMAT(a.create_date, '%Y%m') = #{ymonth} GROUP BY a.`corpwx_userid` ) card_time
+        ON user.`corpwx_userid` = card_time.corpwx_userid
+        LEFT JOIN (SELECT r.creator_id, SUM(r.working_time) AS projectTime FROM report r WHERE r.state = 1 and r.company_id = #{companyId} AND  DATE_FORMAT(r.create_date, '%Y%m') = #{ymonth} GROUP BY r.`creator_id` ) report_time
+        ON report_time.creator_id = user.id
+        WHERE user.company_id=#{companyId}
+        and  (user.`is_active` = 1 OR (user.`is_active` = 0 AND DATE_FORMAT(user.`inactive_date`, '%Y%m') > #{ymonth}))
         <if test="deptIds != null">
             AND user.`department_id` in
             <foreach collection="deptIds" item="deptId" open="(" separator="," close=")">
                 #{deptId}
             </foreach>
         </if>
-        group by user.id
         ORDER BY user.id ASC
     </select>
 

+ 55 - 2
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

@@ -1605,6 +1605,7 @@
                 <span style="font-size:16px;">{{$t('other.Batchimportofworkinghours')}}</span>
                 <el-link v-if="active==0"  style="float:right;margin-right:100px;" type="primary" @click="toView()">{{$t('other.viewLaborImportRecords')}}</el-link>
                 <el-link v-if="active==0"  style="float:right;margin-right:100px;" type="primary" @click="downloadProjectRatio">下载填报工时占比表</el-link>
+                <el-link v-if="active==0 && user.companyId == 469"  style="float:right;margin-right:100px;" type="primary" @click="importCardTimeVisi = true">导入考勤时长</el-link>
             </div>
             
             <span slot="footer">
@@ -1616,7 +1617,13 @@
             
             </span>
         </el-dialog>
-
+        <el-dialog title="导入考勤时长" v-if="importCardTimeVisi" :visible.sync="importCardTimeVisi"  width="200">
+            <p style="display: flex;justify-content: center;height:100px;">
+                <el-upload style="margin-top:10px;" ref="uploadCardTime"  action="#" :limit="1" :http-request="importCardTime" :show-file-list="false">
+                    <el-button type="primary" :underline="false" :loading="importingData">{{$t('other.chooseFileAndUpload')}}</el-button>
+                </el-upload>
+            </p>
+        </el-dialog>
         
         <el-dialog title="导出员工填报工时占比" v-if="exportUserRatio" :visible.sync="exportUserRatio"  width="200">
             <div>
@@ -1628,7 +1635,7 @@
                     ></el-date-picker>
             </div>
             <span slot="footer">
-            <el-button @click="confirmDownloadRatio" >导出</el-button>
+            <el-button @click="confirmDownloadRatio" :loading="startRatioExporting" :disabled="startRatioExporting">导出</el-button>
             </span>
         </el-dialog>
         <!--工时批量代填 -->
@@ -1728,6 +1735,8 @@
         },
         data() {
             return {
+                importCardTimeVisi: false,
+                startRatioExporting: false,
                 exportUserRatio: false,
                 ratioYmonth:null,
                 hasWrittenReport: false,
@@ -2378,11 +2387,13 @@
                 this.ratioYmonth = now.getFullYear()+monthStr;
             },
             confirmDownloadRatio() {
+                this.startRatioExporting = true;
                 this.http.post('/user-corpwx-time/exportProjectTimeRatio',{ 
                     ymonth: this.ratioYmonth
                 },
                 res => {
                     if (res.code == "ok") {
+                        this.startRatioExporting = false;
                         var filePath = res.data;
                         const a = document.createElement('a'); // 创建a标签
                         var data = filePath.split("/");
@@ -2391,6 +2402,7 @@
                         a.click(); //自执行点击事件
                         a.remove();
                     } else {
+                        this.startRatioExporting = false;
                         this.$message({
                             message: res.msg,
                             type: "error"
@@ -2508,6 +2520,47 @@
                     }
                 );
             },
+            importCardTime(item) {
+                //首先判断文件类型
+                let str = item.file.name.split(".");
+                let format = str[str.length - 1];
+                if (format != "xls" && format != "xlsx") {
+                    this.$message({
+                        message: this.$t('other.PleaseselecttheXLSorXLSXfile'),
+                        type: "error"
+                    });
+                } else {
+                    this.importingData = true;
+                    let formData = new FormData();
+                    formData.append("multipartFile", item.file);
+                    formData.append("companyId", this.user.companyId);
+                    this.http.uploadFile('/user-corpwx-time/importCardTime', formData,
+                    res => {
+                        this.$refs.uploadCardTime.clearFiles();
+                        this.importingData = false;
+                        if (res.code == "ok") {
+                            //换成弹出框,以免有人等了半天回来啥也没看到
+                            this.$message({
+                            message: '导入考勤时长成功',
+                            type: "success"
+                            });
+                        } else {
+                            this.$message({
+                            message: res.msg,
+                            type: "error"
+                            });
+                        }
+                    },
+                    error => {
+                        this.$refs.upload.clearFiles();
+                        this.listLoading = false;
+                        this.$message({
+                            message: error,
+                            type: "error"
+                        });
+                    });
+                }
+            },
             batchImportWxData(item) {
                 //首先判断文件类型
                 let str = item.file.name.split(".");