瀏覽代碼

Merge remote-tracking branch 'origin/master'

Guo1B0 1 年之前
父節點
當前提交
bc8bdc19f2

+ 10 - 4
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserWithBeisenController.java

@@ -234,11 +234,11 @@ public class UserWithBeisenController {
         JSONObject item = BeiSenUtils.getAttendanceStatisticWithUser(createDate,withBeisen.get().getUserId(), beisenConfig.getAppKey(), beisenConfig.getAppSecret());
         JSONArray allOverTimeList = BeiSenUtils.getScheduledOverTimeRangeList(createDate,createDate,withBeisen.get().getUserId(), beisenConfig.getAppKey(), beisenConfig.getAppSecret());
         //获取当前数据下的人员工号对应到工时管家
-        String cardNumber = item.getString("staffId");
-        Optional<User> first = userList.stream().filter(f -> f.getJobNumber().equals(cardNumber)).findFirst();
+        Optional<User> first = userList.stream().filter(f -> f.getJobNumber().equals(withBeisen.get().getJobNumber())).findFirst();
+        System.out.println("考勤数据:"+item.toString());
         //todo: 获取早晚打卡时间
-        String firstCard = item.getString("firstCard");
-        String lastCard = item.getString("lastCard");
+        String firstCard = item.getString("firstCardIncludeFillCheck").split(" ")[1];
+        String lastCard = item.getString("lastCardIncludeFillCheck").split(" ")[1];
         //获取最晚下班时间
         if(first.isPresent()){
             boolean workDay = WorkDayCalculateUtils.isWorkDay(LocalDate.parse(createDate,df));
@@ -249,6 +249,10 @@ public class UserWithBeisenController {
             if(beisen.isPresent()){
                 List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
                         && a.getIntValue("ApproveStatus") == 2).collect(Collectors.toList());
+                System.out.println("加班时长数据:"+overTimeList.toString());
+                for (JSONObject jsonObject : overTimeList) {
+                    System.out.println("加班时长:"+jsonObject.getDouble("ActualOverTimeDuration"));
+                }
                 if(overTimeList.size()>0){
                     double actualOverTimeDuration = overTimeList.stream().mapToDouble(i -> i.getDouble("ActualOverTimeDuration")).sum();
                     if(workDay){
@@ -271,6 +275,8 @@ public class UserWithBeisenController {
             }
             userFvTimeService.saveOrUpdate(userFvTime);
             msg.setData(userFvTime);
+        } else {
+            msg.setError("未找到对应员工信息:staffId="+withBeisen.get().getUserId());
         }
         return msg;
     }

+ 11 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/ProjectVO.java

@@ -1,12 +1,15 @@
 package com.management.platform.entity.vo;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.management.platform.entity.Participation;
 import com.management.platform.entity.ParticipationUser;
 import com.management.platform.entity.Project;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
 
+import java.time.LocalDate;
 import java.util.List;
 import java.util.Map;
 
@@ -23,4 +26,12 @@ public class ProjectVO extends Project {
     String projectAuditorName;
     String projectAuditorId;
     List<Map<String,Object>> providerInfoList;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate minFilingDate;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate maxFilingDate;
 }

+ 15 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java

@@ -639,6 +639,10 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                     totalProgress = totalProgress/100/100;
                     projectVO.setProgress(totalProgress);
                 }
+                Optional<LocalDate> maxFillDate = reportList.stream().filter(report -> report.getCreateDate() != null && projectVO.getId().equals(report.getProjectId())).map(Report::getCreateDate).max(Comparator.comparing(date -> date.toEpochDay()));
+                Optional<LocalDate> minFillDate = reportList.stream().filter(report -> report.getCreateDate() != null && projectVO.getId().equals(report.getProjectId())).map(Report::getCreateDate).min(Comparator.comparing(date -> date.toEpochDay()));
+                maxFillDate.ifPresent(projectVO::setMaxFilingDate);
+                minFillDate.ifPresent(projectVO::setMinFilingDate);
 
                 list.add(projectVO);
             }
@@ -2751,12 +2755,16 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
         List<Project> projectList = projectMapper.selectList(queryWrapper);
         List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
+        List<Report> reportList = reportMapper.selectList(new QueryWrapper<Report>().select("id, create_date, project_id, working_time").eq("company_id",companyId).and(wrapper -> wrapper.eq("state", 0).or().eq("state", 1).or().eq("state", 3)));
         List<ProjectVO> list = new ArrayList<>();
         //String[] statusNames = {"-","进行中","已完成","已撤销","暂停"};
         String[] statusNames = {"-",MessageUtils.message("excel.onGoing"),MessageUtils.message("excel.complete"),MessageUtils.message("excel.revoke"),MessageUtils.message("excel.pause")};
         List<List<String>> exportList = new ArrayList<>();
         //String[] titles = {"项目编号", "项目名称", "负责人", "项目金额(元)", "状态","计划开始时间", "计划结束时间", "完成度"};
-        String[] titles = {MessageUtils.message("entry.projectId"), MessageUtils.message("entry.projectName"), MessageUtils.message("excel.charge"), MessageUtils.message("excel.projectAmount")+"(元)", MessageUtils.message("leave.status"),MessageUtils.message("excel.planStart"), MessageUtils.message("excel.planEnd"), MessageUtils.message("excel.degree")};
+        String[] titles = {MessageUtils.message("entry.projectId"), MessageUtils.message("entry.projectName"),
+                MessageUtils.message("excel.charge"), MessageUtils.message("excel.projectAmount")+"(元)", MessageUtils.message("leave.status")
+                ,MessageUtils.message("excel.planStart"), MessageUtils.message("excel.planEnd"),
+                MessageUtils.message("excel.minFillDate"), MessageUtils.message("excel.maxFillDate"),MessageUtils.message("excel.degree")};
         exportList.add(Lists.list(titles));
         for (Project project : projectList) {
             List<String> data = new ArrayList<>();
@@ -2779,6 +2787,12 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             data.add(project.getStatus()==null?"":statusNames[project.getStatus()]);
             data.add(project.getPlanStartDate() != null?df.format(project.getPlanStartDate()):"");
             data.add(project.getPlanEndDate() != null?df.format(project.getPlanEndDate()):"");
+
+            Optional<LocalDate> maxFillDate = reportList.stream().filter(report -> report.getCreateDate() != null && project.getId().equals(report.getProjectId())).map(Report::getCreateDate).max(Comparator.comparing(date -> date.toEpochDay()));
+            Optional<LocalDate> minFillDate = reportList.stream().filter(report -> report.getCreateDate() != null && project.getId().equals(report.getProjectId())).map(Report::getCreateDate).min(Comparator.comparing(date -> date.toEpochDay()));
+            data.add(minFillDate.map(String::valueOf).orElse(""));
+            data.add(maxFillDate.map(String::valueOf).orElse(""));
+
             data.add(project.getProgress() != null?project.getProgress()+"%" :"");
             exportList.add(data);
         }

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

@@ -630,6 +630,8 @@ excel.remarks=备注
 excel.charge=负责人
 excel.projectAmount=项目金额
 excel.planStart=计划开始时间
+excel.minFillDate=首次填报日期
+excel.maxFillDate=最后填报日期
 excel.planEnd=计划结束时间
 excel.degree=完成度
 excel.genExp=一般费用

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

@@ -631,6 +631,8 @@ excel.charge=person in charge
 excel.projectAmount=Project amount
 excel.planStart=Planned start time
 excel.planEnd=Planned end time
+excel.minFillDate=min fill Date
+excel.maxFillDate=max fill Date
 excel.degree=Degree of completion
 excel.genExp=General expenses
 excel.traExp=Travel expenses

+ 3 - 0
fhKeeper/formulahousekeeper/timesheet/src/i18n/en.json

@@ -182,6 +182,7 @@
     "exportingTimeStatistics": "Export labor statistics"
   },
   "other": {
+    "kaoqingTimeTip": "not include pending overtime and holiday time",
     "customerService": "Customer service",
     "sweepWeChatYards": "Sweep WeChat yards",
     "messageCenter": "message center",
@@ -567,6 +568,8 @@
   "schedulestarttime": "plan start time",
   "completeness": "Completeness",
   "scheduleendtime": "planned end time",
+  "minFillDate": "min fill Date",
+  "maxFillDate": "max fill Date",
   "artificialcost": "Labor cost",
   "expirationdate": "expiration date",
   "shi-ji-gong-shi": "Actual working hours",

+ 3 - 0
fhKeeper/formulahousekeeper/timesheet/src/i18n/zh.json

@@ -184,6 +184,7 @@
     "exportingTimeStatistics": "导出工时统计"
   },
   "other": {
+    "kaoqingTimeTip": "工作时长不包含未审批加班及休假",
     "customerService": "咨询客服",
     "sweepWeChatYards": "微信扫码",
     "messageCenter": "消息中心",
@@ -568,6 +569,8 @@
   "he-tong-jine-yuan": "合同金额(元)",
   "schedulestarttime": "计划开始时间",
   "scheduleendtime": "计划结束时间",
+  "minFillDate": "首次填报日期",
+  "maxFillDate": "最后填报日期",
   "completeness": "完成度",
   "shi-ji-gong-shi": "实际工时",
   "expirationdate": "截止日期",

+ 11 - 1
fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue

@@ -246,6 +246,16 @@
                         {{scope.row.planEndDate}}
                     </template>
                 </el-table-column>
+                <el-table-column prop="minFilingDate" :label="$t('minFillDate')" >
+                    <template slot-scope="scope">
+                        {{scope.row.minFilingDate}}
+                    </template>
+                </el-table-column>
+                <el-table-column prop="maxFilingDate" :label="$t('maxFillDate')" >
+                    <template slot-scope="scope">
+                        {{scope.row.maxFilingDate}}
+                    </template>
+                </el-table-column>
                 <el-table-column prop="progress" :label="$t('completeness')">
                     <template slot-scope="scope">
                         {{scope.row.progress==null?"-":scope.row.progress}}%
@@ -2338,7 +2348,7 @@ export default {
         } else if(this.ins == 24) {
           fName = '分组耗用进度表' + '.xlsx'
           url = "/project/exportGroupExpendProcessList"
-          this.proJuctId ? parameter.projectId = this.proJuctId : ''
+          this.proJuctId ? sl.projectId = this.proJuctId : ''
           sl.startDate = this.rangeDatas[0]
           sl.endDate = this.rangeDatas[1]
         } else if(this.ins == 25) {

+ 45 - 6
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

@@ -18,6 +18,9 @@
                                 <br>
                                 <span style="font-size:10px;text-align:center;color:#999;">{{item.weekDay}}</span>
                                 <span class="chooseDate" v-if="index == choseDay"></span>
+                                <!-- <el-tooltip v-if="index == choseDay" effect="dark" content="填报时长超过北森考勤时长" placement="top-start">
+                                <i class="el-icon-warning" style="color:red;"></i>
+                                </el-tooltip> -->
                                 </div>
                             </div>
                             </span>
@@ -401,7 +404,13 @@
                         <span v-if="reportTimeType.type == 3 && user.company.companyName != mingyiName">{{$t('time.hour')}}</span>
                         <!-- <span v-if="isBatch && user.company.companyName != mingyiName">, {{$t('other.fillInTheTotal')}} {{jsTime.toFixed(1)}} {{$t('time.hour')}}</span> -->
                         <span v-if="isBatch && user.company.companyName != mingyiName">, {{$t('other.fillInTheTotal')}} <el-input v-model="jsTime" @change="onBatchTimeChange" style="width:80px;"/> {{$t('time.hour')}}</span>
-                        <span v-if="workForm.time">{{$t('other.attendancePunch')}}: {{workForm.time.startTime}}-{{workForm.time.endTime}}, 工作{{workForm.time.workHours}}{{$t('time.hour')}}
+                        
+                        <!-- AI智能填报 -->
+                        <el-button type="primary" @click="getAIReport()" v-if="!hasWrittenReport" style="margin-left:5px;" >智能填报</el-button>
+                    </el-form-item>
+                    <!--考勤时长显示-->
+                    <el-form-item :label="$t('other.attendancePunch')" v-if="workForm.time || user.companyId == 5978">
+                        <span v-if="workForm.time">{{workForm.time.startTime}}-{{workForm.time.endTime}}, 工作{{workForm.time.workHours}}{{$t('time.hour')}}
                         <span v-if="workForm.time.askLeaveTime">|&nbsp;请假{{ workForm.time.askLeaveTime }}小时</span>
                         </span>
                         <!--批量填报和批量代填不显示考勤记录-->
@@ -414,8 +423,10 @@
                         <el-button type="default" style="margin-left:5px;" size="small" :loading="syncTimeLoading" 
                         v-if="isBatch && user.company.companyName === mingyiName" icon="el-icon-refresh" 
                                 @click="refreshAttendance(workForm.createDate)"></el-button>
-                        <!-- AI智能填报 -->
-                        <el-button type="primary" @click="getAIReport()" v-if="!hasWrittenReport" style="margin-left:5px;" >智能填报</el-button>
+                        <el-button type="default" style="margin-left:5px;" size="small" :loading="syncTimeLoading" 
+                        v-if="!isBatch && user.companyId === 5978" icon="el-icon-refresh" 
+                                @click="refreshBeiSengAttendance(workForm.createDate)"></el-button>
+                        <span v-if="user.companyId==5978" style="margin-left:5px;color:#20a0ff;"><i class="el-icon-warning"></i>{{$t('other.kaoqingTimeTip')}}</span>
                     </el-form-item>
                     <!-- 000000 -->
                     <div v-for="(domain, index) in workForm.domains" :key="domain.id" :style="index>0?'margin-top:10px;':''">
@@ -534,7 +545,7 @@
                         </el-form-item>
                         <el-form-item v-if="user.company.packageProject == 1&& (user.company.nonProjectSimple==0 || (user.company.nonProjectSimple==1&&domain.isPublic != 1))">
                             <template slot="label">
-                                <span style="color:#FF0000;" v-if="user.timeType.reportAuditType == 1 ||user.timeType.reportAuditType == 2">*</span>
+                                <span style="color:#FF0000;" v-if="user.timeType.taskGroupRequired == 1 || user.timeType.reportAuditType == 1 || user.timeType.reportAuditType == 2">*</span>
                                 <span >{{$t('lable.taskGrouping')}}</span>
                             </template>
                             <!-- 任务分组 -->
@@ -772,7 +783,11 @@
                                     <el-option v-for="item in timeBasecostList" :label="item.name" :value="item.id" :key="item.id"></el-option>
                                 </el-select>
                             </el-form-item>
-                            <el-form-item :label="$t('lable.taskGrouping')" v-if="user.company.packageProject == 1">
+                            <el-form-item v-if="user.company.packageProject == 1">
+                                <template slot="label">
+                                    <span style="color:#FF0000;" v-if="user.timeType.taskGroupRequired == 1">*</span>
+                                    <span >{{$t('lable.taskGrouping')}}</span>
+                                </template>
                                 <!-- 任务分组 -->
                                 <el-select v-model="domain.groupId" :placeholder="$t('defaultText.pleaseSelectaTaskGroup')" style="width:200px;" clearable="true" 
                                 :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)" @change="getGroupStages(domain, index)">
@@ -2796,6 +2811,30 @@
                     })
                 })
             },
