소스 검색

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

QuYueTing 9 달 전
부모
커밋
fdec464eaf
40개의 변경된 파일32097개의 추가작업 그리고 12474개의 파일을 삭제
  1. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm/node_modules.zip
  2. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/index.vue
  3. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/type.d.ts
  4. 30882 11721
      fhKeeper/formulahousekeeper/management-crm/crm.log
  5. 2 2
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ClueController.java
  6. 3 4
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/CustomController.java
  7. 4 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Clue.java
  8. 1 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/ClueService.java
  9. 148 78
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/BusinessOpportunityServiceImpl.java
  10. 69 30
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ClueServiceImpl.java
  11. 140 65
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/CustomServiceImpl.java
  12. 14 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ProductServiceImpl.java
  13. 14 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SalesOrderServiceImpl.java
  14. 11 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/TaskServiceImpl.java
  15. 3 3
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/BusinessOpportunityMapper.xml
  16. 6 6
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/CustomMapper.xml
  17. 2 1
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/TaskMapper.xml
  18. 1 1
      fhKeeper/formulahousekeeper/management-platform-import/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  19. 2 2
      fhKeeper/formulahousekeeper/management-platform-import/src/main/resources/application.yml
  20. 6 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java
  21. 33 236
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserWithBeisenController.java
  22. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java
  23. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java
  24. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/UserWithBeisenService.java
  25. 61 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  26. 314 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserWithBeisenServiceImpl.java
  27. 1 254
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  28. 46 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  29. 7 7
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/controller/ReportController.java
  30. 1 1
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/mapper/ReportMapper.java
  31. 1 1
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/ReportService.java
  32. 11 2
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  33. 5 2
      fhKeeper/formulahousekeeper/management-workshop/src/main/resources/mapper/ReportMapper.xml
  34. 42 13
      fhKeeper/formulahousekeeper/timesheet-workshop/src/views/workReport/daily.vue
  35. 59 0
      fhKeeper/formulahousekeeper/timesheet/src/components/echartsEchar.vue
  36. 4 0
      fhKeeper/formulahousekeeper/timesheet/src/http.js
  37. 36 28
      fhKeeper/formulahousekeeper/timesheet/src/views/Home.vue
  38. 87 0
      fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/echartsData.js
  39. 70 6
      fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue
  40. 2 2
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/transferWorkingHours.vue

BIN
fhKeeper/formulahousekeeper/customerBuler-crm/node_modules.zip


+ 2 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/index.vue

@@ -16,7 +16,7 @@
               <el-input v-model="businessOpportunityForm.customerName" clearable placeholder="请输入"></el-input>
             </el-form-item>
             <el-form-item label="联系人">
-              <el-input v-model="businessOpportunityForm.contactPerson" clearable placeholder="请输入"></el-input>
+              <el-input v-model="businessOpportunityForm.contactsName" clearable placeholder="请输入"></el-input>
             </el-form-item>
             <el-form-item label="产品">
               <el-select v-model="businessOpportunityForm.product" placeholder="请选择" clearable>
@@ -242,7 +242,7 @@ const businessOpportunityForm = reactive<businessOpportunityFormType>({
   name: '',
   stageId: '',
   customerName: '',
-  contactPerson: '',
+  contactsName: '',
   product: '',
   inchargerId: '',
   startTime: getFirstDayOfMonth(new Date()),

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/type.d.ts

@@ -3,7 +3,7 @@ interface businessOpportunityFormType {
   name: string;
   stageId: string | number;
   customerName: string;
-  contactPerson: string;
+  contactsName: string;
   product: string | number;
   inchargerId: string | number;
   startTime: string | number;

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 30882 - 11721
fhKeeper/formulahousekeeper/management-crm/crm.log


+ 2 - 2
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ClueController.java

@@ -181,8 +181,8 @@ public class ClueController {
     }
 
     @RequestMapping("/importData")
-    public HttpRespMsg importData(MultipartFile multipartFile){
-        return clueService.importData(multipartFile);
+    public HttpRespMsg importData(MultipartFile multipartFile,HttpServletRequest request){
+        return clueService.importData(multipartFile, request);
     }
     @Value(value = "${upload.path}")
     private String path;

+ 3 - 4
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/CustomController.java

@@ -246,11 +246,10 @@ public class CustomController {
 
     @RequestMapping("getAll")
     public Object getAll(HttpServletRequest request) {
-        User user = userMapper.selectById(request.getHeader("Token"));
+        HttpRespMsg list = list(new Custom(), request);
+        Map<String, Object> data = (Map<String, Object>) list.getData();
         HttpRespMsg msg = new HttpRespMsg();
-        msg.setMsg("操作成功");
-        msg.setData(
-                customMapper.selectList(new QueryWrapper<Custom>().eq("company_id", user.getCompanyId()))
+        msg.setData(data.get("data")
         );
         return msg;
     }

+ 4 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Clue.java

@@ -10,6 +10,8 @@ import java.util.List;
 
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
 import lombok.experimental.Accessors;
 
 /**
@@ -23,6 +25,8 @@ import lombok.experimental.Accessors;
 @Data
 @EqualsAndHashCode(callSuper = false)
 @Accessors(chain = true)
+@Setter
+@Getter
 public class Clue extends Model<Clue> {
 
     private static final long serialVersionUID=1L;

+ 1 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/ClueService.java

@@ -54,7 +54,7 @@ public interface ClueService extends IService<Clue> {
 
     Object downFile(UploadFile file, HttpServletRequest request, HttpServletResponse response);
 
-    HttpRespMsg importData(MultipartFile multipartFile);
+    HttpRespMsg importData(MultipartFile multipartFile,HttpServletRequest request);
 
     HttpRespMsg exportData(Clue clue) throws Exception;
 

+ 148 - 78
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/BusinessOpportunityServiceImpl.java

@@ -38,6 +38,9 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.math.BigDecimal;
 import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.ZoneId;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -82,6 +85,9 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
     @Resource
     private SysDictMapper sysDictMapper;
 
+    @Resource
+    private StageMapper stageMapper;
+
     @Override
     public List<BusinessOpportunity> getAll(BusinessOpportunity bo) {
         return bOMapper.selectAllList(bo);
@@ -432,16 +438,28 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
         bOMapper.deleteBatchIds(ids);
     }
 
+
+    @Autowired
+    private ContactsMapper contactsMapper;
+    @Autowired
+    private CustomMapper customMapper;
     @Override
     public HttpRespMsg importData(MultipartFile multipartFile) {
-        HttpRespMsg msg = new HttpRespMsg();
+        HttpRespMsg msg=new HttpRespMsg();
+        if(!multipartFile.getOriginalFilename().endsWith(".xlsx")){
+            msg.setError("文件格式错误,请使用.xlsx格式的Excel文件进行导入");
+            return msg;
+        }
         String fileName = multipartFile.getOriginalFilename();
         File file = new File(fileName == null ? "file" : fileName);
         User user = userMapper.selectById(request.getHeader("token"));
         Integer companyId = user.getCompanyId();
         WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, companyId));
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
-        List<SysDict> sysDictOfClueSources = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "ClueSources"));
+        List<Stage> stage = stageMapper.selectList(null);
+        List<Contacts> contacts = contactsMapper.selectList(new LambdaQueryWrapper<Contacts>().eq(Contacts::getCompanyId, user.getCompanyId()).eq(Contacts::getIsDelete, 0).orderByDesc(Contacts::getId));
+        List<Custom> customs = customMapper.selectList(new LambdaQueryWrapper<Custom>().eq(Custom::getCompanyId, user.getCompanyId()).eq(Custom::getIsDelete, 0).orderByDesc(Custom::getId));
+
         InputStream inputStream = null;
         OutputStream outputStream = null;
         try {
@@ -461,17 +479,36 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
             //由于第一行需要指明列对应的标题
             int rowNum = sheet.getLastRowNum();
             //获取当前表单模板 校验规则
-            SysForm sysForm = sysFormMapper.selectOne(new LambdaQueryWrapper<SysForm>().eq(SysForm::getCode, "Thread").eq(SysForm::getCompanyId, companyId).eq(SysForm::getIsCurrent, 1));
-            if (sysForm == null) {
+            SysForm sysForm = sysFormMapper.selectOne(new LambdaQueryWrapper<SysForm>().eq(SysForm::getCode, "business").eq(SysForm::getCompanyId, companyId).eq(SysForm::getIsCurrent, 1));
+            if(sysForm==null){
                 msg.setError("当前模块未配置自定义模板,需先完成配置");
                 return msg;
             }
             String config = sysForm.getConfig();
             JSONObject configOb = JSON.parseObject(config);
             JSONArray configObJSONArray = configOb.getJSONArray("list");
-            List<String> userNameList = new ArrayList<>();
-            HttpRespMsg respMsg = new HttpRespMsg();
-            for (int rowIndex = 0; rowIndex <= rowNum; rowIndex++) {
+            //可能存在栅格布局的情况需要特殊处理
+            List<String> modelNameList=new ArrayList<>();
+            for (int i = 0; i < configObJSONArray.size(); i++) {
+                JSONObject jsonObject = configObJSONArray.getJSONObject(i);
+                if(jsonObject.getString("type").equals("grid")){
+                    JSONArray columns = jsonObject.getJSONArray("columns");
+                    for (int i1 = 0; i1 < columns.size(); i1++) {
+                        JSONObject columnsJSONObject = columns.getJSONObject(i1);
+                        JSONArray list = columnsJSONObject.getJSONArray("list");
+                        for (int i2 = 0; i2 < list.size(); i2++) {
+                            JSONObject object = list.getJSONObject(i2);
+                            modelNameList.add(object.getString("model"));
+                        }
+                    }
+                }else {
+                    modelNameList.add(jsonObject.getString("model"));
+                }
+            }
+            List<BusinessOpportunity> importProductList = new ArrayList<>();
+            List<String> userNameList=new ArrayList<>();
+            HttpRespMsg respMsg=new HttpRespMsg();
+            for (int rowIndex = 1; rowIndex <= rowNum; rowIndex++) {
                 XSSFRow row = sheet.getRow(rowIndex);
                 if (row == null) {
                     continue;
@@ -483,37 +520,25 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
                 //获取到当前行的列数据
                 int cellNum = row.getLastCellNum();
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
-                    String modelName = item.getString("model");
+                    String modelName = modelNameList.get(i);
                     XSSFCell cell = row.getCell(i);
-                    if (cell != null) {
-                        switch (item.getString("type")) {
-//                            case "time":cell.setCellType(CellType.NUMERIC);
-//                                break;
-                            default:
-                                cell.setCellType(CellType.STRING);
-                        }
-                    }
-                    if (modelName.equals("inchargerId")) {
-                        System.out.println("=====");
-                        System.out.println(modelName);
-                        System.out.println(cell.toString());
-                        if (!StringUtils.isEmpty(cell.getStringCellValue())) {
+                    if(modelName.equals("inchargerId")){
+                        if(!org.springframework.util.StringUtils.isEmpty(cell.getStringCellValue())){
                             userNameList.add(cell.getStringCellValue());
                         }
                     }
 
                 }
             }
-            System.out.println("参与搜索的人员列表" + userNameList + userNameList.size());
-            if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1 && userNameList.size() > 0) {
-                respMsg = wxCorpInfoService.getBatchSearchUserInfo(wxCorpInfo, userNameList, null);
-                if (respMsg.code.equals("0")) {
-                    msg.setError("姓名为[" + String.valueOf(respMsg.data) + "]的人员存在重复,请使用工号!");
+            System.out.println("参与搜素的人员列表"+userNameList + userNameList.size());
+            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1&&userNameList.size()>0){
+                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<User> targetUserList= (List<User>) respMsg.data;
             //直接忽略空行 从row1开始
             for (int rowIndex = 1; rowIndex <= rowNum; rowIndex++) {
                 XSSFRow row = sheet.getRow(rowIndex);
@@ -526,89 +551,134 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
                 }
                 //获取到当前行的列数据
                 int cellNum = row.getLastCellNum();
-                BusinessOpportunity bo = new BusinessOpportunity();
-                bo.setCompanyId(companyId);
-                bo.setCreateTime(new Date());
-                bo.setCreatorId(user.getId());
+                BusinessOpportunity product=new BusinessOpportunity();
+                product.setCompanyId(companyId);
+                product.setCreatorId(user.getId());
+                product.setCreateTime(new Date());
+                JSONArray objects=new JSONArray();
+                for (int i = 0; i < configObJSONArray.size(); i++) {
+                    JSONObject jsonObject = configObJSONArray.getJSONObject(i);
+                    if(jsonObject.getString("type").equals("grid")){
+                        JSONArray columns = jsonObject.getJSONArray("columns");
+                        for (int i1 = 0; i1 < columns.size(); i1++) {
+                            JSONObject jsonObject1 = columns.getJSONObject(i1).getJSONArray("list").getJSONObject(0);
+                            objects.add(jsonObject1);
+                        }
+                    }else {
+                        objects.add(jsonObject);
+                    }
+                }
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
+                    JSONObject item = objects.getJSONObject(i);
                     String modelName = item.getString("model");
                     String className = modelName.substring(0, 1).toUpperCase() + modelName.substring(1);
-                    String getter = "get" + className;
-                    String setter = "set" + className;
+                    String getter="get"+className;
+                    String setter="set"+className;
                     XSSFCell cell = row.getCell(i);
-                    if (cell != null) {
-                        switch (item.getString("type")) {
+                    if(cell!=null){
+                        switch (item.getString("type")){
 //                            case "time":cell.setCellType(CellType.NUMERIC);
 //                                break;
-                            default:
-                                cell.setCellType(CellType.STRING);
+                            //默认读取所有数据都是文本格式
+                            default:cell.setCellType(CellType.STRING);
                         }
                     }
-                    //校验当前列是否为必填
-                    JSONObject options = item.getJSONObject("options");
-                    JSONObject rules = options.getJSONObject("rules");
-                    Boolean required = rules.getBoolean("required");
-                    if (required) {
-                        if (StringUtils.isEmpty(cell.getStringCellValue())) {
-                            msg.setError(item.getString("label") + "值不能为空值");
-                            return msg;
-                        }
-                    }
-                    if (modelName.equals("inchargerId")) {
-                        if (!StringUtils.isEmpty(cell.getStringCellValue())) {
+                    if(modelName.equals("inchargerId")){
+                        if(!org.springframework.util.StringUtils.isEmpty(cell.getStringCellValue())){
                             String userName = cell.getStringCellValue();
                             Optional<User> first;
-                            if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1) {
+                            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
                                 Optional<User> optional = targetUserList.stream().filter(tl -> tl.getName().equals(userName)).findFirst();
-                                first = userList.stream().filter(u -> (u.getJobNumber() != null && u.getJobNumber().equals(userName)) || (optional.isPresent() && u.getCorpwxUserid() != null && u.getCorpwxUserid().equals(optional.get().getCorpwxUserid()))).findFirst();
-                            } else {
-                                first = userList.stream().filter(u -> u.getName().equals(userName) || (u.getJobNumber() != null && u.getJobNumber().equals(userName))).findFirst();
+                                first= userList.stream().filter(u ->(u.getJobNumber()!=null&&u.getJobNumber().equals(userName))||(optional.isPresent()&&u.getCorpwxUserid()!=null&&u.getCorpwxUserid().equals(optional.get().getCorpwxUserid()))).findFirst();
+                            }else {
+                                first= userList.stream().filter(u -> u.getName().equals(userName)||(u.getJobNumber()!=null&&u.getJobNumber().equals(userName))).findFirst();
                             }
                             if (first.isPresent()) {
-                                bo.setInchargerId(first.get().getId());
+                                product.setInchargerId(first.get().getId());
                             } else {
-                                msg.setError("负责人[" + userName + "]在系统中不存在");
+                                msg.setError("负责人["+userName+"]在系统中不存在");
                                 return msg;
                             }
                         }
-                    } else if (modelName.equals("contactsId")) {
-                        if (!StringUtils.isEmpty(cell.getStringCellValue())) {
-                            String userName = cell.getStringCellValue();
-                            Optional<User> first;
-                            if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1) {
-                                Optional<User> optional = targetUserList.stream().filter(tl -> tl.getName().equals(userName)).findFirst();
-                                first = userList.stream().filter(u -> (u.getJobNumber() != null && u.getJobNumber().equals(userName)) || (optional.isPresent() && u.getCorpwxUserid() != null && u.getCorpwxUserid().equals(optional.get().getCorpwxUserid()))).findFirst();
-                            } else {
-                                first = userList.stream().filter(u -> u.getName().equals(userName) || (u.getJobNumber() != null && u.getJobNumber().equals(userName))).findFirst();
-                            }
-                            if (first.isPresent()) {
-                                bo.setContactsId(Integer.parseInt(first.get().getId()));
-                            } else {
-                                msg.setError("负责人[" + userName + "]在系统中不存在");
+                    }else if(modelName.equals("stageId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Optional<Stage> first = stage.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
+                            if(first.isPresent()){
+                                product.setStageId(first.get().getId());
+                            }else {
+                                msg.setError("阶段["+cell.getStringCellValue()+"]不存在,请在阶段设置中增加");
                                 return msg;
                             }
                         }
-                    } else {
-                        if (!StringUtils.isEmpty(cell.getStringCellValue())) {
-                            Class<Clue> clueClass = Clue.class;
-                            Method method = clueClass.getMethod(setter, String.class);
-                            method.invoke(bo, cell.getStringCellValue());
+                    }else if(modelName.equals("contactsId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Optional<Contacts> first = contacts.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
+                            product.setContactsId(first.get().getId());
+                        }
+                    }else if(modelName.equals("customerId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Optional<Custom> first = customs.stream().filter(s -> s.getCustomName().equals(cell.getStringCellValue())).findFirst();
+                            product.setCustomerId(first.get().getId());
+                        }
+                    }else if(modelName.equals("expectedTransactionDate")){
+                        if(cell != null && cell.getCellTypeEnum() != CellType.BLANK){
+                            if(!org.apache.commons.lang3.StringUtils.isEmpty(cell.getStringCellValue())){
+                                try {
+                                    // 假设 cell 是一个代表 Excel 单元格的对象
+                                    String dateString = cell.getStringCellValue();
+
+                                    // 定义日期格式
+                                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
+
+                                    // 解析字符串为 Date 类型
+                                    Date parsedDate = dateFormat.parse(dateString);
+
+                                    // 设置到对象中
+                                    product.setExpectedTransactionDate(parsedDate);
+
+                                } catch (Exception e) {
+                                    System.out.println("日期时间格式不正确, 应该是yyyy/MM/dd");
+                                    msg.setError("日期时间格式不正确, 应该是yyyy/MM/dd");
+                                    return msg;
+                                }
+                            }
+                        }
+                    }else {
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Class<BusinessOpportunity> productClass = BusinessOpportunity.class;
+                            Method method = productClass.getMethod(setter,String.class);
+                            method.invoke(product,cell.getStringCellValue());
                         }
                     }
 
                 }
-                bOMapper.insert(bo);
+                importProductList.add(product);
+            }
+            if(importProductList.size()>0){
+                if(!saveOrUpdateBatch(importProductList)){
+                    msg.setError("验证失败,请检验数据格式是否正确");
+                    return msg;
+                }
+//                List<ActionLog> ads = new ArrayList<>();
+                for (BusinessOpportunity bo : importProductList) {
+                    ActionLog actionLog = new ActionLog();
+                    actionLog.setName("新增了商机");
+                    actionLog.setItemId(bo.getId());
+                    actionLog.setCode("business");
+                    actionLog.setUserId(user.getId());
+                    actionLogMapper.insert(actionLog);
+                }
             }
         } catch (IOException | NoSuchMethodException e) {
             e.printStackTrace();
+            msg.setError("验证失败,请检验数据格式是否正确");
         } catch (IllegalAccessException e) {
             e.printStackTrace();
         } catch (InvocationTargetException e) {
             e.printStackTrace();
         } catch (Exception e) {
             e.printStackTrace();
-            msg.setError("验证失败");
+            msg.setError("验证失败,请检验数据格式是否正确");
             return msg;
         }
         return msg;

+ 69 - 30
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ClueServiceImpl.java

@@ -46,6 +46,9 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -397,7 +400,7 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public HttpRespMsg importData(MultipartFile multipartFile) {
+    public HttpRespMsg importData(MultipartFile multipartFile,HttpServletRequest request) {
         HttpRespMsg msg=new HttpRespMsg();
         if(!multipartFile.getOriginalFilename().endsWith(".xlsx")){
             msg.setError("文件格式错误,请使用.xlsx格式的Excel文件进行导入");
@@ -409,8 +412,10 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
         Integer companyId = user.getCompanyId();
         WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, companyId));
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
-        List<SysDict> sysDictOfProductType = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "ClueSources"));
-        List<SysDict> sysDictOfProductUnit = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "ProductUnit"));
+        List<SysDict> sysSources = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "ClueSources"));
+        List<SysDict> sysIndutryId = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "CustomIndustry"));
+        List<SysDict> levels = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "CustomLevel"));
+
         InputStream inputStream = null;
         OutputStream outputStream = null;
         try {
@@ -456,7 +461,7 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
                     modelNameList.add(jsonObject.getString("model"));
                 }
             }
-            List<Clue>  importClueList =new ArrayList<>();
+            List<Clue> importProductList = new ArrayList<>();
             List<String> userNameList=new ArrayList<>();
             HttpRespMsg respMsg=new HttpRespMsg();
             for (int rowIndex = 1; rowIndex <= rowNum; rowIndex++) {
@@ -474,7 +479,7 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
                     String modelName = modelNameList.get(i);
                     XSSFCell cell = row.getCell(i);
                     if(modelName.equals("inchargerId")){
-                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                        if(!org.springframework.util.StringUtils.isEmpty(cell.getStringCellValue())){
                             userNameList.add(cell.getStringCellValue());
                         }
                     }
@@ -502,11 +507,25 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
                 }
                 //获取到当前行的列数据
                 int cellNum = row.getLastCellNum();
-                Clue clue =new Clue();
-                clue.setCompanyId(companyId);
-                clue.setCreateId(user.getId());
+                Clue product=new Clue();
+                product.setCompanyId(companyId);
+                product.setCreateId(user.getId());
+                product.setCreateTime(new Date());
+                JSONArray objects=new JSONArray();
+                for (int i = 0; i < configObJSONArray.size(); i++) {
+                    JSONObject jsonObject = configObJSONArray.getJSONObject(i);
+                    if(jsonObject.getString("type").equals("grid")){
+                        JSONArray columns = jsonObject.getJSONArray("columns");
+                        for (int i1 = 0; i1 < columns.size(); i1++) {
+                            JSONObject jsonObject1 = columns.getJSONObject(i1).getJSONArray("list").getJSONObject(0);
+                            objects.add(jsonObject1);
+                        }
+                    }else {
+                        objects.add(jsonObject);
+                    }
+                }
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
+                    JSONObject item = objects.getJSONObject(i);
                     String modelName = item.getString("model");
                     String className = modelName.substring(0, 1).toUpperCase() + modelName.substring(1);
                     String getter="get"+className;
@@ -520,18 +539,8 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
                             default:cell.setCellType(CellType.STRING);
                         }
                     }
-                    //校验当前列是否为必填
-                    JSONObject options = item.getJSONObject("options");
-                    JSONObject rules = options.getJSONObject("rules");
-                    Boolean required = rules.getBoolean("required");
-                    if(required){
-                        if(StringUtils.isEmpty(cell.getStringCellValue())){
-                            msg.setError(item.getString("label")+"值不能为空值");
-                            return msg;
-                        }
-                    }
-                  if(modelName.equals("inchargerId")){
-                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                    if(modelName.equals("inchargerId")){
+                        if(!org.springframework.util.StringUtils.isEmpty(cell.getStringCellValue())){
                             String userName = cell.getStringCellValue();
                             Optional<User> first;
                             if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
@@ -541,7 +550,7 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
                                 first= userList.stream().filter(u -> u.getName().equals(userName)||(u.getJobNumber()!=null&&u.getJobNumber().equals(userName))).findFirst();
                             }
                             if (first.isPresent()) {
-                                clue.setInchargerId(first.get().getId());
+                                product.setInchargerId(first.get().getId());
                             } else {
                                 msg.setError("负责人["+userName+"]在系统中不存在");
                                 return msg;
@@ -549,30 +558,60 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
                         }
                     }else if(modelName.equals("clueSourceId")){
                         if(!StringUtils.isEmpty(cell.getStringCellValue())){
-                            Optional<SysDict> first = sysDictOfProductType.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
+                            Optional<SysDict> first = sysSources.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
                             if(first.isPresent()){
-                                clue.setClueSourceId(first.get().getId());
+                                product.setClueSourceId(first.get().getId());
                             }else {
                                 msg.setError("线索来源["+cell.getStringCellValue()+"]不存在,请在系统字典中增加");
                                 return msg;
                             }
                         }
+                    }else if(modelName.equals("customerIndustryId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Optional<SysDict> first = sysIndutryId.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
+                            if(first.isPresent()){
+                                product.setCustomerIndustryId(first.get().getId());
+                            }else {
+                                msg.setError("客户行业["+cell.getStringCellValue()+"]不存在,请在系统字典中增加");
+                                return msg;
+                            }
+                        }
+                    }else if(modelName.equals("customerLevelId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Optional<SysDict> first = levels.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
+                            if(first.isPresent()){
+                                product.setCustomerLevelId(first.get().getId());
+                            }else {
+                                msg.setError("客户级别["+cell.getStringCellValue()+"]不存在,请在系统字典中增加");
+                                return msg;
+                            }
+                        }
                     }else {
+                        String stringCellValue = cell.getStringCellValue();
+                        System.out.println(stringCellValue+"=============");
                         if(!StringUtils.isEmpty(cell.getStringCellValue())){
-                            Class<Clue> ClueClass = Clue.class;
-                            Method method = ClueClass.getMethod(setter,String.class);
-                            method.invoke(cell,cell.getStringCellValue());
+                            Class<Clue> productClass = Clue.class;
+                            Method method = productClass.getMethod(setter,String.class);
+                            method.invoke(product,cell.getStringCellValue());
                         }
                     }
 
                 }
-                importClueList.add(clue);
+                importProductList.add(product);
             }
-            if(importClueList.size()>0){
-                if(!saveOrUpdateBatch(importClueList)){
+            if(importProductList.size()>0){
+                if(!saveOrUpdateBatch(importProductList)){
                     msg.setError("验证失败,请检验数据格式是否正确");
                     return msg;
                 }
+                for (Clue bo : importProductList) {
+                    ActionLog actionLog = new ActionLog();
+                    actionLog.setName("新增了商机");
+                    actionLog.setItemId(bo.getId());
+                    actionLog.setCode("clue");
+                    actionLog.setUserId(user.getId());
+                    actionLogMapper.insert(actionLog);
+                }
             }
         } catch (IOException | NoSuchMethodException e) {
             e.printStackTrace();

+ 140 - 65
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/CustomServiceImpl.java

@@ -117,6 +117,12 @@ public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom> impleme
             ) > 0) {
                 msg.setError("电话号码重复了");
                 return msg;
+            } if (customMapper.selectCount(new QueryWrapper<Custom>()
+                    .eq("company_phone", custom.getCompanyPhone())
+                    .ne("company_phone", custom1.getCompanyPhone())
+            ) > 0) {
+                msg.setError("电话号码重复了");
+                return msg;
             }
             ActionLog actionLog = new ActionLog();
             actionLog.setCode("custom");
@@ -341,7 +347,9 @@ public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom> impleme
         custom.setIsDelete(0);
         custom.setUserId(user.getId());
         custom.setEndTime(custom.getEndTime() + " 23:59:59");
-        custom.setPageIndex((custom.getPageIndex() - 1) * custom.getPageFrom());
+        if (custom.getPageIndex()!=null){
+            custom.setPageIndex((custom.getPageIndex() - 1) * custom.getPageFrom());
+        }
         boolean isAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部客户");
         boolean isNotAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看负责部门客户");
         List<Custom> list = new ArrayList<>();
@@ -616,14 +624,21 @@ public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom> impleme
 
     @Override
     public HttpRespMsg importData(MultipartFile multipartFile) {
-        HttpRespMsg msg = new HttpRespMsg();
+        HttpRespMsg msg=new HttpRespMsg();
+        if(!multipartFile.getOriginalFilename().endsWith(".xlsx")){
+            msg.setError("文件格式错误,请使用.xlsx格式的Excel文件进行导入");
+            return msg;
+        }
         String fileName = multipartFile.getOriginalFilename();
         File file = new File(fileName == null ? "file" : fileName);
         User user = userMapper.selectById(request.getHeader("token"));
         Integer companyId = user.getCompanyId();
         WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, companyId));
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
-        List<SysDict> sysDictOfClueSources = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "ClueSources"));
+        List<SysDict> sysSources = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "ClueSources"));
+        List<SysDict> sysIndutryId = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "CustomIndustry"));
+        List<SysDict> levels = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "CustomLevel"));
+
         InputStream inputStream = null;
         OutputStream outputStream = null;
         try {
@@ -644,16 +659,35 @@ public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom> impleme
             int rowNum = sheet.getLastRowNum();
             //获取当前表单模板 校验规则
             SysForm sysForm = sysFormMapper.selectOne(new LambdaQueryWrapper<SysForm>().eq(SysForm::getCode, "Customer").eq(SysForm::getCompanyId, companyId).eq(SysForm::getIsCurrent, 1));
-            if (sysForm == null) {
+            if(sysForm==null){
                 msg.setError("当前模块未配置自定义模板,需先完成配置");
                 return msg;
             }
             String config = sysForm.getConfig();
             JSONObject configOb = JSON.parseObject(config);
             JSONArray configObJSONArray = configOb.getJSONArray("list");
-            List<String> userNameList = new ArrayList<>();
-            HttpRespMsg respMsg = new HttpRespMsg();
-            for (int rowIndex = 0; rowIndex <= rowNum; rowIndex++) {
+            //可能存在栅格布局的情况需要特殊处理
+            List<String> modelNameList=new ArrayList<>();
+            for (int i = 0; i < configObJSONArray.size(); i++) {
+                JSONObject jsonObject = configObJSONArray.getJSONObject(i);
+                if(jsonObject.getString("type").equals("grid")){
+                    JSONArray columns = jsonObject.getJSONArray("columns");
+                    for (int i1 = 0; i1 < columns.size(); i1++) {
+                        JSONObject columnsJSONObject = columns.getJSONObject(i1);
+                        JSONArray list = columnsJSONObject.getJSONArray("list");
+                        for (int i2 = 0; i2 < list.size(); i2++) {
+                            JSONObject object = list.getJSONObject(i2);
+                            modelNameList.add(object.getString("model"));
+                        }
+                    }
+                }else {
+                    modelNameList.add(jsonObject.getString("model"));
+                }
+            }
+            List<Custom> importProductList = new ArrayList<>();
+            List<String> userNameList=new ArrayList<>();
+            HttpRespMsg respMsg=new HttpRespMsg();
+            for (int rowIndex = 1; rowIndex <= rowNum; rowIndex++) {
                 XSSFRow row = sheet.getRow(rowIndex);
                 if (row == null) {
                     continue;
@@ -665,37 +699,25 @@ public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom> impleme
                 //获取到当前行的列数据
                 int cellNum = row.getLastCellNum();
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
-                    String modelName = item.getString("model");
+                    String modelName = modelNameList.get(i);
                     XSSFCell cell = row.getCell(i);
-                    if (cell != null) {
-                        switch (item.getString("type")) {
-//                            case "time":cell.setCellType(CellType.NUMERIC);
-//                                break;
-                            default:
-                                cell.setCellType(CellType.STRING);
-                        }
-                    }
-                    if (modelName.equals("inchargerId")) {
-                        System.out.println("=====");
-                        System.out.println(modelName);
-                        System.out.println(cell.toString());
-                        if (!StringUtils.isEmpty(cell.getStringCellValue())) {
+                    if(modelName.equals("inchargerId")){
+                        if(!org.springframework.util.StringUtils.isEmpty(cell.getStringCellValue())){
                             userNameList.add(cell.getStringCellValue());
                         }
                     }
 
                 }
             }
-            System.out.println("参与搜索的人员列表" + userNameList + userNameList.size());
-            if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1 && userNameList.size() > 0) {
-                respMsg = wxCorpInfoService.getBatchSearchUserInfo(wxCorpInfo, userNameList, null);
-                if (respMsg.code.equals("0")) {
-                    msg.setError("姓名为[" + String.valueOf(respMsg.data) + "]的人员存在重复,请使用工号!");
+            System.out.println("参与搜素的人员列表"+userNameList + userNameList.size());
+            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1&&userNameList.size()>0){
+                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<User> targetUserList= (List<User>) respMsg.data;
             //直接忽略空行 从row1开始
             for (int rowIndex = 1; rowIndex <= rowNum; rowIndex++) {
                 XSSFRow row = sheet.getRow(rowIndex);
@@ -708,71 +730,124 @@ public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom> impleme
                 }
                 //获取到当前行的列数据
                 int cellNum = row.getLastCellNum();
-                Custom custom = new Custom();
-                custom.setCompanyId(companyId);
-                custom.setCreateTime(new Date());
-                custom.setCreatorId(user.getId());
+                Custom product=new Custom();
+                product.setCompanyId(companyId);
+                product.setCreatorId(user.getId());
+                product.setIsDelete(0);
+
+                product.setCreateTime(new Date());
+                JSONArray objects=new JSONArray();
+                for (int i = 0; i < configObJSONArray.size(); i++) {
+                    JSONObject jsonObject = configObJSONArray.getJSONObject(i);
+                    if(jsonObject.getString("type").equals("grid")){
+                        JSONArray columns = jsonObject.getJSONArray("columns");
+                        for (int i1 = 0; i1 < columns.size(); i1++) {
+                            JSONObject jsonObject1 = columns.getJSONObject(i1).getJSONArray("list").getJSONObject(0);
+                            objects.add(jsonObject1);
+                        }
+                    }else {
+                        objects.add(jsonObject);
+                    }
+                }
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
+                    JSONObject item = objects.getJSONObject(i);
                     String modelName = item.getString("model");
                     String className = modelName.substring(0, 1).toUpperCase() + modelName.substring(1);
-                    String getter = "get" + className;
-                    String setter = "set" + className;
+                    String getter="get"+className;
+                    String setter="set"+className;
                     XSSFCell cell = row.getCell(i);
-                    if (cell != null) {
-                        switch (item.getString("type")) {
-
-                            default:
-                                cell.setCellType(CellType.STRING);
-                        }
-                    }
-                    //校验当前列是否为必填
-                    JSONObject options = item.getJSONObject("options");
-                    JSONObject rules = options.getJSONObject("rules");
-                    Boolean required = rules.getBoolean("required");
-                    if (required) {
-                        if (StringUtils.isEmpty(cell.getStringCellValue())) {
-                            msg.setError(item.getString("label") + "值不能为空值");
-                            return msg;
+                    if(cell!=null){
+                        switch (item.getString("type")){
+//                            case "time":cell.setCellType(CellType.NUMERIC);
+//                                break;
+                            //默认读取所有数据都是文本格式
+                            default:cell.setCellType(CellType.STRING);
                         }
                     }
-                    if (modelName.equals("inchargerId")) {
-                        if (!StringUtils.isEmpty(cell.getStringCellValue())) {
+                    if(modelName.equals("inchargerId")){
+                        if(!org.springframework.util.StringUtils.isEmpty(cell.getStringCellValue())){
                             String userName = cell.getStringCellValue();
                             Optional<User> first;
-                            if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1) {
+                            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
                                 Optional<User> optional = targetUserList.stream().filter(tl -> tl.getName().equals(userName)).findFirst();
-                                first = userList.stream().filter(u -> (u.getJobNumber() != null && u.getJobNumber().equals(userName)) || (optional.isPresent() && u.getCorpwxUserid() != null && u.getCorpwxUserid().equals(optional.get().getCorpwxUserid()))).findFirst();
-                            } else {
-                                first = userList.stream().filter(u -> u.getName().equals(userName) || (u.getJobNumber() != null && u.getJobNumber().equals(userName))).findFirst();
+                                first= userList.stream().filter(u ->(u.getJobNumber()!=null&&u.getJobNumber().equals(userName))||(optional.isPresent()&&u.getCorpwxUserid()!=null&&u.getCorpwxUserid().equals(optional.get().getCorpwxUserid()))).findFirst();
+                            }else {
+                                first= userList.stream().filter(u -> u.getName().equals(userName)||(u.getJobNumber()!=null&&u.getJobNumber().equals(userName))).findFirst();
                             }
                             if (first.isPresent()) {
-                                custom.setInchargerId(first.get().getId());
+                                product.setInchargerId(first.get().getId());
                             } else {
-                                msg.setError("负责人[" + userName + "]在系统中不存在");
+                                msg.setError("负责人["+userName+"]在系统中不存在");
                                 return msg;
                             }
                         }
-                    } else {
-                        if (!StringUtils.isEmpty(cell.getStringCellValue())) {
-                            Class<Clue> clueClass = Clue.class;
-                            Method method = clueClass.getMethod(setter, String.class);
-                            method.invoke(custom, cell.getStringCellValue());
+                    }else if(modelName.equals("customSourceId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Optional<SysDict> first = sysSources.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
+                            if(first.isPresent()){
+                                product.setCustomSourceId(first.get().getId());
+                            }else {
+                                msg.setError("线索来源["+cell.getStringCellValue()+"]不存在,请在系统字典中增加");
+                                return msg;
+                            }
+                        }
+                    }else if(modelName.equals("customerIndustryId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Optional<SysDict> first = sysIndutryId.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
+                            if(first.isPresent()){
+                                product.setCustomerIndustryId(first.get().getId());
+                            }else {
+                                msg.setError("客户行业["+cell.getStringCellValue()+"]不存在,请在系统字典中增加");
+                                return msg;
+                            }
+                        }
+                    }else if(modelName.equals("customerLevelId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Optional<SysDict> first = levels.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
+                            if(first.isPresent()){
+                                product.setCustomerLevelId(first.get().getId());
+                            }else {
+                                msg.setError("客户级别["+cell.getStringCellValue()+"]不存在,请在系统字典中增加");
+                                return msg;
+                            }
+                        }
+                    }else {
+                        String stringCellValue = cell.getStringCellValue();
+                        System.out.println(stringCellValue+"=============");
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Class<Custom> productClass = Custom.class;
+                            Method method = productClass.getMethod(setter,String.class);
+                            method.invoke(product,cell.getStringCellValue());
                         }
                     }
 
                 }
-                customMapper.insert(custom);
+                importProductList.add(product);
+            }
+            if(importProductList.size()>0){
+                if(!saveOrUpdateBatch(importProductList)){
+                    msg.setError("验证失败,请检验数据格式是否正确");
+                    return msg;
+                }
+                for (Custom bo : importProductList) {
+                    ActionLog actionLog = new ActionLog();
+                    actionLog.setName("新增了商机");
+                    actionLog.setItemId(bo.getId());
+                    actionLog.setCode("custom");
+                    actionLog.setUserId(user.getId());
+                    actionLogMapper.insert(actionLog);
+                }
             }
         } catch (IOException | NoSuchMethodException e) {
             e.printStackTrace();
+            msg.setError("验证失败,请检验数据格式是否正确");
         } catch (IllegalAccessException e) {
             e.printStackTrace();
         } catch (InvocationTargetException e) {
             e.printStackTrace();
         } catch (Exception e) {
             e.printStackTrace();
-            msg.setError("验证失败");
+            msg.setError("验证失败,请检验数据格式是否正确");
             return msg;
         }
         return msg;

+ 14 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ProductServiceImpl.java

@@ -289,8 +289,21 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
                 Product product=new Product();
                 product.setCompanyId(companyId);
                 product.setCreatorId(user.getId());
+                JSONArray objects=new JSONArray();
+                for (int i = 0; i < configObJSONArray.size(); i++) {
+                    JSONObject jsonObject = configObJSONArray.getJSONObject(i);
+                    if(jsonObject.getString("type").equals("grid")){
+                        JSONArray columns = jsonObject.getJSONArray("columns");
+                        for (int i1 = 0; i1 < columns.size(); i1++) {
+                            JSONObject jsonObject1 = columns.getJSONObject(i1).getJSONArray("list").getJSONObject(0);
+                            objects.add(jsonObject1);
+                        }
+                    }else {
+                        objects.add(jsonObject);
+                    }
+                }
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
+                    JSONObject item = objects.getJSONObject(i);
                     String modelName = item.getString("model");
                     String className = modelName.substring(0, 1).toUpperCase() + modelName.substring(1);
                     String getter="get"+className;

+ 14 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SalesOrderServiceImpl.java

@@ -408,8 +408,21 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
                 SalesOrder order=new SalesOrder();
                 order.setCompanyId(companyId);
                 order.setCreatorId(user.getId());
+                JSONArray objects=new JSONArray();
+                for (int i = 0; i < configObJSONArray.size(); i++) {
+                    JSONObject jsonObject = configObJSONArray.getJSONObject(i);
+                    if(jsonObject.getString("type").equals("grid")){
+                        JSONArray columns = jsonObject.getJSONArray("columns");
+                        for (int i1 = 0; i1 < columns.size(); i1++) {
+                            JSONObject jsonObject1 = columns.getJSONObject(i1).getJSONArray("list").getJSONObject(0);
+                            objects.add(jsonObject1);
+                        }
+                    }else {
+                        objects.add(jsonObject);
+                    }
+                }
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
+                    JSONObject item = objects.getJSONObject(i);
                     String modelName = item.getString("model");
                     String className = modelName.substring(0, 1).toUpperCase() + modelName.substring(1);
                     String getter="get"+className;

+ 11 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/TaskServiceImpl.java

@@ -280,6 +280,15 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
         Task task = taskMapper.selectById(taskDto.getId());
         updateTaskRepeatConfigure(task);//将任务中之前的关于重复日期相关的置空
         taskMapper.updateRepeatConfig(task);
+        //根据任务的开始时间与当下时间判断任务的状态
+        if (taskDto.getStartDate()!=null&&taskDto.getStartDate().isAfter(LocalDateTime.now())){
+            task.setStatus(0);
+        }else if (taskDto.getEndDate()!=null&&taskDto.getEndDate().isBefore(LocalDateTime.now())){
+            task.setStatus(3);
+        } else if (taskDto.getStartDate()!=null&&taskDto.getStartDate().isBefore(LocalDateTime.now())&&taskDto.getEndDate()!=null&&taskDto.getEndDate().isAfter(LocalDateTime.now()))
+        {
+            task.setStatus(1);
+        }
         BeanUtils.copyProperties(taskDto,task);
         taskMapper.updateById(task);
 
@@ -1187,7 +1196,8 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
 
     public void updateTaskRepeatConfigure(Task task){
         task.setRepeatType(null).setRepeatEndNever(null).setRepeatEndCount(null)
-                .setRepeatEndDate(null).setRepeatDesignDay(null).setRepeatDesignSameday(null);
+                .setRepeatEndDate(null).setRepeatDesignDay(null).setRepeatDesignSameday(null)
+                .setCustomId(null).setBusinessOpportunityId(null).setOrderId(null).setClueId(null).setContactsId(null);
     }
 
 

+ 3 - 3
fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/BusinessOpportunityMapper.xml

@@ -45,7 +45,7 @@
         <if test="name != null and name != ''">
             and `name` LIKE CONCAT('%', #{name}, '%')
         </if>
-        <if test="inchargerId != null and inchargerId == '' ">
+        <if test="inchargerId != null and inchargerId != '' ">
             and incharger_id = #{inchargerId}
         </if>
         <if test="startTime != null and endTime != null ">
@@ -55,7 +55,7 @@
             and contacts_id in (select id from contacts where `name`LIKE CONCAT('%', #{contactsName}, '%'))
         </if>
         <if test="customerName != null and customerName != ''">
-            and customer_id in (select id from custom where `name`LIKE CONCAT('%', #{customerName}, '%'))
+            and customer_id in (select id from custom where `custom_name`LIKE CONCAT('%', #{customerName}, '%'))
         </if>
         <if test="stageId != null ">
             and stage_id = #{stageId}
@@ -75,7 +75,7 @@
         <if test="name != null and name != ''">
             and `name` LIKE CONCAT('%', #{name}, '%')
         </if>
-        <if test="inchargerId != null ">
+        <if test="inchargerId != null and inchargerId != ''">
             and incharger_id = #{inchargerId}
         </if>
         <if test="startTime != null and endTime != null ">

+ 6 - 6
fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/CustomMapper.xml

@@ -82,7 +82,7 @@
             and c.email LIKE CONCAT('%', #{email}, '%')
         </if>
         <if test="companyPhone != null and companyPhone != '' ">
-            and c.company_phone = #{companyPhone}
+            and c.company_phone LIKE CONCAT('%', #{companyPhone}, '%')
         </if>
         <if test="customerLevelId != null ">
             and c.customer_level_id = #{customerLevelId}
@@ -130,7 +130,7 @@
             and email = #{email}
         </if>
         <if test="companyPhone != null ">
-            and company_phone = #{companyPhone}
+            and company_phone LIKE CONCAT('%', #{companyPhone}, '%')
         </if>
         <if test="customerLevelId != null ">
             and customer_level_id = #{customerLevelId}
@@ -184,7 +184,7 @@
             and c.email LIKE CONCAT('%', #{email}, '%')
         </if>
         <if test="companyPhone != null ">
-            and c.company_phone = #{companyPhone}
+            and c.company_phone LIKE CONCAT('%', #{companyPhone}, '%')
         </if>
         <if test="customerLevelId != null ">
             and c.customer_level_id = #{customerLevelId}
@@ -235,7 +235,7 @@
             and email = #{email}
         </if>
         <if test="companyPhone != null ">
-            and company_phone = #{companyPhone}
+            and company_phone LIKE CONCAT('%', #{companyPhone}, '%')
         </if>
         <if test="customerLevelId != null ">
             and customer_level_id = #{customerLevelId}
@@ -287,7 +287,7 @@
             and email LIKE CONCAT('%', #{email}, '%')
         </if>
         <if test="companyPhone != null ">
-            and company_phone = #{companyPhone}
+            and company_phone LIKE CONCAT('%', #{companyPhone}, '%')
         </if>
         <if test="customerLevelId != null ">
             and customer_level_id = #{customerLevelId}
@@ -323,7 +323,7 @@
             and email = #{email}
         </if>
         <if test="companyPhone != null ">
-            and company_phone = #{companyPhone}
+            and company_phone LIKE CONCAT('%', #{companyPhone}, '%')
         </if>
         <if test="customerLevelId != null ">
             and customer_level_id = #{customerLevelId}

+ 2 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/TaskMapper.xml

@@ -271,7 +271,8 @@
         update task
         <set>
             repeat_type=#{repeatType},repeat_end_never=#{repeatEndNever},repeat_end_count=#{repeatEndCount},
-            repeat_end_date=#{repeatEndDate},repeat_design_day=#{repeatDesignDay},repeat_design_sameday=#{repeatDesignSameday}
+            repeat_end_date=#{repeatEndDate},repeat_design_day=#{repeatDesignDay},repeat_design_sameday=#{repeatDesignSameday},
+            custom_id=#{customId},business_opportunity_id=#{businessOpportunityId},order_id=#{orderId},clue_id=#{clueId},contacts_id=#{contactsId}
         </set>
         where id=#{id}
     </update>

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform-import/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -3987,7 +3987,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     }
                     Optional<SubProject> subProject = allSubProjectList.stream().filter(al -> al.getName().equals(row.getCell(4).getStringCellValue())&&al.getProjectId().equals(project.get().getId())).findFirst();
                     if(!subProject.isPresent()){
-                        msg.setError("子项目["+subProject.get().getName()+"]不属于项目["+project.get().getProjectName()+"]");
+                        msg.setError("子项目["+row.getCell(4).getStringCellValue()+"]不属于项目["+project.get().getProjectName()+"]");
                         return msg;
                     }
                     subP=subProject.get();

+ 2 - 2
fhKeeper/formulahousekeeper/management-platform-import/src/main/resources/application.yml

@@ -15,9 +15,9 @@ spring:
       location: C:/upload/
   datasource:
     driver-class-name: com.mysql.cj.jdbc.Driver
-    url: jdbc:mysql://47.101.180.183:3306/man_import?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&useSSL=false
+    url: jdbc:mysql://47.101.180.183:17089/man_import?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&useSSL=false
     username: root
-    password: HuoshiDB@2022
+    password: P011430@Huoshi*
     hikari:
       maximum-pool-size: 60
       minimum-idle: 10

+ 6 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java

@@ -1477,6 +1477,12 @@ public class ProjectController {
         return projectService.groupExpendProcessList(startDate,endDate,projectId,pageIndex,pageSize);
     }
 
+    //依斯倍定制 分组耗用进度表
+    @RequestMapping("/groupExpendProcessListForChart")
+    public HttpRespMsg groupExpendProcessListForChart(String startDate,String endDate,String projectIds,String groupNames){
+        return projectService.groupExpendProcessListForChart(startDate,endDate,projectIds,groupNames);
+    }
+
     //依斯倍定制 导出分组耗用进度表
     @RequestMapping("/exportGroupExpendProcessList")
     public HttpRespMsg exportGroupExpendProcessList(String startDate,String endDate,Integer projectId){

+ 33 - 236
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserWithBeisenController.java

@@ -148,223 +148,56 @@ public class UserWithBeisenController {
     @RequestMapping("/syncAttendanceFromBeisen")
     @Transactional(rollbackFor = Exception.class)
     public HttpRespMsg syncAttendanceFromBeisen(String startDate,String endDate){
+        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        return userWithBeisenService.syncAttendanceFromBeisen(startDate,endDate,companyId);
+    }
+
+
+    @RequestMapping("/getAttendanceStatisticWithUser")
+    public HttpRespMsg getAttendanceStatisticWithUser(String userId,String createDate){
         HttpRespMsg msg=new HttpRespMsg();
         DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
         DateTimeFormatter df1=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
         DateTimeFormatter df2=DateTimeFormatter.ofPattern("HH:mm");
         DateTimeFormatter df3=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
         DateTimeFormatter df4=DateTimeFormatter.ofPattern("HH:mm:ss");
-        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        if(StringUtils.isEmpty(userId)){
+            userId=request.getHeader("token");
+        }
+        User user = userMapper.selectById(userId);
+        Integer companyId = user.getCompanyId();
         TimeType timeType = timeTypeMapper.selectById(companyId);
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
         List<UserWithBeisen> userWithBeisenList = userWithBeisenService.list(new LambdaQueryWrapper<UserWithBeisen>().eq(UserWithBeisen::getCompanyId, companyId));
         BeisenConfig beisenConfig = beisenConfigMapper.selectById(companyId);
-        //获取特殊节假日设置
-        List<HolidaySetting> holidaySettings = holidaySettingService.list(new LambdaQueryWrapper<HolidaySetting>().eq(HolidaySetting::getCompanyId, companyId));
         if(beisenConfig==null){
             msg.setError("北森基础数据配置未完成,请联系服务商完成配置");
             return msg;
         }
+        Optional<UserWithBeisen> withBeisen = userWithBeisenList.stream().filter(u ->u.getJobNumber()!=null&& u.getJobNumber().equals(user.getJobNumber())).findFirst();
+        if(!withBeisen.isPresent()){
+            msg.setError("当前员工在北森系统中不存在,请完成录入员工信息");
+            return msg;
+        }
         //todo 获取到指定日期的考勤数据
-        JSONArray attendanceStatistics=new JSONArray();
+        JSONObject item = BeiSenUtils.getAttendanceStatisticWithUser(createDate,withBeisen.get().getUserId(), beisenConfig.getAppKey(), beisenConfig.getAppSecret());
         //todo 获取到指定日期的加班数据
-        List<LocalDate> workDaysListInRange = WorkDayCalculateUtils.getWorkDaysListInRange(startDate, endDate, 1);
-        JSONArray allOverTimeList=new JSONArray();
-        JSONArray allVacationList=new JSONArray();
-        List<LeaveSheet> leaveSheetList=new ArrayList<>();
-        List<UserFvTime> userFvTimeList=new ArrayList<>();
-        for (LocalDate localDate : workDaysListInRange) {
-            JSONArray statisticList = BeiSenUtils.getAttendanceStatistics(df.format(localDate), df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
-            JSONArray overTimeList = BeiSenUtils.getOverTimeList(df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
-            JSONArray vacationList = BeiSenUtils.getVacationList(df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(),1,100);
-            allOverTimeList.addAll(overTimeList);
-            attendanceStatistics.addAll(statisticList);
-            allVacationList.addAll(vacationList);
-        }
-        for (LocalDate localDate : workDaysListInRange) {
-            Stream<JSONObject> swipingCardsStream = attendanceStatistics.stream().map(item -> (JSONObject) item);
-            //todo: 获取当天的考勤数据
-            List<JSONObject> swipingCardDateList = swipingCardsStream.filter(i -> LocalDateTime.parse(i.getString("SwipingCardDate"),df1).toLocalDate().equals(localDate)).collect(Collectors.toList());
-            for (JSONObject item : swipingCardDateList) {
-                //获取当前数据下的人员工号对应到工时管家
-                String cardNumber = item.getString("CardNumber");
-                Optional<User> first = userList.stream().filter(f -> f.getJobNumber().equals(cardNumber)).findFirst();
-                //todo: 获取考勤打卡时间集合
-                JSONArray times = item.getJSONArray("Times");
-                Stream<JSONObject> timeStream = times.stream().map(time -> (JSONObject) time);
-                Stream<JSONObject> timeStream1 = times.stream().map(time -> (JSONObject) time);
-                //获取最早上班打卡时间
-                List<LocalTime> minLocalTimeList = timeStream.filter(t -> t.getIntValue("Type") == 1).map(i -> LocalDateTime.parse(i.getString("ActualTime"),df1).toLocalTime()).collect(Collectors.toList());
-                Optional<LocalTime> minOp = minLocalTimeList.stream().min(LocalTime::compareTo);
-                //获取最晚下班时间
-                List<LocalTime> maxLocalTimeList = timeStream1.filter(t -> t.getIntValue("Type") == 9).map(i -> LocalDateTime.parse(i.getString("ActualTime"),df1).toLocalTime()).collect(Collectors.toList());
-                Optional<LocalTime> maxOp = maxLocalTimeList.stream().max(LocalTime::compareTo);
-                if(first.isPresent()){
-                    boolean workDay = WorkDayCalculateUtils.isWorkDay(localDate);
-                    //todo:针对景昱 工作日默认以8小时工作制度加上加班时长 非工作日以加班时长为准
-                    Double workTime;
-                    LocalTime min = minOp.get();
-                    LocalTime max = maxOp.get();
-                    Duration between = Duration.between(min,max);
-                    if(between.toHours()<=0){
-                        continue;
-                    }else {
-                        if(workDay){
-                            //去掉休息时长
-                            workTime=8.0;
-                        }else {
-                            //去掉休息时长
-                            workTime=0.0;
-                        }
-                    }
-                    Stream<JSONObject> overTimeStream = allOverTimeList.stream().map(elment -> (JSONObject) elment);
-                    Stream<JSONObject> vacationStream = allVacationList.stream().map(elment -> (JSONObject) elment);
-                    Optional<UserWithBeisen> beisen = userWithBeisenList.stream().filter(u -> u.getJobNumber() != null && u.getJobNumber().equals(first.get().getJobNumber())).findFirst();
-                    if(beisen.isPresent()){
-                        //todo:之前的逻辑
-//                        List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
-//                                && (a.getIntValue("ApproveStatus") == 2||a.getIntValue("ApproveStatus") == 1)
-//                                &&LocalDateTime.parse(a.getString("StartDate"),df1).toLocalDate().isEqual(localDate)).collect(Collectors.toList());
-                        List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
-                                && (a.getIntValue("ApproveStatus") == 2||a.getIntValue("ApproveStatus") == 1)).collect(Collectors.toList());
-                        //加班数据可能存在结束日期是当前日期的情况的情况
-                        BigDecimal overTimeBigDecimal= new BigDecimal(0);
-                        //计算加班时长 工作日打卡超过19:00:00算加班那 非工作日全天算加班
-                        if(workDay){
-                            //工作日打卡超过19:00:00算加班那 非工作日全天算加班
-                            if(max.isAfter(LocalTime.parse("19:00:00", df4))){
-                                overTimeBigDecimal = new BigDecimal(Duration.between(LocalTime.parse("18:00:00", df4),max).toMinutes());
-                            }
-                        }else {
-                            //非工作日全天 去掉休息时长 都算加班
-                            overTimeBigDecimal=new BigDecimal(Duration.between(min, max).toMinutes()) ;
-                            long rest1 = DateTimeUtil.calculateOverlap(min, max, LocalTime.parse("12:00:00", df4), LocalTime.parse("13:00:00", df4));
-                            long rest2 = DateTimeUtil.calculateOverlap(min, max, LocalTime.parse("17:30:00", df4), LocalTime.parse("18:00:00", df4));
-                            overTimeBigDecimal=overTimeBigDecimal.subtract(new BigDecimal(rest1)).subtract(new BigDecimal(rest2));
-                        }
-                        for (JSONObject o : overTimeList) {
-                            //存在开始日期为当前日期的数据以及结束日期为当天日期的数据 分开计算
-                            if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(localDate)){
-                                //存在开始日期为当天的数据
-                                if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate())){
-                                    //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
-                                    //对比打卡体现的加班时长和加班单时长取小
-                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
-                                    if(divide.doubleValue()>o.getDouble("OverTimeDuration")){
-                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
-                                        workTime=workTime+o.getDouble("OverTimeDuration");
-                                    }else{
-                                        workTime=workTime+round(divide.doubleValue(),0.5);
-                                    }
-                                }else {
-                                    //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
-                                    LocalDateTime start = LocalDateTime.parse(o.getString("StartDate"), df1);
-                                    LocalDateTime stop = start.toLocalDate().atTime(LocalTime.MAX);
-                                    Duration duration = Duration.between(start, stop);
-                                    BigDecimal decimal = new BigDecimal(duration.toMinutes());
-                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
-                                    double l = decimal.doubleValue();
-                                    //对比打卡体现的加班时长和加班单时长取小
-                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
-                                    if(divide.doubleValue()>l){
-                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
-                                        workTime=workTime+l;
-                                    }else {
-                                        workTime=workTime+round(divide.doubleValue(),0.5);
-                                    }
-                                }
-                            }else if(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate().isEqual(localDate)){
-                                //存在结束日期为当天的数据
-                                if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate())){
-                                    //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
-                                    //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
-                                    if(divide.doubleValue()>o.getDouble("OverTimeDuration")){
-                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
-                                        workTime=workTime+o.getDouble("OverTimeDuration");
-                                    }else {
-                                        workTime=workTime+round(divide.doubleValue(),0.5);
-                                    }
-                                }else {
-                                    //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
-                                    LocalDateTime stop = LocalDateTime.parse(o.getString("StopDate"), df1);
-                                    LocalDateTime start = stop.toLocalDate().atTime(LocalTime.MIN);
-                                    Duration duration = Duration.between(start, stop);
-                                    BigDecimal decimal = new BigDecimal(duration.toMinutes());
-                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
-                                    double l = decimal.doubleValue();
-                                    //对比打卡体现的加班时长和加班单时长取小
-                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
-                                    if(divide.doubleValue()>l){
-                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
-                                        workTime=workTime+l;
-                                    }else {
-                                        workTime=workTime+round(divide.doubleValue(),0.5);
-                                    }
-                                }
-                            }
-                        }
-                        //处理修改
-                        List<JSONObject> vacationList = vacationStream.filter(a ->{
-                            LocalDate vacationStartDate = LocalDateTime.parse(a.getString("VacationStartDateTime"), df3).toLocalDate();
-                            LocalDate vacationStopDate = LocalDateTime.parse(a.getString("VacationStopDateTime"), df3).toLocalDate();
-                            boolean b=false;
-                            if((localDate.isAfter(vacationStartDate)||localDate.isEqual(vacationStartDate))
-                                    &&(localDate.isBefore(vacationStopDate)||localDate.isEqual(vacationStopDate))){
-                                b=true;
-                            }
-                            if(a.getString("StaffId").equals(beisen.get().getUserId())
-                                    && b
-                                    &&a.getString("DocumentType").equals("请假")
-                                    &&  (a.getString("ApproveStatus").equals("通过") || a.getString("ApproveStatus").equals("审批中"))){
-                                return true;
-                            }
-                            return false;
-                        }).collect(Collectors.toList());
-                        if(vacationList.size()>0){
-                            double vacationDuration = vacationList.stream().mapToDouble(i -> i.getDouble("VacationDuration")).sum();
-                            BigDecimal decimal = new BigDecimal(vacationDuration);
-                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
-//                            //可能存在休假多天 只减去一天
-                            if(decimal.doubleValue()>=8){
-                                workTime= workTime-8;
-                            }else {
-                                workTime= workTime-decimal.doubleValue();
-                            }
-                        }
-                    }
-                    UserFvTime userFvTime=new UserFvTime();
-                    userFvTime.setWorkDate(localDate);
-                    userFvTime.setStartTime(df2.format(min));
-                    userFvTime.setEndTime(df2.format(max));
-                    userFvTime.setUserId(first.get().getId());
-                    userFvTime.setCompanyId(companyId);
-                    userFvTime.setWorkHours(workTime.floatValue());
-                    UserFvTime one = userFvTimeService.getOne(new LambdaQueryWrapper<UserFvTime>().eq(UserFvTime::getCompanyId, companyId).eq(UserFvTime::getUserId, first.get().getId()).eq(UserFvTime::getWorkDate, localDate));
-                    if(one!=null){
-                        userFvTime.setId(one.getId());
-                    }
-                    userFvTimeList.add(userFvTime);
-                }
-            }
-        }
-        if(userFvTimeList.size()>0){
-            if(!userFvTimeService.saveOrUpdateBatch(userFvTimeList)){
-                msg.setError("同步验证失败");
-            }
-        }
+        JSONArray allOverTimeList = BeiSenUtils.getOverTimeList(createDate,beisenConfig.getAppKey(),beisenConfig.getAppSecret(),1,100);
+        //todo 获取到指定日期的休假数据
+        JSONArray vacationList = BeiSenUtils.getVacationList(createDate, beisenConfig.getAppKey(), beisenConfig.getAppSecret(),1,100);
         //同步休假数据到工时管家
-        for (int i = 0; i < allVacationList.size(); i++) {
-            JSONObject jsonObject = allVacationList.getJSONObject(i);
-            Optional<UserWithBeisen> beisen = userWithBeisenList.stream().filter(b -> b.getUserId().equals(jsonObject.getString("StaffId"))).findFirst();
-            if(beisen.isPresent()){
-                Optional<User> first = userList.stream().filter(u -> u.getJobNumber().equals(beisen.get().getJobNumber())).findFirst();
-                if(first.isPresent()){
+        List<LeaveSheet> leaveSheetList=new ArrayList<>();
+        for (int i = 0; i < vacationList.size(); i++) {
+            JSONObject jsonObject = vacationList.getJSONObject(i);
+            Optional<UserWithBeisen> beisen1 = userWithBeisenList.stream().filter(b -> b.getUserId().equals(jsonObject.getString("StaffId"))).findFirst();
+            if(beisen1.isPresent()){
+                Optional<User> first1 = userList.stream().filter(u -> u.getJobNumber().equals(beisen1.get().getJobNumber())).findFirst();
+                if(first1.isPresent()){
                     LeaveSheet leaveSheet=new LeaveSheet();
                     leaveSheet.setCompanyId(beisenConfig.getCompanyId());
                     leaveSheet.setStatus(0);
-                    leaveSheet.setOwnerId(first.get().getId());
-                    leaveSheet.setOwnerName(first.get().getName());
+                    leaveSheet.setOwnerId(first1.get().getId());
+                    leaveSheet.setOwnerName(first1.get().getName());
                     leaveSheet.setStartDate(LocalDateTime.parse(String.valueOf(jsonObject.get("VacationStartDateTime")),df3).toLocalDate());
                     leaveSheet.setEndDate(LocalDateTime.parse(String.valueOf(jsonObject.get("VacationStopDateTime")),df3).toLocalDate());
                     leaveSheet.setTimeType(1);
@@ -392,10 +225,10 @@ public class UserWithBeisenController {
                     }
                     leaveSheet.setLeaveType(leaveType);
                     leaveSheet.setRemark(jsonObject.getString("Reason"));
-                    leaveSheet.setStatus(jsonObject.getString("ApproveStatus").equals("通过")?0:jsonObject.getString("Reason").equals("审批中")?1:2);
+                    leaveSheet.setStatus(jsonObject.getString("ApproveStatus").equals("通过")?0:jsonObject.getString("ApproveStatus").equals("审批中")?1:2);
                     leaveSheet.setProcinstId(jsonObject.getString("VacationId"));
-                    LeaveSheet one = leaveSheetService.getOne(new LambdaQueryWrapper<LeaveSheet>().eq(LeaveSheet::getProcinstId,leaveSheet.getProcinstId()).eq(LeaveSheet::getOwnerId, first.get().getId()).eq(LeaveSheet::getStartDate, leaveSheet.getStartDate()).eq(LeaveSheet::getEndDate, leaveSheet.getEndDate()));
-                    if(one==null){
+                    LeaveSheet one1 = leaveSheetService.getOne(new LambdaQueryWrapper<LeaveSheet>().eq(LeaveSheet::getOwnerId, first1.get().getId()).eq(LeaveSheet::getStartDate, leaveSheet.getStartDate()).eq(LeaveSheet::getProcinstId,leaveSheet.getProcinstId()).eq(LeaveSheet::getEndDate, leaveSheet.getEndDate()));
+                    if(one1==null){
                         leaveSheetList.add(leaveSheet);
                     }
                 }
@@ -404,42 +237,6 @@ public class UserWithBeisenController {
         if(leaveSheetList.size()>0){
             leaveSheetService.saveOrUpdateBatch(leaveSheetList);
         }
-        return msg;
-    }
-
-
-    @RequestMapping("/getAttendanceStatisticWithUser")
-    public HttpRespMsg getAttendanceStatisticWithUser(String userId,String createDate){
-        HttpRespMsg msg=new HttpRespMsg();
-        DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
-        DateTimeFormatter df1=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-        DateTimeFormatter df2=DateTimeFormatter.ofPattern("HH:mm");
-        DateTimeFormatter df3=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
-        DateTimeFormatter df4=DateTimeFormatter.ofPattern("HH:mm:ss");
-        if(StringUtils.isEmpty(userId)){
-            userId=request.getHeader("token");
-        }
-        User user = userMapper.selectById(userId);
-        Integer companyId = user.getCompanyId();
-        TimeType timeType = timeTypeMapper.selectById(companyId);
-        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
-        List<UserWithBeisen> userWithBeisenList = userWithBeisenService.list(new LambdaQueryWrapper<UserWithBeisen>().eq(UserWithBeisen::getCompanyId, companyId));
-        BeisenConfig beisenConfig = beisenConfigMapper.selectById(companyId);
-        if(beisenConfig==null){
-            msg.setError("北森基础数据配置未完成,请联系服务商完成配置");
-            return msg;
-        }
-        Optional<UserWithBeisen> withBeisen = userWithBeisenList.stream().filter(u ->u.getJobNumber()!=null&& u.getJobNumber().equals(user.getJobNumber())).findFirst();
-        if(!withBeisen.isPresent()){
-            msg.setError("当前员工在北森系统中不存在,请完成录入员工信息");
-            return msg;
-        }
-        //todo 获取到指定日期的考勤数据
-        JSONObject item = BeiSenUtils.getAttendanceStatisticWithUser(createDate,withBeisen.get().getUserId(), beisenConfig.getAppKey(), beisenConfig.getAppSecret());
-        //todo 获取到指定日期的加班数据
-        JSONArray allOverTimeList = BeiSenUtils.getOverTimeList(createDate,beisenConfig.getAppKey(),beisenConfig.getAppSecret(),1,100);
-        //todo 获取到指定日期的休假数据
-        JSONArray vacationList = BeiSenUtils.getVacationList(createDate, beisenConfig.getAppKey(), beisenConfig.getAppSecret(),1,100);
         //获取当前数据下的人员工号对应到工时管家
         Optional<User> first = userList.stream().filter(f -> f.getJobNumber().equals(withBeisen.get().getJobNumber())).findFirst();
         System.out.println("考勤数据:"+item.toString());

+ 2 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java

@@ -184,4 +184,6 @@ public interface ProjectMapper extends BaseMapper<Project> {
     Long userTaskProcessListCount(Integer deptId, String userId, Integer projectId, Integer companyId, @Param("list") List<Integer> deptIds,String startDate,String endDate,@Param("listSecond") List<Integer> regularDeptIds);
     @Update("update project set reviwer_id=null where id=#{id}")
     void removeReviwer(Integer id);
+
+    List<Map<String, Object>> groupExpendProcessListForChart(String userId, Integer companyId, String startDate, String endDate,@Param("list") List<Integer> deptIds,@Param("listSecond") List<Integer> regularDeptIds,@Param("listThird") List<Integer> projectIdList,@Param("listFour") List<String> groupNameList);
 }

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

@@ -298,4 +298,6 @@ public interface ProjectService extends IService<Project> {
     HttpRespMsg batchChangeStage(String projectIdArray, Integer stageId, String stageName, HttpServletRequest request);
 
     HttpRespMsg batchSetProjectTaskExecutor(String projectIds, String userIds);
+
+    HttpRespMsg groupExpendProcessListForChart(String startDate, String endDate, String projectIds, String groupNames);
 }

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

@@ -2,6 +2,7 @@ package com.management.platform.service;
 
 import com.management.platform.entity.UserWithBeisen;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.management.platform.util.HttpRespMsg;
 
 /**
  * <p>
@@ -13,4 +14,5 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface UserWithBeisenService extends IService<UserWithBeisen> {
 
+    HttpRespMsg syncAttendanceFromBeisen(String startDate, String endDate,Integer companyId);
 }

+ 61 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java

@@ -14345,4 +14345,65 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         }
         return msg;
     }
+
+    @Override
+    public HttpRespMsg groupExpendProcessListForChart(String startDate, String endDate, String projectIds, String groupNames) {
+        HttpRespMsg msg=new HttpRespMsg();
+        User user = userMapper.selectById(request.getHeader("token"));
+        NumberFormat percentFormat = NumberFormat.getPercentInstance();
+        percentFormat.setMaximumFractionDigits(2);
+        Integer companyId = user.getCompanyId();
+        List<String> groupNameList=new ArrayList<>();
+        List<Integer> projectIdList=new ArrayList<>();
+        if(!StringUtils.isEmpty(groupNames)){
+            groupNameList = Arrays.asList(groupNames.split(","));
+        }
+        if(!StringUtils.isEmpty(projectIds)){
+            projectIdList=Arrays.asList(projectIds.split(",")).stream().map(i->Integer.valueOf(i)).collect(Collectors.toList());
+        }
+        boolean viewAll = sysFunctionService.hasPriviledge(user.getRoleId(), "全部分组耗用进度表");
+        boolean incharger = sysFunctionService.hasPriviledge(user.getRoleId(), "负责部门分组耗用进度表");
+        List<Department> allDeptList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, companyId));
+        List<Map<String,Object>> resultList;
+        //是否具有查看全部数据的权限
+        //针对依斯呗 指定部门
+        List<Integer> regularDeptIds=new ArrayList<>();
+        if(user.getCompanyId()==3092){
+            List<String> nameString=new ArrayList<>();
+            nameString.add("4");
+            nameString.add("46");
+            nameString.add("45");
+            List<Department> departmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, user.getCompanyId()).in(Department::getDepartmentName, nameString));
+            List<Integer> theCollect = departmentList.stream().map(dm -> dm.getDepartmentId()).distinct().collect(Collectors.toList());
+            theCollect.add(-1);
+            for (Integer integer : theCollect) {
+                List<Integer> branchDepartment = getBranchDepartment(integer, allDeptList);
+                regularDeptIds.addAll(branchDepartment);
+            }
+        }
+        if(!viewAll){
+            if(!incharger){
+                //只能查看本人的数据
+                resultList=projectMapper.groupExpendProcessListForChart(user.getId(),companyId,startDate,endDate,null,null,projectIdList,groupNameList);
+            }else {
+                List<Department> departmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().select(Department::getDepartmentId).eq(Department::getManagerId, user.getId()));
+                List<DepartmentOtherManager> departmentOtherManagerList = departmentOtherManagerMapper.selectList(new QueryWrapper<DepartmentOtherManager>().eq("other_manager_id", user.getId()));
+                List<Integer> deptIds=new ArrayList<>();
+                List<Integer> theCollect = departmentList.stream().map(dm -> dm.getDepartmentId()).distinct().collect(Collectors.toList());
+                theCollect.add(-1);
+                List<Integer> otherCollect = departmentOtherManagerList.stream().map(dom -> dom.getDepartmentId()).distinct().collect(Collectors.toList());
+                otherCollect.add(-1);
+                theCollect.addAll(otherCollect);
+                for (Integer integer : theCollect) {
+                    List<Integer> branchDepartment = getBranchDepartment(integer, allDeptList);
+                    deptIds.addAll(branchDepartment);
+                }
+                resultList=projectMapper.groupExpendProcessListForChart(null,companyId,startDate,endDate,deptIds,regularDeptIds,projectIdList,groupNameList);
+            }
+        }else {
+            resultList=projectMapper.groupExpendProcessListForChart(null,companyId,startDate,endDate,null,regularDeptIds,projectIdList,groupNameList);
+        }
+        msg.setData(resultList);
+        return msg;
+    }
 }

+ 314 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserWithBeisenServiceImpl.java

@@ -1,11 +1,38 @@
 package com.management.platform.service.impl;
 
-import com.management.platform.entity.UserWithBeisen;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.management.platform.entity.*;
+import com.management.platform.mapper.BeisenConfigMapper;
+import com.management.platform.mapper.TimeTypeMapper;
+import com.management.platform.mapper.UserMapper;
 import com.management.platform.mapper.UserWithBeisenMapper;
+import com.management.platform.service.HolidaySettingService;
+import com.management.platform.service.LeaveSheetService;
+import com.management.platform.service.UserFvTimeService;
 import com.management.platform.service.UserWithBeisenService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.management.platform.util.BeiSenUtils;
+import com.management.platform.util.DateTimeUtil;
+import com.management.platform.util.HttpRespMsg;
+import com.management.platform.util.WorkDayCalculateUtils;
 import org.springframework.stereotype.Service;
 
+import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
 /**
  * <p>
  *  服务实现类
@@ -17,4 +44,290 @@ import org.springframework.stereotype.Service;
 @Service
 public class UserWithBeisenServiceImpl extends ServiceImpl<UserWithBeisenMapper, UserWithBeisen> implements UserWithBeisenService {
 
+    private UserFvTimeService userFvTimeService;
+    private UserMapper userMapper;
+    private TimeTypeMapper timeTypeMapper;
+    private HttpServletRequest request;
+    private UserWithBeisenService userWithBeisenService;
+    private BeisenConfigMapper beisenConfigMapper;
+    private HolidaySettingService holidaySettingService;
+    private LeaveSheetService leaveSheetService;
+
+    @Override
+    public HttpRespMsg syncAttendanceFromBeisen(String startDate, String endDate,Integer companyId) {
+        HttpRespMsg msg=new HttpRespMsg();
+        DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        DateTimeFormatter df1=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        DateTimeFormatter df2=DateTimeFormatter.ofPattern("HH:mm");
+        DateTimeFormatter df3=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
+        DateTimeFormatter df4=DateTimeFormatter.ofPattern("HH:mm:ss");
+        TimeType timeType = timeTypeMapper.selectById(companyId);
+        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
+        List<UserWithBeisen> userWithBeisenList = userWithBeisenService.list(new LambdaQueryWrapper<UserWithBeisen>().eq(UserWithBeisen::getCompanyId, companyId));
+        BeisenConfig beisenConfig = beisenConfigMapper.selectById(companyId);
+        //获取特殊节假日设置
+        List<HolidaySetting> holidaySettings = holidaySettingService.list(new LambdaQueryWrapper<HolidaySetting>().eq(HolidaySetting::getCompanyId, companyId));
+        if(beisenConfig==null){
+            msg.setError("北森基础数据配置未完成,请联系服务商完成配置");
+            return msg;
+        }
+        //todo 获取到指定日期的考勤数据
+        JSONArray attendanceStatistics=new JSONArray();
+        //todo 获取到指定日期的加班数据
+        List<LocalDate> workDaysListInRange = WorkDayCalculateUtils.getWorkDaysListInRange(startDate, endDate, 1);
+        JSONArray allOverTimeList=new JSONArray();
+        JSONArray allVacationList=new JSONArray();
+        List<LeaveSheet> leaveSheetList=new ArrayList<>();
+        //同步休假数据到工时管家
+        for (int i = 0; i < allVacationList.size(); i++) {
+            JSONObject jsonObject = allVacationList.getJSONObject(i);
+            Optional<UserWithBeisen> beisen = userWithBeisenList.stream().filter(b -> b.getUserId().equals(jsonObject.getString("StaffId"))).findFirst();
+            if(beisen.isPresent()){
+                Optional<User> first = userList.stream().filter(u -> u.getJobNumber().equals(beisen.get().getJobNumber())).findFirst();
+                if(first.isPresent()){
+                    LeaveSheet leaveSheet=new LeaveSheet();
+                    leaveSheet.setCompanyId(beisenConfig.getCompanyId());
+                    leaveSheet.setStatus(0);
+                    leaveSheet.setOwnerId(first.get().getId());
+                    leaveSheet.setOwnerName(first.get().getName());
+                    leaveSheet.setStartDate(LocalDateTime.parse(String.valueOf(jsonObject.get("VacationStartDateTime")),df3).toLocalDate());
+                    leaveSheet.setEndDate(LocalDateTime.parse(String.valueOf(jsonObject.get("VacationStopDateTime")),df3).toLocalDate());
+                    leaveSheet.setTimeType(1);
+                    leaveSheet.setTimeDays(jsonObject.getFloatValue("DayValueOfDuration"));
+                    leaveSheet.setTimeHours(jsonObject.getFloatValue("VacationDuration")/60);
+                    Integer leaveType;
+                    switch (jsonObject.getString("VacationType")){
+                        case "事假":leaveType=0;
+                            break;
+                        case "病假":leaveType=1;
+                            break;
+                        case "年假":leaveType=2;
+                            break;
+                        case "产假":leaveType=3;
+                            break;
+                        case "婚假":leaveType=4;
+                            break;
+                        case "丧假":leaveType=5;
+                            break;
+                        case "调休":leaveType=6;
+                            break;
+                        case "陪产假":leaveType=7;
+                            break;
+                        default:leaveType=8;
+                    }
+                    leaveSheet.setLeaveType(leaveType);
+                    leaveSheet.setRemark(jsonObject.getString("Reason"));
+                    leaveSheet.setStatus(jsonObject.getString("ApproveStatus").equals("通过")?0:jsonObject.getString("ApproveStatus").equals("审批中")?1:2);
+                    leaveSheet.setProcinstId(jsonObject.getString("VacationId"));
+                    LeaveSheet one = leaveSheetService.getOne(new LambdaQueryWrapper<LeaveSheet>().eq(LeaveSheet::getProcinstId,leaveSheet.getProcinstId()).eq(LeaveSheet::getOwnerId, first.get().getId()).eq(LeaveSheet::getStartDate, leaveSheet.getStartDate()).eq(LeaveSheet::getEndDate, leaveSheet.getEndDate()));
+                    if(one==null){
+                        leaveSheetList.add(leaveSheet);
+                    }
+                }
+            }
+        }
+        if(leaveSheetList.size()>0){
+            leaveSheetService.saveOrUpdateBatch(leaveSheetList);
+        }
+        List<UserFvTime> userFvTimeList=new ArrayList<>();
+        for (LocalDate localDate : workDaysListInRange) {
+            JSONArray statisticList = BeiSenUtils.getAttendanceStatistics(df.format(localDate), df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
+            JSONArray overTimeList = BeiSenUtils.getOverTimeList(df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
+            JSONArray vacationList = BeiSenUtils.getVacationList(df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(),1,100);
+            allOverTimeList.addAll(overTimeList);
+            attendanceStatistics.addAll(statisticList);
+            allVacationList.addAll(vacationList);
+        }
+        for (LocalDate localDate : workDaysListInRange) {
+            Stream<JSONObject> swipingCardsStream = attendanceStatistics.stream().map(item -> (JSONObject) item);
+            //todo: 获取当天的考勤数据
+            List<JSONObject> swipingCardDateList = swipingCardsStream.filter(i -> LocalDateTime.parse(i.getString("SwipingCardDate"),df1).toLocalDate().equals(localDate)).collect(Collectors.toList());
+            for (JSONObject item : swipingCardDateList) {
+                //获取当前数据下的人员工号对应到工时管家
+                String cardNumber = item.getString("CardNumber");
+                Optional<User> first = userList.stream().filter(f -> f.getJobNumber().equals(cardNumber)).findFirst();
+                //todo: 获取考勤打卡时间集合
+                JSONArray times = item.getJSONArray("Times");
+                Stream<JSONObject> timeStream = times.stream().map(time -> (JSONObject) time);
+                Stream<JSONObject> timeStream1 = times.stream().map(time -> (JSONObject) time);
+                //获取最早上班打卡时间
+                List<LocalTime> minLocalTimeList = timeStream.filter(t -> t.getIntValue("Type") == 1).map(i -> LocalDateTime.parse(i.getString("ActualTime"),df1).toLocalTime()).collect(Collectors.toList());
+                Optional<LocalTime> minOp = minLocalTimeList.stream().min(LocalTime::compareTo);
+                //获取最晚下班时间
+                List<LocalTime> maxLocalTimeList = timeStream1.filter(t -> t.getIntValue("Type") == 9).map(i -> LocalDateTime.parse(i.getString("ActualTime"),df1).toLocalTime()).collect(Collectors.toList());
+                Optional<LocalTime> maxOp = maxLocalTimeList.stream().max(LocalTime::compareTo);
+                if(first.isPresent()){
+                    boolean workDay = WorkDayCalculateUtils.isWorkDay(localDate);
+                    //todo:针对景昱 工作日默认以8小时工作制度加上加班时长 非工作日以加班时长为准
+                    Double workTime;
+                    LocalTime min = minOp.get();
+                    LocalTime max = maxOp.get();
+                    Duration between = Duration.between(min,max);
+                    if(between.toHours()<=0){
+                        continue;
+                    }else {
+                        if(workDay){
+                            //去掉休息时长
+                            workTime=8.0;
+                        }else {
+                            //去掉休息时长
+                            workTime=0.0;
+                        }
+                    }
+                    Stream<JSONObject> overTimeStream = allOverTimeList.stream().map(elment -> (JSONObject) elment);
+                    Stream<JSONObject> vacationStream = allVacationList.stream().map(elment -> (JSONObject) elment);
+                    Optional<UserWithBeisen> beisen = userWithBeisenList.stream().filter(u -> u.getJobNumber() != null && u.getJobNumber().equals(first.get().getJobNumber())).findFirst();
+                    if(beisen.isPresent()){
+                        //todo:之前的逻辑
+//                        List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
+//                                && (a.getIntValue("ApproveStatus") == 2||a.getIntValue("ApproveStatus") == 1)
+//                                &&LocalDateTime.parse(a.getString("StartDate"),df1).toLocalDate().isEqual(localDate)).collect(Collectors.toList());
+                        List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
+                                && (a.getIntValue("ApproveStatus") == 2||a.getIntValue("ApproveStatus") == 1)).collect(Collectors.toList());
+                        //加班数据可能存在结束日期是当前日期的情况的情况
+                        BigDecimal overTimeBigDecimal= new BigDecimal(0);
+                        //计算加班时长 工作日打卡超过19:00:00算加班那 非工作日全天算加班
+                        if(workDay){
+                            //工作日打卡超过19:00:00算加班那 非工作日全天算加班
+                            if(max.isAfter(LocalTime.parse("19:00:00", df4))){
+                                overTimeBigDecimal = new BigDecimal(Duration.between(LocalTime.parse("18:00:00", df4),max).toMinutes());
+                            }
+                        }else {
+                            //非工作日全天 去掉休息时长 都算加班
+                            overTimeBigDecimal=new BigDecimal(Duration.between(min, max).toMinutes()) ;
+                            long rest1 = DateTimeUtil.calculateOverlap(min, max, LocalTime.parse("12:00:00", df4), LocalTime.parse("13:00:00", df4));
+                            long rest2 = DateTimeUtil.calculateOverlap(min, max, LocalTime.parse("17:30:00", df4), LocalTime.parse("18:00:00", df4));
+                            overTimeBigDecimal=overTimeBigDecimal.subtract(new BigDecimal(rest1)).subtract(new BigDecimal(rest2));
+                        }
+                        for (JSONObject o : overTimeList) {
+                            //存在开始日期为当前日期的数据以及结束日期为当天日期的数据 分开计算
+                            if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(localDate)){
+                                //存在开始日期为当天的数据
+                                if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate())){
+                                    //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
+                                    //对比打卡体现的加班时长和加班单时长取小
+                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                                    if(divide.doubleValue()>o.getDouble("OverTimeDuration")){
+                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                        workTime=workTime+o.getDouble("OverTimeDuration");
+                                    }else{
+                                        workTime=workTime+round(divide.doubleValue(),0.5);
+                                    }
+                                }else {
+                                    //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
+                                    LocalDateTime start = LocalDateTime.parse(o.getString("StartDate"), df1);
+                                    LocalDateTime stop = start.toLocalDate().atTime(LocalTime.MAX);
+                                    Duration duration = Duration.between(start, stop);
+                                    BigDecimal decimal = new BigDecimal(duration.toMinutes());
+                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
+                                    double l = decimal.doubleValue();
+                                    //对比打卡体现的加班时长和加班单时长取小
+                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                                    if(divide.doubleValue()>l){
+                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                        workTime=workTime+l;
+                                    }else {
+                                        workTime=workTime+round(divide.doubleValue(),0.5);
+                                    }
+                                }
+                            }else if(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate().isEqual(localDate)){
+                                //存在结束日期为当天的数据
+                                if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate())){
+                                    //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
+                                    //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
+                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                                    if(divide.doubleValue()>o.getDouble("OverTimeDuration")){
+                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                        workTime=workTime+o.getDouble("OverTimeDuration");
+                                    }else {
+                                        workTime=workTime+round(divide.doubleValue(),0.5);
+                                    }
+                                }else {
+                                    //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
+                                    LocalDateTime stop = LocalDateTime.parse(o.getString("StopDate"), df1);
+                                    LocalDateTime start = stop.toLocalDate().atTime(LocalTime.MIN);
+                                    Duration duration = Duration.between(start, stop);
+                                    BigDecimal decimal = new BigDecimal(duration.toMinutes());
+                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
+                                    double l = decimal.doubleValue();
+                                    //对比打卡体现的加班时长和加班单时长取小
+                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                                    if(divide.doubleValue()>l){
+                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                        workTime=workTime+l;
+                                    }else {
+                                        workTime=workTime+round(divide.doubleValue(),0.5);
+                                    }
+                                }
+                            }
+                        }
+                        //处理修改
+                        List<JSONObject> vacationList = vacationStream.filter(a ->{
+                            LocalDate vacationStartDate = LocalDateTime.parse(a.getString("VacationStartDateTime"), df3).toLocalDate();
+                            LocalDate vacationStopDate = LocalDateTime.parse(a.getString("VacationStopDateTime"), df3).toLocalDate();
+                            boolean b=false;
+                            if((localDate.isAfter(vacationStartDate)||localDate.isEqual(vacationStartDate))
+                                    &&(localDate.isBefore(vacationStopDate)||localDate.isEqual(vacationStopDate))){
+                                b=true;
+                            }
+                            if(a.getString("StaffId").equals(beisen.get().getUserId())
+                                    && b
+                                    &&a.getString("DocumentType").equals("请假")
+                                    &&  (a.getString("ApproveStatus").equals("通过") || a.getString("ApproveStatus").equals("审批中"))){
+                                return true;
+                            }
+                            return false;
+                        }).collect(Collectors.toList());
+                        if(vacationList.size()>0){
+                            double vacationDuration = vacationList.stream().mapToDouble(i -> i.getDouble("VacationDuration")).sum();
+                            BigDecimal decimal = new BigDecimal(vacationDuration);
+                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
+//                            //可能存在休假多天 只减去一天
+                            if(decimal.doubleValue()>=8){
+                                workTime= workTime-8;
+                            }else {
+                                workTime= workTime-decimal.doubleValue();
+                            }
+                        }else {
+//                            //在工时管家已经同步到的请假数据中找到当前人员的所有请假数据
+//                            List<LeaveSheet> list = leaveSheetService.list(new LambdaQueryWrapper<LeaveSheet>().eq(LeaveSheet::getOwnerId, beisen.get().getUserId()));
+//                            //当前考勤日期在工时同步到的请假数据开始请假和结束日期区间的数据
+//                            List<LeaveSheet> sheets = list.stream().filter(l -> (l.getStartDate().isBefore(localDate) || l.getStartDate().isEqual(localDate)) && (l.getEndDate().isAfter(localDate) || l.getEndDate().isEqual(localDate))).collect(Collectors.toList());
+//                            double sum = sheets.stream().mapToDouble(LeaveSheet::getTimeHours).sum();
+//                            if(sum>=8){
+//                                workTime= workTime-8;
+//                            }else {
+//                                workTime= workTime-sum;
+//                            }
+                        }
+                    }
+                    UserFvTime userFvTime=new UserFvTime();
+                    userFvTime.setWorkDate(localDate);
+                    userFvTime.setStartTime(df2.format(min));
+                    userFvTime.setEndTime(df2.format(max));
+                    userFvTime.setUserId(first.get().getId());
+                    userFvTime.setCompanyId(companyId);
+                    userFvTime.setWorkHours(workTime.floatValue());
+                    UserFvTime one = userFvTimeService.getOne(new LambdaQueryWrapper<UserFvTime>().eq(UserFvTime::getCompanyId, companyId).eq(UserFvTime::getUserId, first.get().getId()).eq(UserFvTime::getWorkDate, localDate));
+                    if(one!=null){
+                        userFvTime.setId(one.getId());
+                    }
+                    userFvTimeList.add(userFvTime);
+                }
+            }
+        }
+        if(userFvTimeList.size()>0){
+            if(!userFvTimeService.saveOrUpdateBatch(userFvTimeList)){
+                msg.setError("同步验证失败");
+            }
+        }
+        return msg;
+    }
+
+    public static double round( double num, double multipleOf) {
+        if (num%multipleOf == 0){
+            return num;
+        }
+        return Math.floor(num / multipleOf) * multipleOf;
+    }
 }

+ 1 - 254
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java

@@ -2268,260 +2268,7 @@ public class TimingTask {
             startDate=LocalDate.now().minusDays(3).format(df);
             endDate=LocalDate.now().plusDays(1).format(df);
         }
-
-
-        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, 5978));
-        List<UserWithBeisen> userWithBeisenList = userWithBeisenService.list(new LambdaQueryWrapper<UserWithBeisen>().eq(UserWithBeisen::getCompanyId, 5978));
-        BeisenConfig beisenConfig = beisenConfigMapper.selectById(5978);
-        //获取特殊节假日设置
-        List<HolidaySetting> holidaySettings = holidaySettingService.list(new LambdaQueryWrapper<HolidaySetting>().eq(HolidaySetting::getCompanyId, 5978));
-        if(beisenConfig==null){
-            return;
-        }
-        //todo 获取到指定日期的加班数据
-        List<LocalDate> workDaysListInRange = WorkDayCalculateUtils.getWorkDaysListInRange(startDate, endDate, 1);
-        JSONArray allOverTimeList=new JSONArray();
-        JSONArray attendanceStatistics=new JSONArray();
-        JSONArray allVacationList=new JSONArray();
-        List<UserFvTime> userFvTimeList=new ArrayList<>();
-        List<LeaveSheet> leaveSheetList=new ArrayList<>();
-        for (LocalDate localDate : workDaysListInRange) {
-            JSONArray overTimeList = BeiSenUtils.getOverTimeList(df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
-            //todo 获取到指定日期的考勤数据
-            JSONArray attendanceStatisticList = BeiSenUtils.getAttendanceStatistics(df.format(localDate), df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
-            JSONArray vacationList = BeiSenUtils.getVacationList(df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(),1,100);
-            allOverTimeList.addAll(overTimeList);
-            attendanceStatistics.addAll(attendanceStatisticList);
-            allVacationList.addAll(vacationList);
-        }
-        for (LocalDate localDate : workDaysListInRange) {
-            Stream<JSONObject> swipingCardsStream = attendanceStatistics.stream().map(item -> (JSONObject) item);
-            //todo: 获取当天的考勤数据
-            List<JSONObject> swipingCardDateList = swipingCardsStream.filter(i -> LocalDateTime.parse(i.getString("SwipingCardDate"),df1).toLocalDate().equals(localDate)).collect(Collectors.toList());
-            for (JSONObject item : swipingCardDateList) {
-                //获取当前数据下的人员工号对应到工时管家
-                String cardNumber = item.getString("CardNumber");
-                Optional<User> first = userList.stream().filter(f -> f.getJobNumber().equals(cardNumber)).findFirst();
-                //todo: 获取考勤打卡时间集合
-                JSONArray times = item.getJSONArray("Times");
-                Stream<JSONObject> timeStream = times.stream().map(time -> (JSONObject) time);
-                Stream<JSONObject> timeStream1 = times.stream().map(time -> (JSONObject) time);
-                //获取最早上班打卡时间
-                List<LocalTime> minLocalTimeList = timeStream.filter(t -> t.getIntValue("Type") == 1).map(i -> LocalDateTime.parse(i.getString("ActualTime"),df1).toLocalTime()).collect(Collectors.toList());
-                Optional<LocalTime> minOp = minLocalTimeList.stream().min(LocalTime::compareTo);
-                //获取最早上班打卡时间
-                List<LocalTime> maxLocalTimeList = timeStream1.filter(t -> t.getIntValue("Type") == 9).map(i -> LocalDateTime.parse(i.getString("ActualTime"),df1).toLocalTime()).collect(Collectors.toList());
-                Optional<LocalTime> maxOp = maxLocalTimeList.stream().max(LocalTime::compareTo);
-                //获取最晚下班时间
-                if(first.isPresent()){
-                    boolean workDay = WorkDayCalculateUtils.isWorkDay(localDate);
-                    //todo:针对景昱 工作日默认以8小时工作制度加上加班时长 非工作日以加班时长为准
-                    Double workTime;
-                    LocalTime min = minOp.get();
-                    LocalTime max = maxOp.get();
-                    Duration between = Duration.between(min,max);
-                    if(between.toHours()<=0){
-                        continue;
-                    }else {
-                        if(workDay){
-                            //去掉休息时长
-                            workTime=8.0;
-                        }else {
-                            //去掉休息时长
-                            workTime=0.0;
-                        }
-                    }
-                    Stream<JSONObject> overTimeStream = allOverTimeList.stream().map(elment -> (JSONObject) elment);
-                    Stream<JSONObject> vacationStream = allVacationList.stream().map(elment -> (JSONObject) elment);
-                    Optional<UserWithBeisen> beisen = userWithBeisenList.stream().filter(u -> u.getJobNumber() != null && u.getJobNumber().equals(first.get().getJobNumber())).findFirst();
-                    if(beisen.isPresent()){
-                        //todo:之前的逻辑
-//                        List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
-//                                && (a.getIntValue("ApproveStatus") == 2||a.getIntValue("ApproveStatus") == 1)
-//                                &&LocalDateTime.parse(a.getString("StartDate"),df1).toLocalDate().isEqual(localDate)).collect(Collectors.toList());
-                        List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
-                                && (a.getIntValue("ApproveStatus") == 2||a.getIntValue("ApproveStatus") == 1)).collect(Collectors.toList());
-                        //加班数据可能存在结束日期是当前日期的情况的情况
-                        BigDecimal overTimeBigDecimal= new BigDecimal(0);
-                        //计算加班时长 工作日打卡超过19:00:00算加班那 非工作日全天算加班
-                        if(workDay){
-                            //工作日打卡超过19:00:00算加班那 非工作日全天算加班
-                            if(max.isAfter(LocalTime.parse("19:00:00", df4))){
-                                overTimeBigDecimal = new BigDecimal(Duration.between(LocalTime.parse("18:00:00", df4),max).toMinutes());
-                            }
-                        }else {
-                            //非工作日全天 去掉休息时长 都算加班
-                            overTimeBigDecimal=new BigDecimal(Duration.between(min, max).toMinutes()) ;
-                            long rest1 = DateTimeUtil.calculateOverlap(min, max, LocalTime.parse("12:00:00", df4), LocalTime.parse("13:00:00", df4));
-                            long rest2 = DateTimeUtil.calculateOverlap(min, max, LocalTime.parse("17:30:00", df4), LocalTime.parse("18:00:00", df4));
-                            overTimeBigDecimal=overTimeBigDecimal.subtract(new BigDecimal(rest1)).subtract(new BigDecimal(rest2));
-                        }
-                        for (JSONObject o : overTimeList) {
-                            //存在开始日期为当前日期的数据以及结束日期为当天日期的数据 分开计算
-                            if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(localDate)){
-                                //存在开始日期为当天的数据
-                                if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate())){
-                                    //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
-                                    //对比打卡体现的加班时长和加班单时长取小
-                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
-                                    if(divide.doubleValue()>o.getDouble("OverTimeDuration")){
-                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
-                                        workTime=workTime+o.getDouble("OverTimeDuration");
-                                    }else{
-                                        workTime=workTime+round(divide.doubleValue(),0.5);
-                                    }
-                                }else {
-                                    //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
-                                    LocalDateTime start = LocalDateTime.parse(o.getString("StartDate"), df1);
-                                    LocalDateTime stop = start.toLocalDate().atTime(LocalTime.MAX);
-                                    Duration duration = Duration.between(start, stop);
-                                    BigDecimal decimal = new BigDecimal(duration.toMinutes());
-                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
-                                    double l = decimal.doubleValue();
-                                    //对比打卡体现的加班时长和加班单时长取小
-                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
-                                    if(divide.doubleValue()>l){
-                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
-                                        workTime=workTime+l;
-                                    }else {
-                                        workTime=workTime+round(divide.doubleValue(),0.5);
-                                    }
-                                }
-                            }else if(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate().isEqual(localDate)){
-                                //存在结束日期为当天的数据
-                                if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate())){
-                                    //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
-                                    //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
-                                    if(divide.doubleValue()>o.getDouble("OverTimeDuration")){
-                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
-                                        workTime=workTime+o.getDouble("OverTimeDuration");
-                                    }else {
-                                        workTime=workTime+round(divide.doubleValue(),0.5);
-                                    }
-                                }else {
-                                    //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
-                                    LocalDateTime stop = LocalDateTime.parse(o.getString("StopDate"), df1);
-                                    LocalDateTime start = stop.toLocalDate().atTime(LocalTime.MIN);
-                                    Duration duration = Duration.between(start, stop);
-                                    BigDecimal decimal = new BigDecimal(duration.toMinutes());
-                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
-                                    double l = decimal.doubleValue();
-                                    //对比打卡体现的加班时长和加班单时长取小
-                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
-                                    if(divide.doubleValue()>l){
-                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
-                                        workTime=workTime+l;
-                                    }else {
-                                        workTime=workTime+round(divide.doubleValue(),0.5);
-                                    }
-                                }
-                            }
-                        }
-                        List<JSONObject> vacationList = vacationStream.filter(a ->{
-                            LocalDate vacationStartDate = LocalDateTime.parse(a.getString("VacationStartDateTime"), df3).toLocalDate();
-                            LocalDate vacationStopDate = LocalDateTime.parse(a.getString("VacationStopDateTime"), df3).toLocalDate();
-                            boolean b=false;
-                            if((localDate.isAfter(vacationStartDate)||localDate.isEqual(vacationStartDate))
-                                    &&(localDate.isBefore(vacationStopDate)||localDate.isEqual(vacationStopDate))){
-                                b=true;
-                            }
-                            if(a.getString("StaffId").equals(beisen.get().getUserId())
-                                    && b
-                                    &&a.getString("DocumentType").equals("请假")
-                                    &&  (a.getString("ApproveStatus").equals("通过") || a.getString("ApproveStatus").equals("审批中"))){
-                                return true;
-                            }
-                            return false;
-                        }).collect(Collectors.toList());
-                        if(vacationList.size()>0){
-                            double vacationDuration = vacationList.stream().mapToDouble(i -> i.getDouble("VacationDuration")).sum();
-                            BigDecimal decimal = new BigDecimal(vacationDuration);
-                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
-//                            //可能存在休假多天 只减去一天
-                            if(decimal.doubleValue()>=8){
-                                workTime= workTime-8;
-                            }else {
-                                workTime= workTime-decimal.doubleValue();
-                            }
-                        }
-                    }
-                    UserFvTime userFvTime=new UserFvTime();
-                    userFvTime.setWorkDate(localDate);
-                    userFvTime.setStartTime(df2.format(min));
-                    userFvTime.setEndTime(df2.format(max));
-                    userFvTime.setUserId(first.get().getId());
-                    userFvTime.setCompanyId(5978);
-                    userFvTime.setWorkHours(workTime.floatValue());
-                    UserFvTime one = userFvTimeService.getOne(new LambdaQueryWrapper<UserFvTime>().eq(UserFvTime::getCompanyId, 5978).eq(UserFvTime::getUserId, first.get().getId()).eq(UserFvTime::getWorkDate, localDate));
-                    if(one!=null){
-                        userFvTime.setId(one.getId());
-                    }
-                    userFvTimeList.add(userFvTime);
-                }
-            }
-        }
-        if(userFvTimeList.size()>0){
-            userFvTimeService.saveOrUpdateBatch(userFvTimeList);
-        }
-        //同步休假数据到工时管家
-        for (int i = 0; i < allVacationList.size(); i++) {
-            JSONObject jsonObject = allVacationList.getJSONObject(i);
-            Optional<UserWithBeisen> beisen = userWithBeisenList.stream().filter(b -> b.getUserId().equals(jsonObject.getString("StaffId"))).findFirst();
-            if(beisen.isPresent()){
-                Optional<User> first = userList.stream().filter(u -> u.getJobNumber().equals(beisen.get().getJobNumber())).findFirst();
-                if(first.isPresent()){
-                    LeaveSheet leaveSheet=new LeaveSheet();
-                    leaveSheet.setCompanyId(beisenConfig.getCompanyId());
-                    leaveSheet.setStatus(0);
-                    leaveSheet.setOwnerId(first.get().getId());
-                    leaveSheet.setOwnerName(first.get().getName());
-                    leaveSheet.setStartDate(LocalDateTime.parse(String.valueOf(jsonObject.get("VacationStartDateTime")),df3).toLocalDate());
-                    leaveSheet.setEndDate(LocalDateTime.parse(String.valueOf(jsonObject.get("VacationStopDateTime")),df3).toLocalDate());
-                    leaveSheet.setTimeType(1);
-                    leaveSheet.setTimeDays(jsonObject.getFloatValue("DayValueOfDuration"));
-                    leaveSheet.setTimeHours(jsonObject.getFloatValue("VacationDuration")/60);
-                    Integer leaveType;
-                    switch (jsonObject.getString("VacationType")){
-                        case "事假":leaveType=0;
-                            break;
-                        case "病假":leaveType=1;
-                            break;
-                        case "年假":leaveType=2;
-                            break;
-                        case "产假":leaveType=3;
-                            break;
-                        case "婚假":leaveType=4;
-                            break;
-                        case "丧假":leaveType=5;
-                            break;
-                        case "调休":leaveType=6;
-                            break;
-                        case "陪产假":leaveType=7;
-                            break;
-                        default:leaveType=8;
-                    }
-                    leaveSheet.setLeaveType(leaveType);
-                    leaveSheet.setRemark(jsonObject.getString("Reason"));
-                    leaveSheet.setStatus(jsonObject.getString("ApproveStatus").equals("通过")?0:jsonObject.getString("Reason").equals("审批中")?1:2);
-                    leaveSheet.setProcinstId(jsonObject.getString("VacationId"));
-                    LeaveSheet one = leaveSheetService.getOne(new LambdaQueryWrapper<LeaveSheet>().eq(LeaveSheet::getOwnerId, first.get().getId()).eq(LeaveSheet::getStartDate, leaveSheet.getStartDate()).eq(LeaveSheet::getProcinstId,leaveSheet.getProcinstId()).eq(LeaveSheet::getEndDate, leaveSheet.getEndDate()));
-                    if(one==null){
-                        leaveSheetList.add(leaveSheet);
-                    }
-                }
-            }
-        }
-        if(leaveSheetList.size()>0){
-            leaveSheetService.saveOrUpdateBatch(leaveSheetList);
-        }
-    }
-
-    public static double round( double num, double multipleOf) {
-        if (num%multipleOf == 0){
-            return num;
-        }
-        return Math.floor(num / multipleOf) * multipleOf;
+        userWithBeisenService.syncAttendanceFromBeisen(startDate,endDate,5978);
     }
 
 

+ 46 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml

@@ -1915,7 +1915,11 @@
         LEFT JOIN department d ON d.department_id=u.department_id
         LEFT JOIN (
         SELECT SUM(working_time) AS realHour,SUM(cost) AS realCost,(SUM(working_time)-SUM(overtime_hours)) AS normalHour,SUM(overtime_hours) AS overHour,group_id,dept_id
-        FROM report  WHERE state=1 <if test="startDate!=null and startDate!='' and endDate!=null and endDate!=''"> AND create_date BETWEEN #{startDate} AND #{endDate} </if>AND project_id IS NOT NULL AND company_id=#{companyId} GROUP BY group_id,dept_id) r ON r.group_id=tg.`id` and r.dept_id=u.department_id
+        FROM report  WHERE state=1
+        <if test="startDate!=null and startDate!='' and endDate!=null and endDate!=''">
+         AND create_date BETWEEN #{startDate} AND #{endDate}
+        </if>
+        AND project_id IS NOT NULL AND company_id=#{companyId} GROUP BY group_id,dept_id) r ON r.group_id=tg.`id` and r.dept_id=u.department_id
         WHERE u.company_id=#{companyId}
         AND tg.name IN ('生产部电气','生产部车间','工程部现场安装施工','工程部配合调试','研发部工艺设计','研发部结构设计','研发部BIM设计','研发部电气设计','研发部工艺调试验收','研发部电气调试验收')
         <if test="userId!=null and userId!=''">
@@ -1924,6 +1928,47 @@
         GROUP BY p.id,tg.id,d.department_id ORDER BY p.id,d.department_id
     </select>
 
+    <select id="groupExpendProcessListForChart" resultType="java.util.Map">
+        SELECT groupName,SUM(realHour) AS realHour,SUM(realCost) AS realCost,SUM(normalHour) AS normalHour,SUM(overHour) AS overHour,SUM(planHour) AS planHour,SUM(afterSetPlanHour) AS afterSetPlanHour
+         FROM   (SELECT p.project_name AS projectName,p.id AS projectId,tg.id AS groupId,d.department_name,d.department_id AS deptId,d.corpwx_deptid AS corpwxDeptId,tg.name AS groupName,
+        IFNULL(r.realHour,0) AS realHour,IFNULL(r.realCost,0) AS realCost,IFNULL(r.normalHour,0) AS normalHour,IFNULL(r.overHour,0) AS overHour,
+        IFNULL(tg.man_day*8,0) AS planHour,IFNULL((SELECT SUM(change_man_day*8) FROM `group_budget_review` WHERE group_id=tg.`id` AND `status`=1),0) AS afterSetPlanHour
+        FROM task_executor te
+        LEFT JOIN task t ON t.id=te.task_id
+        LEFT JOIN `user` u ON te.executor_id=u.id
+        LEFT JOIN task_group tg ON tg.id=t.group_id
+        LEFT JOIN project p ON p.id=tg.project_id
+        LEFT JOIN department d ON d.department_id=u.department_id
+        LEFT JOIN (
+        SELECT SUM(working_time) AS realHour,SUM(cost) AS realCost,(SUM(working_time)-SUM(overtime_hours)) AS normalHour,SUM(overtime_hours) AS overHour,group_id,dept_id
+        FROM report  WHERE state=1
+        <if test="startDate!=null and startDate!='' and endDate!=null and endDate!=''">
+            AND create_date BETWEEN #{startDate} AND #{endDate}
+        </if>
+        AND project_id IS NOT NULL AND company_id=#{companyId} GROUP BY group_id,dept_id) r ON r.group_id=tg.`id`
+        WHERE u.company_id=#{companyId}
+        <if test="listThird!=null and listThird.size()>0">
+            AND tg.project_id in
+            <foreach collection="listThird" separator="," open="(" close=")" item="item">
+                #{item}
+            </foreach>
+        </if>
+        AND tg.name IN ('生产部电气','生产部车间','工程部现场安装施工','工程部配合调试','研发部工艺设计','研发部结构设计','研发部BIM设计','研发部电气设计','研发部工艺调试验收','研发部电气调试验收')
+        <if test="userId!=null and userId!=''">
+            and t.executor_id=#{userId}
+        </if>
+        GROUP BY tg.id ORDER BY p.id,d.department_id) AS t
+        <where>
+            <if test="listFour!=null and listFour.size()>0">
+                t.groupName in
+                <foreach collection="listFour" close=")" open="(" separator="," item="item">
+                    #{item}
+                </foreach>
+            </if>
+        </where>
+         GROUP BY t.groupName
+    </select>
+
     <select id="projectExpendProcessList" resultType="java.util.Map">
         select p.id AS projectId,p.project_name as projectName,DATE_FORMAT(p.`plan_start_date`,'%Y-%m-%d') AS planStartDate,DATE_FORMAT(p.`plan_end_date`,'%Y-%m-%d') AS planEndDate,pc.name as categoryName,p.project_code as projectCode,IFNULL(SUM(te.plan_hours),0) as planHour,
         IFNULL((select SUM(working_time) from report where project_id=p.id and create_date BETWEEN #{startDate} AND #{endDate} and state=1),0) as realHour, IFNULL((select SUM(cost) from report where project_id=p.id and create_date BETWEEN #{startDate} AND #{endDate} and state=1),0) as realCost,

+ 7 - 7
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/controller/ReportController.java

@@ -1601,18 +1601,18 @@ public class ReportController {
      * date 日期 格式yyyy-mm-dd
      */
     @RequestMapping("/exportReport")
-    public HttpRespMsg exportReport(String startDate, String endDate, Integer planId,@RequestParam(defaultValue = "0") Integer stateKey,Integer departmentId) {
+    public HttpRespMsg exportReport(String startDate, String endDate, Integer planId,@RequestParam(defaultValue = "0") Integer stateKey,String deptIds) {
         //startDate和endDate间隔不得超过1年
         DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
         LocalDate start = LocalDate.parse(startDate, dateTimeFormatter);
         LocalDate end = LocalDate.parse(endDate, dateTimeFormatter);
-        if (start.until(end, ChronoUnit.DAYS) > 365) {
-            HttpRespMsg httpRespMsg = new HttpRespMsg();
-            httpRespMsg.setError("导出日报时间间隔不得超过1年");
-            return httpRespMsg;
-        }
+//        if (start.until(end, ChronoUnit.DAYS) > 365) {
+//            HttpRespMsg httpRespMsg = new HttpRespMsg();
+//            httpRespMsg.setError("导出日报时间间隔不得超过1年");
+//            return httpRespMsg;
+//        }
 
-        return reportService.exportReport(startDate, endDate, planId,stateKey,departmentId, request);
+        return reportService.exportReport(startDate, endDate, planId,stateKey,deptIds, request);
     }
     /**
      * 删除报告

+ 1 - 1
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/mapper/ReportMapper.java

@@ -204,7 +204,7 @@ public interface ReportMapper extends BaseMapper<Report> {
 
     Integer getDpetStatisticsProgressCount(Integer companyId, List<Integer> deptIds, String foremanId, String userId, String startDate, String endDate);
 
-    List<Map<String,Object>> getReportList(String startDate, String endDate, Integer planId, Integer stateKey, Integer departmentId, Integer companyId);
+    List<Map<String,Object>> getReportList(String startDate, String endDate, Integer planId, Integer stateKey,@Param("list") List<Integer> deptIdList, Integer companyId);
 
     List<Map<String,Object>> getPlanDataWithStation(Integer companyId, String startDate, String endDate, String foremanId, Integer pageStart, Integer pageSize);
 

+ 1 - 1
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/ReportService.java

@@ -139,7 +139,7 @@ public interface ReportService extends IService<Report> {
 
     HttpRespMsg exportDpetStatisticsProgressList(String deptIds, String userId, String startDate, String endDate);
 
-    HttpRespMsg exportReport(String startDate, String endDate, Integer planId, Integer stateKey, Integer departmentId, HttpServletRequest request);
+    HttpRespMsg exportReport(String startDate, String endDate, Integer planId, Integer stateKey, String deptIds, HttpServletRequest request);
 
     HttpRespMsg deleteReport(String id);
 

+ 11 - 2
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -4979,11 +4979,20 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg exportReport(String startDate, String endDate, Integer planId, Integer stateKey, Integer departmentId, HttpServletRequest request) {
+    public HttpRespMsg exportReport(String startDate, String endDate, Integer planId, Integer stateKey, String deptIds, HttpServletRequest request) {
         HttpRespMsg msg=new HttpRespMsg();
         Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
         List<Department> departmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, companyId));
-        List<Map<String,Object>> reportList=reportMapper.getReportList(startDate,endDate,planId,stateKey,departmentId,companyId);
+        List<Integer> departmentIdList=new ArrayList<>();
+        if(!StringUtils.isEmpty(deptIds)){
+            List<Integer> list = Arrays.asList(deptIds.split(",")).stream().map(i -> Integer.valueOf(i)).collect(Collectors.toList());
+            departmentIdList.addAll(list);
+            for (Integer integer : list) {
+                List<Integer> branchDepartment = getBranchDepartment(integer, departmentList);
+                departmentIdList.addAll(branchDepartment);
+            }
+        }
+        List<Map<String,Object>> reportList=reportMapper.getReportList(startDate,endDate,planId,stateKey,departmentIdList,companyId);
         List<List<String>> dataList=new ArrayList<>();
 //        String[] title={"员工","工号","所属部门","排产工单号/任务变更通知号","钢印号","工作时长","产品名称","工序名称","进度","质检类型","质检人","工作日期","填报日期"};
 //        String[] title={"所属部门","工号","员工","排产工单号/任务变更通知号","钢印号","产品名称","工序名称","进度","工作件数", "工作时长","单价","工价","汇总",

+ 5 - 2
fhKeeper/formulahousekeeper/management-workshop/src/main/resources/mapper/ReportMapper.xml

@@ -583,8 +583,11 @@
         <if test="startDate!=null and startDate!='' and endDate!=null and endDate!=''">
             and r.create_date between  #{startDate} and #{endDate}
         </if>
-        <if test="departmentId!=null">
-            and p.station_id=#{departmentId}
+        <if test="list!=null and list.size()>0">
+            and p.station_id in
+            <foreach collection="list" open="(" close=")" item="item" separator=",">
+                #{item}
+            </foreach>
         </if>
         <if test="planId!=null">
             and r.plan_id=#{planId}

+ 42 - 13
fhKeeper/formulahousekeeper/timesheet-workshop/src/views/workReport/daily.vue

@@ -669,11 +669,13 @@
                         <el-option v-for="item in allPlanList"  :key="item.id" :label="item.productName" :value="item.id"></el-option>
                     </el-select>
                 </el-form-item> -->
-                <el-form-item prop="departmentId" :label="'选择工位'" v-if="permissions.reportsCompany">
+                <el-form-item :label="'选择工位'" v-if="permissions.reportsCompany">
 
-                    <el-cascader v-if="user.userNameNeedTranslate != 1" v-model="exportParam.departmentId" :placeholder="$t('other.allDepartments')" :options="departmentList" :props="{ checkStrictly: true, value: 'id' }" clearable style="width: 350px;"></el-cascader>
-
-                    <vueCascader :size="'medium'" :widthStr="'350'" :clearable="true" :subject="departmentList" :radios="true" :distinction="'1'" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1" :selectNameChuan="$t('other.allDepartments')"></vueCascader>
+                    <!-- 部门筛选 -->
+                    <el-cascader  v-model="departmentIdArray" :options="departmentList" :placeholder="$t('qing-xuan-ze-bu-men')"
+                        :props="{ multiple: true, checkStrictly: true,expandTrigger: 'hover' }" collapse-tags :show-all-levels="false" clearable
+                        size="small" style="margin-bottom: 10px;width:180px"
+                    ></el-cascader>
 
                 </el-form-item>
                 <el-form-item prop="projectId" :label="$t('time.dateRange')">
@@ -1379,7 +1381,7 @@
         },
         data() {
             return {
-                
+                props:{ multiple: true },
                 checkTypeTxt:['自检','互检','专检'],
                 modItemDataId: null,
                 modImportTime: null,
@@ -1465,7 +1467,7 @@
                 weekDay : [this.$t('weekDay.sunday'), this.$t('weekDay.monday'), this.$t('weekDay.tuesday'), this.$t('weekDay.wednesday'), this.$t('weekDay.thursday'), this.$t('weekDay.friday'), this.$t('weekDay.saturday')],
                 statusStyle:["waiting", "filledReportStyle", "RejectStyle", "waitSubmitStyle"],
                 fillStatusList: [],
-                exportParam:{projectId: null, dateRange:[], departmentId: null},
+                exportParam:{projectId: null, dateRange:[], deptIds: null},
                 exportDialog:false,
                 timeFields:['timeType', 'workingTime', 'startTime', 'progress'],
                 subProjectList:[],
@@ -1653,6 +1655,7 @@
                 totalReportHours: 0, // 合计的工时
 
                 allPlanList: [], // 所有计划
+                departmentIdArray:[],
             };
         },
         watch: {
@@ -1697,7 +1700,7 @@
             this.exportParam.dateRange = [startStr,t];
             this.getAllDate(1);
             this.getReportList();
-            
+            this.getDepartmentList()
             // this.getFillProjectList();
             // this.getTimeType();
             this.getDepartment();
@@ -3856,7 +3859,25 @@
                         });
                 }
             },
-            
+            getDepartmentList() {
+            this.http.post( this.port.manage.depList, {},
+                res => {
+                if (res.code == "ok") {
+                    let dptlist = JSON.parse(JSON.stringify(res.data));
+                    this.departmentList = this.changeArr(dptlist);
+                } else {
+                    this.$message({
+                    message: res.msg,
+                    type: "error"
+                    });
+                }
+                },error => {
+                this.$message({
+                    message: error,
+                    type: "error"
+                });
+                });
+            },
             // 获取部门列表
             getDepartment() {
                 let day = (this.choseDay+1) > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
@@ -3871,7 +3892,7 @@
                             // })
                             return
                         }
-                        this.departmentList = JSON.parse(JSON.stringify(res.data))
+                        // this.departmentList = JSON.parse(JSON.stringify(res.data))
                         var list = res.data , list1 = JSON.parse(JSON.stringify(res.data));
                         // let noAllData = JSON.parse(JSON.stringify(res.data));
                         // if (this.user.role > 0) {
@@ -4311,20 +4332,28 @@
             //导出日报
             exportReport() {
                 this.listLoading = true;
+                var fName ='日报统计表_' + '.xlsx';
                 var param = {};
                 const { dateRange, departmentId } = this.exportParam
                 param.startDate = dateRange[0]
                 param.endDate = dateRange[1]
-                console.log(departmentId)
-                if(departmentId && departmentId.length > 0) {
-                    param.departmentId = departmentId[departmentId.length - 1]
+                let deptArr = []
+                for(var i in this.departmentIdArray){
+                let itemList = this.departmentIdArray[i] 
+                deptArr.push(itemList[itemList.length - 1])
                 }
+                param.deptIds = deptArr.join(',')
                 this.http.post('/report/exportReport', param,
                 res => {
                     this.listLoading = false;
                     if (res.code == "ok") {
-                        location.href = res.data;
+                        var filePath = res.data;
                         this.exportDialog = false;
+                        const a = document.createElement('a'); // 创建a标签
+                        a.setAttribute('download', fName);// download属性
+                        a.setAttribute('href', filePath);// href链接
+                        a.click(); //自执行点击事件
+                        a.remove();
                     } else {
                         this.$message({
                             message: res.msg,

+ 59 - 0
fhKeeper/formulahousekeeper/timesheet/src/components/echartsEchar.vue

@@ -0,0 +1,59 @@
+<template>
+  <div :id="uuid" :style="style"></div>
+</template>
+
+<script>
+import * as echarts from "echarts";
+export default {
+  props: {
+    height: {
+      type: String,
+      default: "100%",
+    },
+    width: {
+      type: String,
+      default: "100%",
+    },
+    options: {
+      type: Object,
+      default: null,
+    },
+  },
+  components: {},
+  data() {
+    return {
+      uuid: null,
+      myChart: null,
+    };
+  },
+  computed: {
+    style() {
+      return {
+        height: this.height,
+        width: this.width,
+      };
+    },
+  },
+  watch: {
+    options() {
+      if (this.myChart) {
+        this.myChart.setOption(this.options);
+      }
+    },
+  },
+  created() {
+    this.uuid = this.idGen();
+  },
+  mounted() {
+    this.myChart = echarts.init(document.getElementById(this.uuid));
+    this.myChart.setOption(this.options);
+  },
+  methods: {
+    idGen() {
+      return new Date().getTime();
+    },
+  },
+};
+</script>
+
+<style scoped lang="scss"></style>

+ 4 - 0
fhKeeper/formulahousekeeper/timesheet/src/http.js

@@ -59,6 +59,8 @@ export default {
         }
         if(localStorage.getItem('lang') == 'en') {
             data.lang = 'english'
+        } else {
+            data.lang = 'zh'
         }
         axios({
             method: 'post',
@@ -109,6 +111,8 @@ export default {
         }
         if(localStorage.getItem('lang') == 'en') {
             data.lang = 'english'
+        } else {
+            data.lang = 'zh'
         }
         axios({
             method: 'post',

+ 36 - 28
fhKeeper/formulahousekeeper/timesheet/src/views/Home.vue

@@ -36,7 +36,7 @@
                     <span class="el-dropdown-link userinfo-inner">
                         <i class="el-icon-user" style="font-size:18px" ></i>
                         <!-- {{$t('other.customerService')}} -->
-                        帮助中心
+                        {{ $t('bangZhuZhongXin') }} 
                     </span> 
                     <el-dropdown-menu slot="dropdown">
                         <el-dropdown-item >
@@ -49,14 +49,14 @@
                                 src="../assets/image/code.jpg" />
                             </div>
                             <div v-if="isCorpWX">
-                                <div>扫码添加企业微信客服</div>
+                                <div>{{ $t('saoMaTianJiaQiYeWeiXinKeFu') }}</div>
                                 <img
                                 style="width: 153px; height: 153px"
                                 src="../assets/image/qwcode.png" />
                             </div>
                             <div>
                                 <div>
-                                    <el-link type="primary" :underline="false" href="https://www.ttkuaiban.com/download/%E5%B7%A5%E6%97%B6%E7%AE%A1%E5%AE%B6%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E%E4%B9%A6.pdf">点击查看操作手册</el-link>
+                                    <el-link type="primary" :underline="false" href="https://www.ttkuaiban.com/download/%E5%B7%A5%E6%97%B6%E7%AE%A1%E5%AE%B6%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E%E4%B9%A6.pdf">{{ $t('dianJiChaKanCaoZuoShouCe') }}</el-link>
                                 </div>
                             </div>
                         </el-dropdown-item>
@@ -155,7 +155,7 @@
                         <el-menu-item v-if="item.leaf && item.children.length > 0" :index="item.children[0].path" :data-v-step="item.children[0].path">
                             <i :class="item.iconCls"></i> 
                             <!-- {{item.children[0].name}} -->
-                            <span class="bosx" v-if="$t(item.meta.text).length < 16">{{$t(item.meta.text)}}</span>
+                            <span class="bosx" v-if="$t(item.meta.text).length <= 16">{{$t(item.meta.text)}}</span>
                             <el-tooltip class="itemName bosx"  v-if="$t(item.meta.text).length > 16" effect="dark" :content="$t(item.meta.text)" placement="top">
                                 <span>{{$t(item.meta.text)}}</span>
                             </el-tooltip>
@@ -236,43 +236,43 @@
                 </el-dialog>
 
                 <el-dialog
-                    title="修改公司名称"
+                    :title="$t('xiuGaiGongSiMingCheng')"
                     :visible.sync="editCompanyNamedialog"
                     width="30%">
                     <el-form :model="companyForm" :rules="rules" ref="companyForm" label-width="100px" class="demo-ruleForm">
-                        <el-form-item label="公司名称" prop="name">
+                        <el-form-item :label="$t('gongSiMingCheng')" prop="name">
                             <el-input v-model.trim="companyForm.name"></el-input>
                         </el-form-item>
                     </el-form>
                     <span slot="footer" class="dialog-footer">
-                        <el-button @click="editCompanyNamedialog = false">取 消</el-button>
-                        <el-button type="primary" @click="editCompanyName('companyForm')">确 定</el-button>
+                        <el-button @click="editCompanyNamedialog = false">{{ $t('quXiao') }}</el-button>
+                        <el-button type="primary" @click="editCompanyName('companyForm')">{{ $t('queDing') }}</el-button>
                     </span>
                 </el-dialog>
             </section>
         </el-col>
 
         <!-- 完善工号弹窗 -->
-        <el-dialog title="完善工号" :visible.sync="perfectJobNumber" width="500px" :show-close="false">
+        <el-dialog :title="$t('wanShanGongHao')" :visible.sync="perfectJobNumber" width="500px" :show-close="false">
             <el-form :model="perfectForm" :rules="rules" ref="perfectForm" label-width="80px" class="demo-ruleForm">
-                <el-form-item label="工号" prop="jobNumber">
+                <el-form-item :label="$t('Worknumber')" prop="jobNumber">
                     <el-input v-model.trim="perfectForm.jobNumber"></el-input>
                 </el-form-item>
             </el-form>
             <span slot="footer" class="dialog-footer">
-                <el-button type="primary" @click="editPerfectJobNumber('perfectForm')">确 定</el-button>
+                <el-button type="primary" @click="editPerfectJobNumber('perfectForm')">{{ $t('queDing') }}</el-button>
             </span>
         </el-dialog>
 
         <!-- 完善名称弹窗 -->
-        <el-dialog title="完善姓名" :visible.sync="perfectName" width="500px" :show-close="false">
+        <el-dialog :title="$t('wanShanXingMing')" :visible.sync="perfectName" width="500px" :show-close="false">
             <el-form :model="perfectFormName" :rules="rules" ref="perfectFormName" label-width="80px" class="demo-ruleForm">
-                <el-form-item label="姓名" prop="userName">
+                <el-form-item :label="$t('lable.name')" prop="userName">
                     <el-input v-model.trim="perfectFormName.userName"></el-input>
                 </el-form-item>
             </el-form>
             <span slot="footer" class="dialog-footer">
-                <el-button type="primary" @click="editPerfectName('perfectFormName')">确 定</el-button>
+                <el-button type="primary" @click="editPerfectName('perfectFormName')">{{$t('queDing')}}</el-button>
             </span>
         </el-dialog>
     </el-row>
@@ -285,6 +285,7 @@
         inject:['reloads'],
         data() {
             return {
+                textLength: 16,
                 companyForm:{
                     name: '',
                 },
@@ -296,14 +297,14 @@
                 },
                 rules: {
                     name: [
-                        { required: true, message: '请输入公司名称', trigger: 'blur' },
-                        { min: 1, max: 20, message: '长度为1-20个字符', trigger: 'blur' }
+                        { required: true, message: this.$t('qingShuRuGongSiMingCheng'), trigger: 'blur' },
+                        { min: 1, max: 20, message: this.$t('changDuWei_120GeZiFu'), trigger: 'blur' }
                     ],
                     jobNumber: [
-                        { required: true, message: '请输入工号', trigger: 'blur' }
+                        { required: true, message: this.$t('qingShuRuGongHao'), trigger: 'blur' }
                     ],
                     userName: [
-                        { required: true, message: '请输入姓名', trigger: 'blur' }
+                        { required: true, message: this.$t('defaultText.PleaseEnterYourName'), trigger: 'blur' }
                     ]
                 },
                 tourFlg: false,
@@ -359,10 +360,10 @@
                     startTimeout: 1000,   //1秒后执行
                     highlight: true,
                     labels: {
-                        buttonSkip: '跳过',
-                        buttonPrevious: '上一步',
-                        buttonNext: '下一步',
-                        buttonStop: '关闭'
+                        buttonSkip: this.$t('tiaoGuo'),
+                        buttonPrevious: this.$t('btn.previousstep'),
+                        buttonNext: this.$t('btn.nextStep'),
+                        buttonStop: this.$t('Shutdown')
                     }
                 },
                 myCallbacks: {
@@ -642,7 +643,7 @@
                 var h = util.formatDate.cdTime(new Date(new Date().getTime() + this.user.remainingTime), new Date(), 'h');
                 var m = util.formatDate.cdTime(new Date(new Date().getTime() + this.user.remainingTime), new Date(), 'm');
                 var s = util.formatDate.cdTime(new Date(new Date().getTime() + this.user.remainingTime), new Date(), 's');
-                this.remainingTime = d+'天'+h+'时'+m+'分'+s+'秒';
+                this.remainingTime = d+this.$t('time.day')+h+this.$t('shi')+m+this.$t('fen')+s+this.$t('miao');
             },
 
             // 加载消息
@@ -825,7 +826,7 @@
                                             fail: function (res) {
                                                 console.log('查看错误信息', res)
                                                 if (res.errMsg.indexOf('function not exist') > -1) {
-                                                    alert('版本过低请升级')
+                                                    alert(that.$t('banBenGuoDiQingShengJi'))
                                                 }
                                             },
                                         })
@@ -833,7 +834,7 @@
                                 }, (error) => {
                                     console.log('查看错误信息' + res)
                                     if (error.errMsg.indexOf('function not exist') > -1) {
-                                        alert('版本过低请升级')
+                                        alert(that.$t('banBenGuoDiQingShengJi'))
                                     }
                                 })
                         });
@@ -861,7 +862,7 @@
                                 }
                                 sessionStorage.setItem('user', JSON.stringify(nerUser));
                                 this.$message({
-                                    message: '操作成功',
+                                    message: this.$t('operationissuccessful'),
                                     type: "success"
                                 });
                             } else {
@@ -898,7 +899,7 @@
                                 }
                                 sessionStorage.setItem('user', JSON.stringify(nerUser));
                                 this.$message({
-                                    message: '操作成功',
+                                    message: this.$t('operationissuccessful'),
                                     type: "success"
                                 });
                             } else {
@@ -976,7 +977,7 @@
             }
 
             // 判断是否为新用户
-            if(this.user.isFirstLogin == 1 && this.user.roleName == '超级管理员' && this.firstTourFalse != 'false' && this.user.createTime[0] > '2022') {
+            if(this.user.isFirstLogin == 1 && this.user.roleName == this.$t('role.superAdministrator') && this.firstTourFalse != 'false' && this.user.createTime[0] > '2022') {
                 var thats = this
                 this.tourFlg = true
                 setTimeout(() => {
@@ -999,6 +1000,13 @@
             if(this.user.dingdingUserid) {
                 this.setDDOpenData()
             }
+
+            // 中英文显示字符长度
+            if(this.language == '中文') {
+                this.textLength = 16
+            } else {
+                this.textLength = 17
+            }
         },
     };
 </script>

+ 87 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/echartsData.js

@@ -0,0 +1,87 @@
+export function getGroupConsumption(nameList = [], actualPlan = [], actualSupplement = [], summary = [], realHourList = []) {
+  let num1 = actualPlan.reduce((accumulator, currentValue) => accumulator + currentValue, 0)
+  let num2 = actualSupplement.reduce((accumulator, currentValue) => accumulator + currentValue, 0)
+  let num3 = realHourList.reduce((accumulator, currentValue) => accumulator + currentValue, 0)
+  return {
+    title: {
+      text: `求和项:合计工时:${num3}(h) 实际工时: ${num1}(h)  实际增补: ${num2}(h)`,
+      top: 20
+    },
+    tooltip: {},
+    toolbox: {},
+    grid: {
+      top: 80,
+      left: 80,
+      right: 80,
+      bottom: 120,
+    },
+    legend: {
+      data: ["实际计划", "实际增补", "汇总"],
+      top: 20,
+      right: 100
+    },
+    xAxis: [
+      {
+        data: nameList,
+        axisPointer: {
+          type: "shadow",
+        },
+        axisLabel: {
+          rotate: 45,
+        },
+      },
+    ],
+    yAxis: [
+      {
+        type: "value",
+        axisLabel: {
+          formatter: "{value} (h)",
+        },
+      },
+      {
+        type: "value",
+        axisLabel: {
+          formatter: "{value} (h)",
+        },
+      },
+    ],
+    series: [
+      {
+        name: "实际计划",
+        type: "bar",
+        stack: "one",
+        barWidth: 40,
+        itemStyle: {
+          normal: {
+            color: "#5B9BD5",
+          },
+        },
+        data: actualPlan,
+      },
+      {
+        name: "实际增补",
+        type: "bar",
+        stack: "one",
+        barWidth: 40,
+        itemStyle: {
+          normal: {
+            color: "#ED7D31",
+          },
+        },
+        data: actualSupplement,
+      },
+      {
+        name: "汇总",
+        type: "line",
+        yAxisIndex: 1,
+        lineStyle: {
+          normal: {
+            width: 3,
+            color: "#5B9BD5",
+          },
+        },
+        data: summary,
+      },
+    ],
+  }
+}

+ 70 - 6
fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue

@@ -117,6 +117,13 @@
             <el-option label="已核销" :value="1" ></el-option>
           </el-select>
         </template>
+
+        <template v-if="ins == 24">
+          <el-radio-group v-model="tabPosition" size="small" @input="getGroupConsumptionData">
+            <el-radio-button label="0">表格</el-radio-button>
+            <el-radio-button label="1">柱状图</el-radio-button>
+          </el-radio-group>
+        </template>
           
         <!-- 按部门/项目筛选 -->
         <!-- <el-select v-if="ins == 10" v-model="departmentOrProject" placeholder="请选择" size="small" @change="selcts(10)" style="margin-left:10px;width:120px">
@@ -132,6 +139,10 @@
           </el-option>
         </el-select>
 
+        <el-select v-if="ins == 24 && tabPosition == 1" v-model="groupConsumptionName" placeholder="'请选择任务分组'" clearable filterable size="small" @change="getList(true)" multiple collapse-tags style="margin-left:10px; width: 250px">
+          <el-option v-for="(item, index) in groupConsumptionList" :key="item.id" :label="item" :value="item"> </el-option>
+        </el-select>
+
         <!-- 任务分组 -->
         <el-select v-if="ins == 1 && user.companyId == '3092'" v-model="projectGroupId" :placeholder="$t('defaultText.pleaseSelectaTaskGroup')" clearable filterable size="small" @change="getList(true)" style="margin-left:10px">
           <el-option v-for="(item) in projectTaskgroupList" :key="item.id" :label="item.name" :value="item.id"></el-option>
@@ -1161,7 +1172,7 @@
             </el-table>
 
             <!-- 分组耗用进度表 -->
-            <el-table  v-if="ins == 24" :key="24" border :data="isbeCustomReport.consumptionSchedule" highlight-current-row v-loading="listLoading" :height="(+tableHeight - 0) - 1" style="width: 100%;" :span-method="objectSpanMethod">
+            <el-table  v-if="ins == 24 && tabPosition==0" :key="24" border :data="isbeCustomReport.consumptionSchedule" highlight-current-row v-loading="listLoading" :height="(+tableHeight - 0) - 1" style="width: 100%;" :span-method="objectSpanMethod">
               <el-table-column align="center" prop="projectName" :label="$t('headerTop.projectName')" min-width="200"></el-table-column>
               <el-table-column align="center" prop="department_name" :label="$t('fuZeBuMen')" min-width="150">
                 <template slot-scope="scope">
@@ -1188,6 +1199,11 @@
               <el-table-column align="center" prop="process" :label="$t('gongShiHaoYongShuai')" width="150"></el-table-column>
             </el-table>
 
+            <!-- 分组耗用进度图表 -->
+            <div v-if="ins == 24 && tabPosition!=0" class="useASchedule" :style="`height:${tableHeight + 50}px`" v-loading="groupConsumptionLoading">
+              <EchartsEchar :options="groupConsumptionOption"></EchartsEchar>
+            </div>
+
             <!-- 项目耗用进度表 -->
             <el-table  v-if="ins == 25" :key="25" border :data="isbeCustomReport.consumptionScheduleTwo" highlight-current-row v-loading="listLoading" :height="(+tableHeight) - 1" style="width: 100%;" >
               <el-table-column align="center" prop="projectName" :label="$t('headerTop.projectName')" min-width="220"></el-table-column>
@@ -1314,7 +1330,7 @@
               <el-table-column align="center" prop="onTimePercent" :label="$t('anShiWanChengShuai')" min-width="150"></el-table-column>
             </el-table>
         <!--工具条-->
-        <el-col :span="24" class="toolbar" v-if="ins != 6 && ins != 20 && ins != 21">
+        <el-col :span="24" class="toolbar" v-if="ins != 6 && ins != 20 && ins != 21 && tabPosition==0">
           <el-pagination
                 v-if="ins == 12"
                 @size-change="groupSizeChange"
@@ -1630,12 +1646,15 @@
 import selectCat from "@/components/select.vue"
 // 引入自定义级联组件
 import vueCascader from "@/components/cascader.vue"
+import EchartsEchar from "@/components/echartsEchar.vue"
+import { getGroupConsumption } from "./echartsData"
 
 export default {
   name: "expense",
   components: {
     selectCat,
-    vueCascader
+    vueCascader,
+    EchartsEchar
   },
   props: {},
   data() {
@@ -1861,6 +1880,14 @@ export default {
       writeOffOperationVisable: false,
       writeOffOperationTransitionData: {},
       writeOffStatus: '',
+      tabPosition:"0",
+
+      // 分组耗用进度图表
+      groupConsumptionOption: {},
+      groupConsumptionLoading: false,
+      groupConsumptionList: ['工程部现场安装施工', '工程部配合调试', '生产部电气', '生产部车间', '研发部BIM设计', '研发部工艺设计', '研发部工艺调试验收', '研发部电气设计', '研发部电气调试验收', '研发部结构设计'],
+      groupConsumptionName: [],
+      groupConsumptionTimer: null
     };
   },
   computed: {},
@@ -2318,7 +2345,11 @@ export default {
                   this.getProjectSchedule()
                 }
                 if(this.ins == 24) {
-                  this.getConsumptionSchedule()
+                  if(this.tabPosition == 1) {
+                    this.getGroupConsumptionData()
+                  } else {
+                    this.getConsumptionSchedule()
+                  }
                 }
                 if(this.ins == 25) {
                   this.getConsumptionScheduleTwo()
@@ -2619,6 +2650,7 @@ export default {
       this.outputValueTitle = []
       this.userId = null
       this.selUserList = this.userList
+      this.tabPosition="0"
       this.getList();
     },
     stateKeySel(){
@@ -3687,7 +3719,11 @@ export default {
         this.getProjectSchedule()
       }
       if(this.ins == 24) {
-        this.getConsumptionSchedule()
+        if(this.tabPosition == 1) {
+          this.getGroupConsumptionData()
+        } else {
+          this.getConsumptionSchedule()
+        }
       }
       if(this.ins == 25) {
         this.page=1
@@ -4250,6 +4286,32 @@ export default {
         this.writeOffOperationVisable = false
       }
       this.getList(6)
+    },
+
+    getGroupConsumptionData() {
+      if(this.groupConsumptionTimer) {
+        clearTimeout(this.groupConsumptionTimer)
+      }
+      this.groupConsumptionTimer = setTimeout(async () => {
+        if(this.tabPosition == 0) {
+          this.proJuctId = ''
+          return
+        }
+        this.groupConsumptionLoading = true
+        let { data } = await this.postData('/project/groupExpendProcessListForChart', {
+          startDate: this.rangeDatas[0],
+          endDate: this.rangeDatas[1],
+          projectIds: this.proJuctId,
+          groupNames: this.groupConsumptionName.join(',')
+        })
+        this.groupConsumptionLoading = false
+        let nameList = data.map(item => (item.groupName || ''))
+        let realHourList = data.map(item => (item.realHour || 0))
+        let actualPlan = data.map(item => (item.planHour || 0))
+        let actualSupplement = data.map(item => (item.afterSetPlanHour || 0))
+        let summary = data.map(item => (item.planHour || 0) + (item.afterSetPlanHour || 0))
+        this.groupConsumptionOption = getGroupConsumption(nameList, actualPlan, actualSupplement, summary, realHourList)
+      }, 500)
     }
   },
 };
@@ -4479,5 +4541,7 @@ export default {
 .warntext{
   color:red;
 }
-
+.useASchedule {
+  width: 100%;
+}
 </style>

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

@@ -26,7 +26,7 @@
                         <el-form-item :label="$t('other.project')">
                             <el-select v-model="filterCriteriaForm.projectId" filterable clearable
                                 :placeholder="$t('defaultText.pleaseChoose')" size="small" @change="filterSelect()">
-                                <el-option v-for="item in allProjectList" :key="item.id" :label="item.projectName"
+                                <el-option v-for="item in allProjectList" :key="item.id" :label="item.projectName + item.projectCode"
                                     :value="item.id">
                                     <div class="omitText">
                                         <div class="left">{{ item.projectName }}</div>
@@ -86,7 +86,7 @@
                             <el-select v-model="transform.projectId" filterable clearable
                                 :placeholder="$t('defaultText.pleaseChoose')" size="small" :disabled="!tableSelected.length"
                                 @change="changeProject()">
-                                <el-option v-for="item in allProjectList" :key="item.id" :label="item.projectName"
+                                <el-option v-for="item in allProjectList" :key="item.id" :label="item.projectName + item.projectCode"
                                     :value="item.id">
                                     <div class="omitText">
                                         <div class="left">{{ item.projectName }}</div>