+            refreshBeiSengAttendance(workdate) {
+                 if (!workdate) return;
+                this.syncTimeLoading = true;
+                this.http.post('/user-with-beisen/syncAttendanceFromBeisen',{
+                    startDate: workdate,
+                    endDate: workdate
+                },res => {
+                    this.syncTimeLoading = false;
+                    if(res.code == 'ok'){
+                        this.workForm.time = res.data;
+                    }else {
+                        this.$message({
+                            message: res.msg,
+                            type: 'error'
+                        })
+                    }
+                },err => {
+                    this.syncTimeLoading = false;
+                    this.$message({
+                        message: err,
+                        type: 'error'
+                    })
+                })
+            },
             weeklyFilledTimeClick(parameterDate){ //按周填报-已填工时-点击
                 this.weeklyFilledTimeDialog = true
                 this.weeklyFilledTimeLoading = true
@@ -7742,7 +7781,7 @@
                             }
                             if(this.user.timeType.taskGroupRequired == 1 && !this.workForm.domains[i].groupId) {
                                 this.$message({
-                                    message: this.$t('defaultText.pleaseset') + "["+this.workForm.domains[i].projectName+"]"+this.$t('message.Projectgroupleader'),
+                                    message: `请选择【${this.workForm.domains[i].projectName}】项目下的任务分组`,
                                     type: "error"
                                 });
                                 return