소스 검색

Merge remote-tracking branch 'origin/master'

yusm 4 달 전
부모
커밋
eeb2ff9603
36개의 변경된 파일1469개의 추가작업 그리고 81개의 파일을 삭제
  1. 5 2
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/components/common/pullDownSelector.vue
  2. 4 4
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/moduleList/moduleList.vue
  3. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/business/businessInfo.vue
  4. 4 3
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/customer/customerInfo.vue
  5. 4 5
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/product/newAndModifiedRelatedProducts.vue
  6. 3 2
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/thread/threadInfo.vue
  7. 23 4
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/workbench.vue
  8. 7 2
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/visitorProgram/addEditorVisitor.vue
  9. 45 9
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/visitorProgram/visitorDetails.vue
  10. 21 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/BusinessOpportunityController.java
  11. 36 4
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/CustomController.java
  12. 4 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/vo/VisitPlanVO.java
  13. 2 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/BusinessOpportunityServiceImpl.java
  14. 3 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/time/VisitPlanTask.java
  15. 1 1
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/VisitPlanMapper.xml
  16. 103 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/TaskController.java
  17. 180 9
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/TaskFilesController.java
  18. 59 7
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Task.java
  19. 5 4
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/TaskFiles.java
  20. 12 6
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/TimeType.java
  21. 13 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/bo/QueryTaskChargePage.java
  22. 77 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/excel/SpecialContractMonthSalary.java
  23. 24 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/TaskChargePageVO.java
  24. 3 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/TaskFilesMapper.java
  25. 10 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/TaskMapper.java
  26. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/TaskFilesService.java
  27. 7 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/TaskService.java
  28. 366 7
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinanceServiceImpl.java
  29. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/TaskFilesServiceImpl.java
  30. 137 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/TaskServiceImpl.java
  31. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  32. 7 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java
  33. 79 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  34. 6 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TaskFilesMapper.xml
  35. 214 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TaskMapper.xml
  36. 1 1
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

+ 5 - 2
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/components/common/pullDownSelector.vue

@@ -1,8 +1,8 @@
 <template>
   <div class="w-full h-full flex flex-col">
-    <div class="w-full pt-2">
+    <div class="w-full pt-2 searchKeywords">
       <van-search v-model.trim="searchForValue" shape="round" placeholder="请输入搜索关键词"
-        @update:model-value="debouncedSearchOptions" />
+        @update:model-value="debouncedSearchOptions" input-align="left" />
     </div>
     <div class="flex-1 my-2 overflow-y-auto">
       <template v-if="renderingOptions.length == 1 && renderingOptions[0] && !renderingOptions[0].label">
@@ -187,3 +187,6 @@ onMounted(() => {
   }
 });
 </script>
+
+<style lang="scss" scoped>
+</style>

+ 4 - 4
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/moduleList/moduleList.vue

@@ -500,13 +500,13 @@ useLifecycle({
     router.on('moduleListDetailParameter', (data) => {
       reloadListData(data)
     })
+
+    router.eventOn('moduleListRefreshData', (data) => {
+      onRefresh(true)
+    })
   }
 });
 
-router.eventOn('moduleListRefreshData', (data) => {
-  onRefresh(true)
-})
-
 </script>
 
 <style lang='scss' scoped>

+ 1 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/business/businessInfo.vue

@@ -60,6 +60,7 @@
 
 <script setup>
 import { ref } from 'vue';
+import { showConfirmDialog } from 'vant';
 import { useLifecycle } from '@hooks/useCommon.js';
 import { BUSINESS_OPPORTUNITY_TRANSFER, GET_CONTACTS_WITH_MORE_I_DS, CONTACT_PERSON_ASSOCIATED_WITH_BUSINESS_OPPORTUNITY } from '@hooks/useApi'
 import requests from "@common/requests";

+ 4 - 3
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/customer/customerInfo.vue

@@ -3,7 +3,7 @@
     <div class="bg-white info flex-1 overflow-y-auto cellnormall">
       <van-cell title="客户名称" :value="info.customName" />
       <van-cell title="客户来源" :value="info.customSourceValue" />
-      <van-cell title="电话号码" :value="info.telPhone" />
+      <van-cell title="电话号码" :value="info.companyPhone" />
       <van-cell title="邮箱" :value="info.email" />
       <van-cell title="客户行业" :value="info.customerIndustryValue" />
       <van-cell title="客户级别" :value="info.customerLevelValue" />
@@ -44,6 +44,7 @@
 import { ref } from 'vue';
 import { useLifecycle } from '@hooks/useCommon.js';
 import { TRANSFER_CUSTOMERS } from '@hooks/useApi'
+import { showConfirmDialog } from 'vant';
 import requests from "@common/requests";
 import useShowToast from '@hooks/useToast'
 import useInfoStore from '@store/useInfoStore'
@@ -81,12 +82,12 @@ function confirmTransfer() {
 function claimAndClaim() {
   showConfirmDialog({
     title: '认领客户',
-    message: `确定认领【${props.info.name}】客户吗?`,
+    message: `确定认领【${props.info.customName}】客户吗?`,
   }).then(() => {
     requests.post(TRANSFER_CUSTOMERS, { ids: props.info.id, inchargerId: userInfo.userInfo.id }).then((res) => {
       toastSuccess('认领成功')
       listReloadData()
-      props.info.inchargerName = userInfo.userInfo.name
+      props.info.inchargerName = userInfo.userInfo.customName
       showDialog.value = false
     })
   })

+ 4 - 5
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/product/newAndModifiedRelatedProducts.vue

@@ -11,7 +11,6 @@
       v-model="form.productId"
       is-link
       readonly
-      required
       name="productId"
       label="产品名称"
       placeholder="请选择"
@@ -26,7 +25,7 @@
       readonly
       name="productType"
       label="产品类型"
-      placeholder="请先选择产品"
+      :placeholder="!form.productId ? '请先选择产品' : '该产品未设置类型'"
     ></van-field>
     <van-field
       class="resetStyles"
@@ -34,7 +33,7 @@
       readonly
       name="unit"
       label="单位"
-      placeholder="请先选择产品"
+      :placeholder="!form.productId ? '请先选择产品' : '该产品未设置单位'"
     ></van-field>
     <van-field
       class="resetStyles"
@@ -43,7 +42,7 @@
       readonly
       name="price"
       label="标准价格"
-      placeholder="请先选择产品"
+      :placeholder="!form.productId ? '请先选择产品' : '该产品未设置标准价格'"
     ></van-field>
     <van-field
       class="resetStyles"
@@ -52,7 +51,7 @@
       readonly
       name="inventory"
       label="库存"
-      placeholder="请先选择产品"
+      :placeholder="!form.productId ? '请先选择产品' : '该产品未设置标准库存'"
     ></van-field>
     <van-field
       class="resetStyles"

+ 3 - 2
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/thread/threadInfo.vue

@@ -40,6 +40,7 @@
 
 <script setup>
 import { ref } from 'vue';
+import { showConfirmDialog } from 'vant';
 import { useLifecycle } from '@hooks/useCommon.js';
 import { TRANSFER_CLUES } from '@hooks/useApi'
 import requests from "@common/requests";
@@ -86,12 +87,12 @@ function confirmTransfer() {
 function claimAndClaim() {
   showConfirmDialog({
     title: '认领线索',
-    message: `确定认领【${props.info.name}】线索吗?`,
+    message: `确定认领【${props.info.clueName}】线索吗?`,
   }).then(() => {
     requests.post(TRANSFER_CLUES, { ids: props.info.id, inchargerId: userInfo.userInfo.id }).then((res) => {
       toastSuccess('认领成功')
       listReloadData()
-      props.info.inchargerName = userInfo.userInfo.name
+      props.info.inchargerName = userInfo.userInfo.clueName
       showDialog.value = false
     })
   })

+ 23 - 4
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/workbench.vue

@@ -6,7 +6,7 @@
         :show-title="false" :show-mark="false" :poppable="false" :show-confirm="false" :row-height="'3rem'"
         :min-date="minDate"
         :style="{ borderRadius: '0.3rem', height: expandAndCollapse ? (calendarHeight ? calendarHeight + 'px' : 'auto') : usePxToVwView(140) }"
-        :formatter="formatter" @select="calendarSelect">
+        :formatter="formatter" @select="calendarSelect" @panel-change="calendarPanelChangeSet">
         <template #month-title></template>
         <template #bottom-info="day">
           <div class="doT" v-if="day?.bottomInfo"></div>
@@ -42,7 +42,8 @@
                   <div class="w-2/3 text-[#505050]" style="width: 62%;">拜访时间: {{ item.visitTime }}</div>
                   <div class="w-1/3 text-[#505050] flex items-center" style="width: 38%;">
                     <van-icon name="phone-o" class="text-size-in mr-2" />
-                    {{ item.telPhone }}
+                    <!-- {{ item.telPhone }} -->
+                    {{ item?.companyPhone }}
                   </div>
                 </div>
               </div>
@@ -78,7 +79,7 @@
       <div class="p16 pt-0 pb-0 flex justify-between overflow-x-auto">
         <div class="flex">
           <template v-for="item in commonModulesList">
-            <div class="w80 bg-[#FFA359] h-28 rounded-md flex flex-col items-center justify-center">
+            <div class="w80 bg-[#FFA359] h-28 rounded-md flex flex-col items-center justify-center" @click="jumpToAdd(item)">
               <div class="formImage">
                 <img class="w-full h-full" src="/src/assets/image/form.png">
               </div>
@@ -185,6 +186,23 @@ const commonExpressionsHaveBeenNodded = ref([])
 const areYouRequesting = ref(false)
 const displayFrequentlyUsedContacts = ref(false)
 
+function calendarPanelChangeSet(data) {
+  dateConditions.value = dayjs(data.date).format('YYYY-MM-DD')
+  getVisitorPlan()
+}
+
+function jumpToAdd(rows) {
+  const jumpTo = routingInfos[rows.path.replace('/', '')]
+  router.navigateTo({
+    pathName: 'addEditor',
+    success: () => {
+      router.emit('addEditorParameter', {
+        routerInfo: JSON.stringify(jumpTo)
+      })
+    }
+  })
+}
+
 function toContactDetails(item) {
   router.navigateTo({
     pathName: 'details',
@@ -266,7 +284,8 @@ function jumpToAddNewVisitors(row) {
     pathName: 'addEditorVisitor',
     success: () => {
       router.emit('addEditorVisitorParameter', {
-        row: JSON.stringify(row || {})
+        row: JSON.stringify(row || {}),
+        date: JSON.stringify(dateConditions.value || {})
       })
     }
   })

+ 7 - 2
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/visitorProgram/addEditorVisitor.vue

@@ -2,6 +2,9 @@
   <Page :title="`${addOrEdit ? '编辑' : '新增'}访客计划`">
     <template v-slot:body>
       <div class="w-full h-full flex flex-col">
+        <div class="bg-[#EAEAEA] py-4 px-5" v-if="headDate">
+          {{ headDate }}
+        </div>
         <van-form
           ref="addEditFormRef"
           show-error
@@ -98,7 +101,6 @@
             name="remindTime"
             label="提醒时间"
             placeholder="请选择"
-            :disabled="addOrEdit"
             :rules="[{ required: true, message: '' }]"
             @click="showPickerClick('remindTime')"
           >
@@ -230,6 +232,7 @@ const currentTime = ref(dayjs(new Date()).format("HH:mm").split(":"));
 const dateSelectionFiled = ref("");
 const addOrEdit = ref(true); // true 编辑,false 新增
 const addOrEditRow = ref({})
+const headDate = ref('')
 
 function onSubmit() {
   addEditFormRef.value.validate().then((res) => {
@@ -291,7 +294,7 @@ function timeConfirm({ selectedValues }) {
 }
 
 function showPickerClick(filed) {
-  const dateTimeVal = form.value[filed] ? form.value[filed] : new Date()
+  const dateTimeVal = form.value[filed] ? form.value[filed] : headDate.value ? new Date(headDate.value) : new Date()
   dateSelectionValue.value = dayjs(dateTimeVal).format("YYYY-MM-DD").split("-")
   currentTime.value = dayjs(dateTimeVal).format("HH:mm").split(":")
   dateSelectionFiled.value = filed;
@@ -301,8 +304,10 @@ function showPickerClick(filed) {
 function processingDataSource(data) {
   const row = JSON.parse(data.row);
   addOrEdit.value = Object.keys(row).length > 0 ? true : false;
+  headDate.value = JSON.parse(data.date)
   addOrEditRow.value = row
   form.value = row
+  addEditFormRef.value?.resetValidation()
   obtainThePurposeOfTheVisit();
   getReminderTime();
   getAllCustomers();

+ 45 - 9
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/visitorProgram/visitorDetails.vue

@@ -1,5 +1,8 @@
 <template>
   <Page title="访客计划详情">
+    <template v-slot:headerRight>
+      <div class="themeTextColor" v-if="detailedData.finishState == 0" @click="visitorEditor">编辑</div>
+    </template>
     <template v-slot:body>
       <!-- 头部 -->
       <div class="planDetailsHead">
@@ -14,7 +17,8 @@
         <div class="w-full flex items-center">
           <van-icon name="user-circle-o" class="text-size-in mr-2" />
           客户:
-          <div class="ml-2 themeTextColor decoration-auto underline">{{ detailedData.customName }}</div>
+          <div class="ml-2 themeTextColor decoration-auto underline" @click="jumpToCustomerDetails()">{{
+            detailedData.customName }}</div>
         </div>
       </div>
 
@@ -71,19 +75,14 @@
         <van-date-picker v-model="showDatePickerVal" @confirm="showPickerConfirm" @cancel="showDatePicker = false" />
       </van-popup>
 
-      <van-popup
-        v-model:show="timeShowPicker"
-        destroy-on-close
-        position="bottom"
-        :style="{ height: '50%' }"
-      >
+      <van-popup v-model:show="timeShowPicker" destroy-on-close position="bottom" :style="{ height: '50%' }">
         <van-time-picker v-model="currentTime" title="选择时间" @confirm="timeConfirm" />
       </van-popup>
     </template>
 
     <template v-slot:footer v-if="detailedData.finishState == 0">
       <div class="w-full flex justify-between layout">
-        <div class="footerBtnLeft layouts" @click="showContacts = true">
+        <div class="footerBtnLeft layouts" @click="showContactsCli()">
           <div class="imgClss"></div>
           联系人
         </div>
@@ -105,11 +104,12 @@
 import { ref } from "vue";
 import { showConfirmDialog } from 'vant';
 import { useLifecycle } from "@hooks/useCommon.js";
-import { OBTAIN_DETAILS_OF_THE_VISIT_PLAN, POSTPONE_THE_VISIT_PLAN, COMPLETE_THE_VISIT_PLAN } from "@hooks/useApi"
+import { OBTAIN_DETAILS_OF_THE_VISIT_PLAN, POSTPONE_THE_VISIT_PLAN, COMPLETE_THE_VISIT_PLAN, OBTAIN_CUSTOMER_DETAILS } from "@hooks/useApi"
 import useToast from "@hooks/useToast"
 import requests from "@common/requests";
 import useRouterStore from "@store/useRouterStore.js";
 import dayjs from "dayjs";
+import { routingInfos } from "@utility/generalVariables.js";
 import useFixedData from "@store/useFixedData.js";
 import PullDownSelector from "@components/common/pullDownSelector.vue";
 
@@ -125,6 +125,41 @@ const showDelayData = ref('')
 const currentTime = ref('')
 const contactList = ref([]);
 
+function visitorEditor() {
+  router.navigateTo({
+    pathName: 'addEditorVisitor',
+    success: () => {
+      router.emit('addEditorVisitorParameter', {
+        row: JSON.stringify(detailedData.value || {}),
+        date: JSON.stringify(detailedData.value.visitTime || {})
+      })
+    }
+  })
+}
+
+function jumpToCustomerDetails() {
+  const routerInfo = routingInfos['customer']
+  requests.post(OBTAIN_CUSTOMER_DETAILS, { id: detailedData.value.customId }).then(res => {
+    router.navigateTo({
+      pathName: 'details',
+      success: () => {
+        router.emit('detailParameter', {
+          routerInfo: JSON.stringify(routerInfo || {}),
+          parameter: JSON.stringify(res.data || {})
+        })
+      }
+    })
+  })
+}
+
+function showContactsCli() {
+  if(!((contactList.value || []).length)) {
+    toastText('该联系人无号码')
+    return
+  }
+  showContacts.value = true
+}
+
 function completeThePlan() {
   showConfirmDialog({
     title: `完成访客计划`,
@@ -141,6 +176,7 @@ function delayTimeEvent() {
   requests.post(POSTPONE_THE_VISIT_PLAN, { planId: detailedData.value.id, visitTime: showDelayData.value }).then(() => {
     toastSuccess(`操作成功`)
     getDetailData(detailedData.value)
+    showDelay.value = false
   })
 }
 

+ 21 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/BusinessOpportunityController.java

@@ -15,6 +15,7 @@ import com.management.platform.service.SysFunctionService;
 import com.management.platform.service.WxCorpInfoService;
 import com.management.platform.service.impl.ExcelExportServiceImpl;
 import com.management.platform.util.HttpRespMsg;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -67,6 +68,8 @@ public class BusinessOpportunityController {
     private ActionLogMapper actionLogMapper;
     @Resource
     private BusinessOpportunityService businessOpportunityService;
+    @Autowired
+    private TaskMapper taskMapper;
 
     @RequestMapping("getAll")
     public Object getAll(HttpServletRequest request) {
@@ -193,6 +196,15 @@ public class BusinessOpportunityController {
             for (String id : ids1.split(",")) {
                 ids.add(Integer.parseInt(id));
             }
+            Integer taskCount = taskMapper.selectCount(new LambdaQueryWrapper<Task>()
+                    .ne(Task::getStatus, 2)
+                    .eq(Task::getIsDelete, 0)
+                    .in(Task::getBusinessOpportunityId, ids)
+            );
+            if(null!=taskCount&&taskCount>0){
+                msg.setError("选中商机仍有关联任务,无法删除");
+                return msg;
+            }
             bOservice.isDelete(ids);
             msg.setMsg("操作成功");
         } else {
@@ -250,6 +262,15 @@ public class BusinessOpportunityController {
             bo.setUserId(user.getId());
             bo.setCreateTime(new Date());
             bo.setIsDelete(0);
+            if(StringUtils.isNotBlank(bo.getBusinessItemProductList())){
+                List<BusinessItemProduct> businessItemProducts = JSONArray.parseArray(bo.getBusinessItemProductList(), BusinessItemProduct.class);
+                for (BusinessItemProduct businessItemProduct : businessItemProducts) {
+                    if(businessItemProduct.getQuantity() > businessItemProduct.getInventory()){
+                        msg.setError("["+businessItemProduct.getProductName()+"]产品数量不能大于库存");
+                        return msg;
+                    }
+                }
+            }
             QueryWrapper<BusinessOpportunity> queryWrapper = new QueryWrapper<>();
             queryWrapper.eq("stage_id", bo.getStageId()).eq("is_delete",0).orderByDesc("seq").last("limit 1");
             List<BusinessOpportunity> list = bOservice.list(queryWrapper);

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

@@ -6,10 +6,7 @@ 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.CustomMapper;
-import com.management.platform.mapper.SysDictMapper;
-import com.management.platform.mapper.SysFormMapper;
-import com.management.platform.mapper.UserMapper;
+import com.management.platform.mapper.*;
 import com.management.platform.service.ContactsService;
 import com.management.platform.service.CustomService;
 import com.management.platform.service.WxCorpInfoService;
@@ -60,6 +57,12 @@ public class CustomController {
     private WxCorpInfoService wxCorpInfoService;
     @Autowired
     private ContactsService contactsService;
+    @Autowired
+    private TaskMapper taskMapper;
+    @Autowired
+    private BusinessOpportunityMapper businessOpportunityMapper;
+    @Autowired
+    private SalesOrderMapper salesOrderMapper;
 
 
     @RequestMapping("list")
@@ -203,6 +206,35 @@ public class CustomController {
             for (String id : ids1.split(",")) {
                 ids.add(Integer.parseInt(id));
             }
+            //任务
+            Integer taskCount = taskMapper.selectCount(new LambdaQueryWrapper<Task>()
+                            .ne(Task::getStatus,2)
+                            .eq(Task::getIsDelete,0)
+                    .in(Task::getCustomId, ids));
+            if(null!=taskCount&&taskCount>0){
+                msg.setError("选中客户仍有任务,无法删除");
+                return msg;
+            }
+            //商机
+            Integer boCount = businessOpportunityMapper.selectCount(new LambdaQueryWrapper<BusinessOpportunity>()
+                            .eq(BusinessOpportunity::getIsDelete,0)
+                    .in(BusinessOpportunity::getCustomerId, ids)
+            );
+            if(null!=boCount&&boCount>0){
+                msg.setError("选中客户仍有商机,无法删除");
+                return msg;
+            }
+
+            //销售订单
+            Integer salesCount = salesOrderMapper.selectCount(new LambdaQueryWrapper<SalesOrder>()
+                            .eq(SalesOrder::getIsDelete,0)
+                    .in(SalesOrder::getCustomId, ids));
+            if(null!=salesCount&&salesCount>0){
+                msg.setError("选中客户仍有销售订单,无法删除");
+                return msg;
+            }
+
+
             customService.isDelete(ids);
             msg.setMsg("操作成功");
         } else {

+ 4 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/vo/VisitPlanVO.java

@@ -35,6 +35,9 @@ public class VisitPlanVO {
     /**完成状态 0未完成 1已完成*/
     private Integer finishState;
 
-    /**客户电话*/
+    /**客户电话[废弃]*/
     private String telPhone;
+
+    /**公司电话*/
+    private String companyPhone;
 }

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

@@ -156,9 +156,11 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
                 // 折后价格
                 discountedPrice = discountedPrice.add(price.multiply(divide));
             }
+            if(finalPrice.compareTo(new BigDecimal(0))>0){
             BigDecimal divide = discountedPrice.divide(finalPrice, 2, BigDecimal.ROUND_UP);
             // 整单折扣率
             businessOpportunity.setFinalPrice(divide.multiply(new BigDecimal(100)));
+            }
         }
         businessOpportunity.setBusinessItemProducts(businessItemProducts);
 

+ 3 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/time/VisitPlanTask.java

@@ -11,6 +11,7 @@ import com.management.platform.service.impl.WxCorpInfoServiceImpl;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
@@ -35,7 +36,8 @@ public class VisitPlanTask {
     @Resource
     private UserMapper userMapper ;
 
-//    @Scheduled(cron = "0 0/1 * * * *")
+    @Scheduled(cron = "0 0/1 * * * *")
+    //TODO 需还原
     public void checkRemindMessage() {
         Date now = new Date();
         System.out.println("===开始检查该分钟需提醒的访客计划==="+now);

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

@@ -29,7 +29,7 @@
              , vs.visit_time, vs.remark
              , vs.remind_type, case remind_type when -1 then '自定义时间' else sd2.name end as remindTypeName
              ,vs.remind_time, vs.finish_state
-             , vs.create_by,c.tel_phone
+             , vs.create_by,c.tel_phone,c.company_phone
         from visit_plan vs
                  left join user u on vs.incharger_id = u.id
                  left join (select * from sys_dict where code = 'VisitGoal') sd1 on vs.visit_goal = sd1.id

+ 103 - 3
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/TaskController.java

@@ -3,23 +3,23 @@ package com.management.platform.controller;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.github.pagehelper.IPage;
 import com.management.platform.entity.*;
+import com.management.platform.entity.bo.QueryTaskChargePage;
 import com.management.platform.entity.vo.SysRichFunction;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.MessageUtils;
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.poi.hssf.usermodel.*;
 import org.assertj.core.util.Lists;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
@@ -118,6 +118,46 @@ public class TaskController {
     @Autowired
     private ProjectCategoryMapper projectCategoryMapper;
 
+    @Resource
+    private TimeTypeMapper timeTypeMapper;
+
+    @Resource
+    private DepartmentMapper departmentMapper;
+
+    @PostMapping("/getTaskChargePage")
+    public HttpRespMsg getTaskChargePage(
+            QueryTaskChargePage queryBO, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        msg = taskService.getTaskChargePage(queryBO,request);
+        return msg;
+    }
+
+
+
+    @PostMapping("/getFileRejectReason")
+    public HttpRespMsg getFileRejectReason(@RequestParam("taskId")String taskId,HttpServletRequest request){
+        return taskService.getFileRejectReason(taskId,request);
+    }
+
+
+    /***
+     * 文件审核
+     * @param taskId 任务id
+     * @param projectId 项目id
+     * @param auditStatus 审核状态 1通过 2驳回
+     * @param reason 驳回理由
+     * @param request
+     * @return
+     */
+    @PostMapping("/auditFile")
+    public HttpRespMsg auditFile(@RequestParam("taskId")String taskId
+            ,@RequestParam("projectId")String projectId
+            ,@RequestParam("auditStatus")Integer auditStatus
+            ,@RequestParam(value = "reason",required = false)String reason
+            ,HttpServletRequest request) {
+        return taskService.auditFile(taskId,projectId,auditStatus,reason,request);
+    }
+
     @RequestMapping("/save")
     @Transactional
     public HttpRespMsg save(Task task) throws Exception {
@@ -135,6 +175,24 @@ public class TaskController {
             task.setCreaterName(user.getName());
             task.setCreatorColor(user.getColor());
             task.setCompanyId(user.getCompanyId());
+            TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
+            Integer taskFileCharge = timeType.getTaskFileCharge();
+            if(1 == taskFileCharge){
+                //主管: 员工所在部门[department]的manager_id 阶段一
+                //项目经理:project表的in_charge_id 阶段二
+                Department department = departmentMapper.selectById(user.getDepartmentId());
+                Project project = projectMapper.selectById(task.getProjectId());
+                if(org.apache.commons.lang3.StringUtils.isBlank(department.getManagerId())){
+                    msg.setError("员工所在部门无负责人,请重新设置");
+                    return msg;
+                }
+                if(org.apache.commons.lang3.StringUtils.isBlank(project.getInchargerId())){
+                    msg.setError("该项目未设置项目经理,请重新设置");
+                    return msg;
+                }
+                task.setChargeOneId(department.getManagerId());
+                task.setChargeTwoId(project.getInchargerId());
+            }
         }
         if (!StringUtils.isEmpty(executorListStr)) {
             List<User> allUsers = userMapper.selectList(new QueryWrapper<User>().eq("company_id", user.getCompanyId()));
@@ -1282,6 +1340,47 @@ public class TaskController {
         List<Integer> pids = list.stream().map(Task::getProjectId).collect(Collectors.toList());
         pids.add(-1);
         List<Project> projectList = projectService.list(new QueryWrapper<Project>().in("id", pids));
+        TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
+        if(1 == timeType.getTaskFileCharge()){
+            List<String> userIds = new ArrayList<>();
+            List<String> chargeOneIds = list.stream().filter(t-> org.apache.commons.lang3.StringUtils.isNotBlank(t.getChargeOneId()))
+                    .map(Task::getChargeOneId).collect(Collectors.toList());
+            List<String> chargeTwoIds = list.stream().filter(t-> org.apache.commons.lang3.StringUtils.isNotBlank(t.getChargeTwoId()))
+                    .map(Task::getChargeTwoId).collect(Collectors.toList());
+            userIds.addAll(chargeOneIds);
+            userIds.addAll(chargeTwoIds);
+
+            Map<String, String> userIdNameMap = new HashMap<>();
+            if(CollectionUtils.isNotEmpty(userIds)){
+                userIds = userIds.stream().distinct().collect(Collectors.toList());
+                List<User> users = userMapper.selectList(new LambdaQueryWrapper<User>()
+                                .select(User::getId,User::getName)
+                        .in(User::getId, userIds)
+                );
+                userIdNameMap = users.stream().collect(Collectors.toMap(User::getId, User::getName));
+            }
+            for (Task task : list) {
+                if(org.apache.commons.lang3.StringUtils.isBlank(task.getChargeOneId()) || org.apache.commons.lang3.StringUtils.isBlank(task.getChargeTwoId())){
+                    continue;
+                }
+                if(1 == task.getFinalChargeStatus()){
+                    task.setFinalChargeStatusText("审核通过");
+                } else if (0 == task.getFinalChargeStatus()) {
+                    String name = "";
+                    String statusText = "";
+                    int finalStatus = 1==task.getChargeStage()?task.getChargeOneStatus():task.getChargeTwoStatus();
+                    String tmpUserId = 1==task.getChargeStage()?task.getChargeOneId():task.getChargeTwoId();
+                    name = userIdNameMap.getOrDefault(tmpUserId,"");
+                    switch (finalStatus)
+                    {
+                        case 0:  statusText = "待审核";break;
+                        case 1:  statusText = "通过";break;
+                        case 2:  statusText = "驳回";break;
+                    }
+                    task.setFinalChargeStatusText(statusText+"("+name+")");
+                }
+            }
+        }
         list.forEach(l->{
             List<TaskExecutor> executorList = taskExecutorList.stream().filter(tl -> tl.getTaskId().equals(l.getId())&&tl.getExecutorId()!=null).collect(Collectors.toList());
             l.setExecutorList(executorList);
@@ -1297,6 +1396,7 @@ public class TaskController {
         msg.data = map;
         return msg;
     }
+
     private List<Integer> getBranchDepartment(Integer departmentId, List<Department> departmentList) {
         List<Integer> list = new ArrayList<>();
         list.add(departmentId);

+ 180 - 9
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/TaskFilesController.java

@@ -1,17 +1,22 @@
 package com.management.platform.controller;
 
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.management.platform.entity.*;
 import com.management.platform.mapper.*;
 import com.management.platform.service.ProjectDocumentService;
+import com.management.platform.service.WxCorpInfoService;
 import com.management.platform.task.SFTPAsyncUploader;
-import com.management.platform.util.*;
+import com.management.platform.util.DocumentTypeUtil;
+import com.management.platform.util.FileUtil;
+import com.management.platform.util.HttpRespMsg;
+import com.management.platform.util.MessageUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.RequestMapping;
-
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.MultipartFile;
@@ -21,12 +26,10 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.File;
 import java.io.IOException;
+import java.time.LocalDateTime;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.UUID;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
 
 /**
  * <p>
@@ -53,6 +56,21 @@ public class TaskFilesController {
     @Autowired
     private SFTPAsyncUploader sftpAsyncUploader;
 
+    @Resource
+    private TaskMapper taskMapper;
+
+    @Resource
+    private TimeTypeMapper timeTypeMapper;
+
+    @Resource
+    private TaskCommentMapper taskCommentMapper;
+
+    @Resource
+    private WxCorpInfoService wxCorpInfoService;
+
+    @Resource
+    private WxCorpInfoMapper wxCorpInfoMapper;
+
     /**
      * 获取该项目下的所有有效的文件列表
      * @param keyword
@@ -93,6 +111,33 @@ public class TaskFilesController {
         record.setServerName(document.getServerName());
         record.setUrl(document.getUrl());
         taskFilesMapper.insert(record);
+
+        //判断文件阶段做回退处理
+        TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
+        if(1 == timeType.getTaskFileCharge()){
+            this.resetTaskChargeStatus(taskId);
+        }
+
+        //添加动态消息
+        Task task = taskMapper.selectById(taskId);
+        String content = user.getName()+"在任务:"+task.getName()+"中关联了文件:"+document.getDocumentName();
+        TaskComment comment =  new TaskComment();
+        comment.setTaskId(taskId);
+        comment.setUserId(user.getId());
+        comment.setContent(content);
+        comment.setCreateTime(LocalDateTime.now());
+        comment.setUserColor(user.getColor());
+        comment.setUserName(user.getName());
+        taskCommentMapper.insert(comment);
+
+//        WxCorpInfo info = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
+//        if(1 == task.getChargeStage()){
+//            User tmpUser = userMapper.selectById(task.getChargeOneId());
+//            wxCorpInfoService.sendWXCorpMsg(info,tmpUser.getCorpwxUserid(),content+",请及时审核",null, WxCorpInfoServiceImpl.TEXT_CARD_MSG_TASK_FILE_UPDATE);
+//        } else if (2 == task.getChargeStage()) {
+//            User tmpUser = userMapper.selectById(task.getChargeTwoId());
+//            wxCorpInfoService.sendWXCorpMsg(info,tmpUser.getCorpwxUserid(),content+",请及时审核",null, WxCorpInfoServiceImpl.TEXT_CARD_MSG_TASK_FILE_UPDATE);
+//        }
         return msg;
     }
 
@@ -115,11 +160,13 @@ public class TaskFilesController {
             HttpServletResponse response) throws Exception {
         HttpRespMsg msg = new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("Token"));
+        StringBuilder fileNames = new StringBuilder();
         for (MultipartFile file : files) {
             TaskFiles record = new TaskFiles();
             record.setCreatorId(user.getId());
             record.setCreatorName(user.getName());
             record.setDocumentName(file.getOriginalFilename());
+            fileNames.append(file.getOriginalFilename()).append(",");
             record.setTaskId(taskId);
             record.setProjectId(projectId);
             if (file != null && !file.isEmpty()) {
@@ -193,11 +240,39 @@ public class TaskFilesController {
             }
         }
 
+        //判断文件阶段做回退处理
+        TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
+        if(1 == timeType.getTaskFileCharge()){
+            this.resetTaskChargeStatus(taskId);
+        }
+
+        //添加动态消息
+        String resFileNames = fileNames.deleteCharAt(fileNames.length() - 1).toString();
+        Task task = taskMapper.selectById(taskId);
+        String content = user.getName()+"在任务:"+task.getName()+"中上传了文件:"+resFileNames;
+        TaskComment comment =  new TaskComment();
+        comment.setTaskId(taskId);
+        comment.setUserId(user.getId());
+        comment.setContent(content);
+        comment.setCreateTime(LocalDateTime.now());
+        comment.setUserColor(user.getColor());
+        comment.setUserName(user.getName());
+        taskCommentMapper.insert(comment);
+
+//        WxCorpInfo info = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
+//        if(1 == task.getChargeStage()){
+//            User tmpUser = userMapper.selectById(task.getChargeOneId());
+//            wxCorpInfoService.sendWXCorpMsg(info,tmpUser.getCorpwxUserid(),content+",请及时审核",null, WxCorpInfoServiceImpl.TEXT_CARD_MSG_TASK_FILE_UPDATE);
+//        } else if (2 == task.getChargeStage()) {
+//            User tmpUser = userMapper.selectById(task.getChargeTwoId());
+//            wxCorpInfoService.sendWXCorpMsg(info,tmpUser.getCorpwxUserid(),content+",请及时审核",null, WxCorpInfoServiceImpl.TEXT_CARD_MSG_TASK_FILE_UPDATE);
+//        }
+
         return msg;
     }
 
     @RequestMapping(value="delete")
-    public HttpRespMsg delFile(@RequestParam Integer id) {
+    public HttpRespMsg delFile(@RequestParam Integer id,HttpServletRequest request) {
         TaskFiles taskFiles = taskFilesMapper.selectById(id);
         if (taskFiles.getDocumentId() == null) {
             //仅当前任务上传的,需要把文件删掉
@@ -209,6 +284,34 @@ public class TaskFilesController {
         }
         taskFilesMapper.deleteById(id);
 
+        //判断文件阶段做回退处理
+        User user = userMapper.selectById(request.getHeader("Token"));
+        TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
+        if(1 == timeType.getTaskFileCharge()){
+            this.resetTaskChargeStatus(taskFiles.getTaskId());
+        }
+
+        //添加动态消息
+        Task task = taskMapper.selectById(taskFiles.getTaskId());
+        String content = user.getName()+"删除了任务:"+task.getName()+"中的文件:"+taskFiles.getDocumentName();
+        TaskComment comment =  new TaskComment();
+        comment.setTaskId(taskFiles.getTaskId());
+        comment.setUserId(user.getId());
+        comment.setContent(content);
+        comment.setCreateTime(LocalDateTime.now());
+        comment.setUserColor(user.getColor());
+        comment.setUserName(user.getName());
+        taskCommentMapper.insert(comment);
+
+//        WxCorpInfo info = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
+//        if(1 == task.getChargeStage()){
+//            User tmpUser = userMapper.selectById(task.getChargeOneId());
+//            wxCorpInfoService.sendWXCorpMsg(info,tmpUser.getCorpwxUserid(),content+",请及时审核",null, WxCorpInfoServiceImpl.TEXT_CARD_MSG_TASK_FILE_UPDATE);
+//        } else if (2 == task.getChargeStage()) {
+//            User tmpUser = userMapper.selectById(task.getChargeTwoId());
+//            wxCorpInfoService.sendWXCorpMsg(info,tmpUser.getCorpwxUserid(),content+",请及时审核",null, WxCorpInfoServiceImpl.TEXT_CARD_MSG_TASK_FILE_UPDATE);
+//        }
+
         HttpRespMsg msg = new HttpRespMsg();
         msg.data=MessageUtils.message("file.deleteSuc");
         return msg;
@@ -235,12 +338,80 @@ public class TaskFilesController {
      * taskId 任务id
      */
     @RequestMapping(value="getTaskFiles")
-    public HttpRespMsg getTaskFiles(Integer taskId) {
-        List<TaskFiles> list = taskFilesMapper.selectList(new QueryWrapper<TaskFiles>().eq("task_id", taskId));
+    public HttpRespMsg getTaskFiles(Integer taskId,HttpServletRequest request) {
+        User user = userMapper.selectById(request.getHeader("Token"));
+        Task task = taskMapper.selectById(taskId);
+        HashMap<String,Object> map = new HashMap<>();
+        TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
+        if(1 == timeType.getTaskFileCharge()){
+            if(1 == task.getFinalChargeStatus()){
+                map.put("fileChargeStatusText","审核通过");
+            } else if (0 == task.getFinalChargeStatus()) {
+                String name = "";
+                String statusText = "";
+                int finalStatus = 1==task.getChargeStage()?task.getChargeOneStatus():task.getChargeTwoStatus();
+                String userId = 1==task.getChargeStage()?task.getChargeOneId():task.getChargeTwoId();
+                User chargeUser = userMapper.selectById(userId);
+                if(null != chargeUser){
+                    name = chargeUser.getName();
+                }
+                switch (finalStatus)
+                {
+                    case 0:  statusText = "待审核";break;
+                    case 1:  statusText = "通过";break;
+                    case 2:  statusText = "驳回";break;
+                }
+                map.put("fileChargeStatusText",statusText+"("+name+")");
+            }
+        }
+        List<TaskFiles> list = taskFilesMapper.selectList(new LambdaQueryWrapper<TaskFiles>()
+                .eq(TaskFiles::getTaskId,taskId)
+        );
+        map.put("fileList",list);
         HttpRespMsg msg = new HttpRespMsg();
-        msg.data = list;
+        msg.data = map;
         return msg;
     }
 
+
+    public void resetTaskChargeStatus(Integer taskId){
+        Task task = taskMapper.selectById(taskId);
+        if(1 == task.getFinalChargeStatus()){
+            //重置阶段一、二的时间、状态、理由
+            //重置 文件审核阶段为 1 阶段一  最终审核状态为 0未通过
+            taskMapper.update(null,new LambdaUpdateWrapper<Task>()
+                    .set(Task::getFinalChargeStatus, 0)
+                    .set(Task::getChargeStage,1)
+                    .set(Task::getChargeOneStatus,0)
+                    .set(Task::getChargeTwoStatus,0)
+                    .set(Task::getChargeOneTime,null)
+                    .set(Task::getChargeTwoTime,null)
+                    .set(Task::getFileRejectReason,null)
+//                    .set(Task::getChargeOneReason,null)
+//                    .set(Task::getChargeTwoReason,null)
+                    .eq(Task::getId,task.getId())
+            );
+        } else if (0 == task.getFinalChargeStatus()) {
+            //判断当前阶段
+            if(1==task.getChargeStage()){
+                //重置阶段一的时间、状态、理由
+                taskMapper.update(null,new LambdaUpdateWrapper<Task>()
+                        .set(Task::getChargeOneStatus,0)
+                        .set(Task::getChargeOneTime,null)
+                        .set(Task::getFileRejectReason,null)
+                        .eq(Task::getId,task.getId())
+                );
+            } else if (2 == task.getChargeStage()) {
+                //重置阶段二的时间、状态、理由
+                taskMapper.update(null,new LambdaUpdateWrapper<Task>()
+                        .set(Task::getChargeTwoStatus,0)
+                        .set(Task::getChargeTwoTime,null)
+                        .set(Task::getFileRejectReason,null)
+                        .eq(Task::getId,task.getId())
+                );
+            }
+        }
+    }
+
 }
 

+ 59 - 7
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Task.java

@@ -1,20 +1,21 @@
 package com.management.platform.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.extension.activerecord.Model;
-import java.time.LocalDate;
-import com.baomidou.mybatisplus.annotation.TableId;
-import java.time.LocalDateTime;
 import com.baomidou.mybatisplus.annotation.TableField;
-import java.io.Serializable;
-import java.util.List;
-
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 import org.springframework.format.annotation.DateTimeFormat;
 
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
+
 /**
  * <p>
  * 
@@ -242,7 +243,58 @@ public class Task extends Model<Task> {
     @TableField("sap_task_code")
     private String sapTaskCode;
 
+    /**文件审核人一id*/
+    @TableField("charge_one_id")
+    private String chargeOneId;
 
+
+    /**文件审核人一的审核状态 0待审核 1通过 2驳回*/
+    @TableField("charge_one_status")
+    private Integer chargeOneStatus;
+
+    /**文件审核人一的审核时间*/
+    @TableField("charge_one_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date chargeOneTime;
+
+//    /**文件审核人一的驳回原因*/
+//    @TableField("charge_one_reason")
+//    private String chargeOneReason;
+
+    /**文件审核人二id*/
+    @TableField("charge_two_id")
+    private String chargeTwoId;
+
+
+    /**文件审核人二的审核状态 0待审核 1通过 2驳回*/
+    @TableField("charge_two_status")
+    private Integer chargeTwoStatus;
+
+    /**文件审核人二的审核时间*/
+    @TableField("charge_two_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date chargeTwoTime;
+
+//    /**文件审核人二的驳回原因*/
+//    @TableField("charge_two_reason")
+//    private String chargeTwoReason;
+
+    /**文件审核阶段 1审核人一 2审核人二 3都审核通过*/
+    @TableField("charge_stage")
+    private Integer chargeStage;
+
+    /**文件最终审核状态  0未通过 1通过*/
+    @TableField("final_charge_status")
+    private Integer finalChargeStatus;
+
+    /**文件审核驳回原因*/
+    @TableField("file_reject_reason")
+    private String fileRejectReason;
+
+    @TableField(exist = false)
+    private String finalChargeStatusText;
     @Override
     protected Serializable pkVal() {
         return this.id;

+ 5 - 4
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/TaskFiles.java

@@ -1,15 +1,16 @@
 package com.management.platform.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.extension.activerecord.Model;
-import com.baomidou.mybatisplus.annotation.TableId;
-import java.time.LocalDateTime;
 import com.baomidou.mybatisplus.annotation.TableField;
-import java.io.Serializable;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
 /**
  * <p>
  * 

+ 12 - 6
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/TimeType.java

@@ -1,16 +1,16 @@
 package com.management.platform.entity;
 
-import java.math.BigDecimal;
-import com.baomidou.mybatisplus.extension.activerecord.Model;
-import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableField;
-import java.io.Serializable;
-import java.util.List;
-
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
 /**
  * <p>
  * 
@@ -628,6 +628,12 @@ public class TimeType extends Model<TimeType> {
     @TableField("force_reject_reason")
     private Integer forceRejectReason;
 
+    /**
+     * 任务文件审核 0不启用 1启用
+     */
+    @TableField("task_file_charge")
+    private Integer taskFileCharge;
+
 
     @Override
     protected Serializable pkVal() {

+ 13 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/bo/QueryTaskChargePage.java

@@ -0,0 +1,13 @@
+package com.management.platform.entity.bo;
+
+import lombok.Data;
+
+@Data
+public class QueryTaskChargePage {
+    private Integer deptId;
+    private Integer projectId;
+    private Integer taskId;
+    private Integer pageIndex = 1;
+    private Integer pageSize;
+    private String userId;
+}

+ 77 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/excel/SpecialContractMonthSalary.java

@@ -0,0 +1,77 @@
+package com.management.platform.entity.excel;
+
+import lombok.Data;
+import org.apache.commons.lang3.StringUtils;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Data
+public class SpecialContractMonthSalary {
+    private String projectCode;
+    private String project;
+    private String userName;
+    private String departmentName;
+    private String plate1;
+    private String plate2;
+    private String plate3;
+    private String plate4;
+    private String plate5;
+    private Double workingTime;
+    private BigDecimal salary;
+    private BigDecimal bonus;
+    private BigDecimal allowance;
+    private BigDecimal old;
+    private BigDecimal medical;
+    private BigDecimal loseJob;
+    private BigDecimal injury;
+    private BigDecimal house;
+    private BigDecimal field1;
+    private BigDecimal field2;
+    private BigDecimal field3;
+    private BigDecimal field4;
+    private BigDecimal field5;
+    private BigDecimal field6;
+    private BigDecimal field7;
+    private BigDecimal cost;
+
+    public static void main(String[] args) {
+        List<SpecialContractMonthSalary> list =new ArrayList<>();
+        SpecialContractMonthSalary s1 = new SpecialContractMonthSalary();
+        s1.setPlate1("合同主体1");s1.setSalary(new BigDecimal("4"));
+
+        SpecialContractMonthSalary s2 = new SpecialContractMonthSalary();
+        s2.setPlate1("合同主体2");s2.setSalary(new BigDecimal("3"));
+
+        SpecialContractMonthSalary s3 = new SpecialContractMonthSalary();
+        s3.setPlate1("合同主体2");s3.setSalary(new BigDecimal("2"));
+
+        SpecialContractMonthSalary s4 = new SpecialContractMonthSalary();
+        s4.setSalary(new BigDecimal("2"));
+        SpecialContractMonthSalary s5 = new SpecialContractMonthSalary();
+        s5.setSalary(new BigDecimal("1"));
+
+        list.add(s1);
+        list.add(s2);
+        list.add(s3);
+        list.add(s4);
+        list.add(s5);
+
+        Map<String, List<SpecialContractMonthSalary>> collect = list.stream()
+                .collect(Collectors.groupingBy(t-> StringUtils.isBlank(t.getPlate1())?"":t.getPlate1()));
+        System.out.println("map size== "+collect.size());
+        for (Map.Entry<String, List<SpecialContractMonthSalary>> entry : collect.entrySet()) {
+            System.out.println("entry key== "+entry.getKey());
+            for (SpecialContractMonthSalary salary : entry.getValue()) {
+                System.out.println("salary== "+salary.getSalary());
+            }
+        }
+
+        System.out.println("---------------------");
+        BigDecimal bigDecimal = new BigDecimal(12);
+        System.out.println(bigDecimal.add(null));
+    }
+}

+ 24 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/TaskChargePageVO.java

@@ -0,0 +1,24 @@
+package com.management.platform.entity.vo;
+
+import com.management.platform.entity.TaskExecutor;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class TaskChargePageVO {
+    private Integer taskId;
+    private String taskName;
+    private Integer projectId;
+    private String projectName;
+    private String creatorId;
+    private Integer chargeStage;
+    private String chargeOneId;
+    private Integer chargeOneStatus;
+    private String chargeTwoId;
+    private Integer chargeTwoStatus;
+    private String finalChargeId;
+    private String finalChargeName;
+    private String executorId;
+    private List<TaskExecutor> executorList;
+}

+ 3 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/TaskFilesMapper.java

@@ -3,6 +3,8 @@ package com.management.platform.mapper;
 import com.management.platform.entity.TaskFiles;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
+import java.util.List;
+
 /**
  * <p>
  *  Mapper 接口
@@ -13,4 +15,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  */
 public interface TaskFilesMapper extends BaseMapper<TaskFiles> {
 
+    List<Integer> getAllTaskIds();
 }

+ 10 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/TaskMapper.java

@@ -1,11 +1,12 @@
 package com.management.platform.mapper;
 
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.management.platform.entity.Task;
 import com.management.platform.entity.TimeTask;
+import com.management.platform.entity.bo.QueryTaskChargePage;
+import com.management.platform.entity.vo.TaskChargePageVO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Update;
 
@@ -61,4 +62,12 @@ public interface TaskMapper extends BaseMapper<Task> {
     List<Map<String, Object>> getTaskByUserId(String startDate, String endDate, String userId, Integer pageStart, Integer pageSize);
 
     Integer getTaskByUserIdCount(String startDate, String endDate, String userId);
+
+    List<Task> getTaskWithProjectNameWithCharge(@Param(Constants.WRAPPER) Wrapper wrapper, Integer pageStart, Integer pageSize,Integer companyId,List<Integer> deptIds,String userId);
+
+    int selectCountWithCharge(@Param(Constants.WRAPPER) Wrapper wrapper,String userId);
+
+    List<TaskChargePageVO> getTaskChargePage(@Param("queryBO") QueryTaskChargePage queryBO, @Param("deptIds") List<Integer> deptIds);
+
+    int getTaskChargePageTotal(@Param("queryBO") QueryTaskChargePage queryBO, @Param("deptIds")List<Integer> branchDepartment);
 }

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

@@ -1,7 +1,7 @@
 package com.management.platform.service;
 
-import com.management.platform.entity.TaskFiles;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.management.platform.entity.TaskFiles;
 
 /**
  * <p>

+ 7 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/TaskService.java

@@ -1,10 +1,10 @@
 package com.management.platform.service;
 
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.management.platform.entity.Task;
 import com.management.platform.entity.TaskGroup;
+import com.management.platform.entity.bo.QueryTaskChargePage;
 import com.management.platform.util.HttpRespMsg;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -54,4 +54,10 @@ public interface TaskService extends IService<Task> {
     HttpRespMsg exportUserTaskCompleteDetail(String startDate, String endDate, String userId, Integer deptId);
 
     HttpRespMsg getTaskByUserId(String startDate, String endDate, String userId, Integer pageIndex, Integer pageSize);
+
+    HttpRespMsg auditFile(String taskId, String projectId, Integer auditStatus, String reason, HttpServletRequest request);
+
+    HttpRespMsg getFileRejectReason(String taskId, HttpServletRequest request);
+
+    HttpRespMsg getTaskChargePage(QueryTaskChargePage queryBO, HttpServletRequest request);
 }

+ 366 - 7
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinanceServiceImpl.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.management.platform.entity.*;
+import com.management.platform.entity.excel.SpecialContractMonthSalary;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
 import com.management.platform.util.ExcelUtil;
@@ -696,11 +697,18 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                 headList.add(MessageUtils.message("entry.projectName"));
                 //headList.add("人员");
                 headList.add(MessageUtils.message("entry.personnel"));
-                headList.add(MessageUtils.message("entry.dept"));
-                for (UserCustom userCustom : userCustoms) {
-                    headList.add(userCustom.getName());
-                    fixedColCount++;
+//                headList.add(userCustoms.get(0).getName());
+
+                if(companyId == 7737){ //
+                    headList.add(userCustoms.get(0).getName());
+                }else{
+                    headList.add(MessageUtils.message("entry.dept"));
+                    for (UserCustom userCustom : userCustoms) {
+                        headList.add(userCustom.getName());
+                        fixedColCount++;
+                    }
                 }
+
                 //headList.add("工时(h)");
                 headList.add(MessageUtils.message("entry.workHours")+"(h)");
                 fixedColCount++;
@@ -1185,9 +1193,15 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                     rowData.add(p.projectCode);
                     rowData.add(p.project);
                     rowData.add("项目合计");
-                    //部门空出来
-                    rowData.add("");
-                    userCustoms.forEach(userCustom -> {rowData.add("");});
+
+                    if(7737 == companyId){//
+                        rowData.add("");
+                    }else{
+                        //部门空出来
+                        rowData.add("");
+                        userCustoms.forEach(userCustom -> {rowData.add("");});
+                    }
+
                     rowData.add(workTimeFormatter.format(p.workingTime));
                     rowData.add(p.salary.toPlainString());
                     rowData.add(p.bonus.toPlainString());
@@ -1221,6 +1235,109 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                     rowData.add(p.cost.toPlainString());
                     allList.add(rowData);
 
+                    if(0 == onlyTotal){
+                        if(7737 == companyId){//
+                            List<SpecialContractMonthSalary> list =new ArrayList<>();
+                            //普通
+                            List<SpecialContractMonthSalary> tmpListOne =this.transProjectTimeToMonthSalary(projectTimeList,userTime,p
+                                    ,userList,finances,allDepartments,wxCorpInfo,dingding,userCustoms,cusColList);
+                            list.addAll(tmpListOne);
+                            //无项目人员成本
+                            if (assignNoProUser != null && assignNoProUser){
+                                List<SpecialContractMonthSalary> tmpListTwo = this.transNoProjectUserToMonthSalary(noProjectUser,p
+                                        ,userList,noPUserDataList,allDepartments,wxCorpInfo,dingding,userCustoms,cusColList);
+                                list.addAll(tmpListTwo);
+                            }
+
+                            if(CollectionUtils.isNotEmpty(list)){
+                                //按照合同主体分类 plate1
+//                                DecimalFormat workTimeFormatter = new DecimalFormat("0.00");
+                                Map<String, List<SpecialContractMonthSalary>> contractMap = list.stream()
+                                        .collect(Collectors.groupingBy(t-> StringUtils.isBlank(t.getPlate1())?"":t.getPlate1()));
+                                for (Map.Entry<String, List<SpecialContractMonthSalary>> entry : contractMap.entrySet()) {
+                                    String plate1 = entry.getKey();
+                                    List<SpecialContractMonthSalary> salaryList = entry.getValue();
+                                    List<String> plate1List = new ArrayList<>();
+                                    plate1List.add("");//projectCode
+                                    plate1List.add("");//project
+                                    plate1List.add("");//$userName
+//                                    plate1List.add("");//$departmentName
+                                    plate1List.add(plate1);//plate1
+
+                                    BigDecimal workingTime = new BigDecimal(0);
+                                    BigDecimal salary = new BigDecimal(0);
+                                    BigDecimal bonus = new BigDecimal(0);
+                                    BigDecimal allowance = new BigDecimal(0);
+                                    BigDecimal old = new BigDecimal(0);
+                                    BigDecimal medical = new BigDecimal(0);
+                                    BigDecimal loseJob = new BigDecimal(0);
+                                    BigDecimal injury = new BigDecimal(0);
+                                    BigDecimal house = new BigDecimal(0);
+                                    BigDecimal field1 = new BigDecimal(0);
+                                    BigDecimal field2 = new BigDecimal(0);
+                                    BigDecimal field3 = new BigDecimal(0);
+                                    BigDecimal field4 = new BigDecimal(0);
+                                    BigDecimal field5 = new BigDecimal(0);
+                                    BigDecimal field6 = new BigDecimal(0);
+                                    BigDecimal field7 = new BigDecimal(0);
+                                    BigDecimal cost = new BigDecimal(0);
+                                    for (SpecialContractMonthSalary monthSalary : salaryList) {
+                                        workingTime = workingTime.add(BigDecimal.valueOf(null == monthSalary.getWorkingTime()?0:monthSalary.getWorkingTime()));
+                                        salary = salary.add(null == monthSalary.getSalary()?new BigDecimal(0):monthSalary.getSalary());
+                                        bonus = bonus.add(null == monthSalary.getBonus()?new BigDecimal(0):monthSalary.getBonus());
+                                        allowance= allowance.add(null == monthSalary.getAllowance()?new BigDecimal(0):monthSalary.getAllowance());
+                                        old = old.add(null == monthSalary.getOld()?new BigDecimal(0):monthSalary.getOld());
+                                        medical= medical.add(null == monthSalary.getMedical()?new BigDecimal(0):monthSalary.getMedical());
+                                        loseJob = loseJob.add(null == monthSalary.getLoseJob()?new BigDecimal(0):monthSalary.getLoseJob());
+                                        injury= injury.add(null == monthSalary.getInjury()?new BigDecimal(0):monthSalary.getInjury());
+                                        house= house.add(null == monthSalary.getHouse()?new BigDecimal(0):monthSalary.getHouse());
+                                        field1 = field1.add(null == monthSalary.getField1()?new BigDecimal(0):monthSalary.getField1());
+                                        field2 = field2.add(null == monthSalary.getField2()?new BigDecimal(0):monthSalary.getField2());
+                                        field3= field3.add(null == monthSalary.getField3()?new BigDecimal(0):monthSalary.getField3());
+                                        field4 = field4.add(null == monthSalary.getField4()?new BigDecimal(0):monthSalary.getField4());
+                                        field5  = field5.add(null == monthSalary.getField5()?new BigDecimal(0):monthSalary.getField5());
+                                        field6 = field6.add(null == monthSalary.getField6()?new BigDecimal(0):monthSalary.getField6());
+                                        field7 = field7.add(null == monthSalary.getField7()?new BigDecimal(0):monthSalary.getField7());
+                                        cost = cost.add(null == monthSalary.getCost()?new BigDecimal(0):monthSalary.getCost());
+                                    }
+                                    plate1List.add(workingTime.setScale(2 ,BigDecimal.ROUND_HALF_UP).toPlainString());//workingTime
+                                    plate1List.add(salary.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());//salary
+                                    plate1List.add(bonus.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());//bonus
+                                    plate1List.add(allowance.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());//allowance
+                                    plate1List.add(old.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());//old
+                                    plate1List.add(medical.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());//medical
+                                    plate1List.add(loseJob.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());//loseJob
+                                    plate1List.add(injury.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());//injury
+                                    plate1List.add(house.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());//house
+                                    if (cusColList.size() > 0) {
+                                        plate1List.add(field1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    }
+                                    if (cusColList.size() > 1) {
+                                        plate1List.add(field2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    }
+                                    if (cusColList.size() > 2) {
+                                        plate1List.add(field3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    }
+                                    if (cusColList.size() > 3) {
+                                        plate1List.add(field4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    }
+                                    if (cusColList.size() > 4) {
+                                        plate1List.add(field5.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    }
+                                    if (cusColList.size() > 5) {
+                                        plate1List.add(field6.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    }
+                                    if (cusColList.size() > 6) {
+                                        plate1List.add(field7.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    }
+                                    plate1List.add(cost.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    allList.add(plate1List);
+                                }
+                            }
+
+                        }
+                    }
+
                     if(0 != onlyTotal){
                         //获取成员
                         for (Map<String, Object> membMap : projectTimeList) {
@@ -1449,6 +1566,7 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                                 }
                             }
                         }
+
                     }
                 }
             } else {
@@ -1630,6 +1748,247 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
         return httpRespMsg;
     }
 
+    private List<SpecialContractMonthSalary> transNoProjectUserToMonthSalary(List<Finance> noProjectUser,ProjectSumItem p
+            ,List<User> userList, List<Map> noPUserDataList
+            , List<Department> allDepartments, WxCorpInfo wxCorpInfo, CompanyDingding dingding, List<UserCustom> userCustoms
+            , List<FinanceTblcuscol> cusColList) {
+        List<SpecialContractMonthSalary> resList =new ArrayList<>();
+        for (Finance npu : noProjectUser) {
+            SpecialContractMonthSalary toAddItem = new SpecialContractMonthSalary();
+            toAddItem.setProjectCode(p.projectCode);
+            toAddItem.setProject(p.project);
+            Double workingTime = new Double(0);
+            Finance userFinance = npu;
+            Optional<Map> op = noPUserDataList.stream().filter(map->((Integer)map.get("projectId")).equals(p.projectId) && ((String)map.get("creatorId")).equals(npu.getUserId())).findFirst();
+            if (op.isPresent()) {
+                Map percentMap = op.get();
+                double percent = (double)percentMap.get("percent");
+                if (percent > 0) {
+                    //各项收入按比例计算,累加到当前项目上
+                    Finance newFinance = Finance.getByPercent(npu, percent);
+
+                    BigDecimal cost = newFinance.getTotalCost();
+                    BigDecimal salary = newFinance.getMonthCost();
+                    BigDecimal bonus = newFinance.getBonus();
+                    BigDecimal allowance = newFinance.getAllowance();
+                    BigDecimal old = newFinance.getInsuranceOld();
+                    BigDecimal medical = newFinance.getInsuranceMedical();
+                    BigDecimal loseJob = newFinance.getInsuranceLosejob();
+                    BigDecimal injury = newFinance.getInsuranceInjury();
+                    BigDecimal house = newFinance.getHouseFund();
+                    BigDecimal field1 = newFinance.getCustomField1() == null? new BigDecimal(0):newFinance.getCustomField1();
+                    BigDecimal field2 = newFinance.getCustomField2() == null? new BigDecimal(0):newFinance.getCustomField2();
+                    BigDecimal field3 = newFinance.getCustomField3() == null? new BigDecimal(0):newFinance.getCustomField3();
+                    BigDecimal field4 = newFinance.getCustomField4() == null? new BigDecimal(0):newFinance.getCustomField4();
+                    BigDecimal field5 = newFinance.getCustomField5() == null? new BigDecimal(0):newFinance.getCustomField5();
+                    BigDecimal field6 = newFinance.getCustomField6() == null? new BigDecimal(0):newFinance.getCustomField6();
+                    BigDecimal field7 = newFinance.getCustomField7() == null? new BigDecimal(0):newFinance.getCustomField7();
+                    User us = userList.stream().filter(u->u.getId().equals(npu.getUserId())).findFirst().get();
+                    if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                        toAddItem.setUserName("$userName="+(us.getCorpwxUserid()==null?"":us.getCorpwxUserid())+"$");
+                    }else if(dingding!=null&&dingding.getContactNeedTranslate()==1){
+                        toAddItem.setUserName("$userName="+us.getName()+"$");
+                    }else {
+                        toAddItem.setUserName(npu.getName());
+                    }
+
+                    //增加部门
+                    Optional<Department> first = allDepartments.stream().filter(dp -> dp.getDepartmentId().equals(us.getDepartmentId())).findFirst();
+                    if (first.isPresent()) {
+                        if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                            toAddItem.setDepartmentName("$departmentName="+(first.get().getCorpwxDeptid()==null?"":first.get().getCorpwxDeptid())+"$");
+                        }else if(dingding!=null&&dingding.getContactNeedTranslate()==1){
+                            toAddItem.setDepartmentName("$departmentName="+(first.get().getDdDeptid()==null?"":first.get().getDdDeptid())+"$");
+                        }else {
+                            toAddItem.setDepartmentName(first.get().getDepartmentName());
+                        }
+                    } else {
+                        toAddItem.setDepartmentName("");
+                    }
+                    //自定义字段的显示
+                    for (int i = 0; i < userCustoms.size(); i++) {
+                        switch (i){
+                            case 0:
+                                toAddItem.setPlate1(us.getPlate1()==null?"":us.getPlate1());
+                                break;
+                            case 1:
+                                toAddItem.setPlate2(us.getPlate2()==null?"":us.getPlate2());
+                                break;
+                            case 2:
+                                toAddItem.setPlate3(us.getPlate3()==null?"":us.getPlate3());
+                                break;
+                            case 3:
+                                toAddItem.setPlate4(us.getPlate4()==null?"":us.getPlate4());
+                                break;
+                            case 4:
+                                toAddItem.setPlate5(us.getPlate5()==null?"":us.getPlate5());
+                                break;
+                        }
+                    }
+                    toAddItem.setWorkingTime(workingTime);
+                    toAddItem.setSalary(salary);
+                    toAddItem.setBonus(bonus);
+                    toAddItem.setAllowance(allowance);
+                    toAddItem.setOld(old);
+                    toAddItem.setMedical(medical);
+                    toAddItem.setLoseJob(loseJob);
+                    toAddItem.setInjury(injury);
+                    toAddItem.setHouse(house);
+                    //自定义字段
+                    if (cusColList.size() > 0) {
+                        toAddItem.setField1(field1);
+                    }
+                    if (cusColList.size() > 1) {
+                        toAddItem.setField2(field2);
+                    }
+                    if (cusColList.size() > 2) {
+                        toAddItem.setField3(field3);
+                    }
+                    if (cusColList.size() > 3) {
+                        toAddItem.setField4(field4);
+                    }
+                    if (cusColList.size() > 4) {
+                        toAddItem.setField5(field5);
+                    }
+                    if (cusColList.size() > 5) {
+
+                        toAddItem.setField6(field6);
+                    }
+                    if (cusColList.size() > 6) {
+                        toAddItem.setField7(field7);
+                    }
+                    toAddItem.setCost(cost);
+                    resList.add(toAddItem);
+                }
+            }
+        }
+        return resList;
+    }
+
+    private List<SpecialContractMonthSalary> transProjectTimeToMonthSalary(
+            List<Map<String, Object>> projectTimeList,HashMap<String,UserWorkTime> userTime
+    ,ProjectSumItem p,List<User> userList,List<Finance> finances
+            ,List<Department> allDepartments
+            ,WxCorpInfo wxCorpInfo,CompanyDingding dingding
+            ,List<UserCustom> userCustoms,List<FinanceTblcuscol> cusColList
+    ) {
+        List<SpecialContractMonthSalary> resList= new ArrayList<>();
+        for (Map<String, Object> membMap : projectTimeList) {
+            SpecialContractMonthSalary toAddItem = new SpecialContractMonthSalary();
+            Integer projectId = ((Long) membMap.get("projectId")).intValue();
+            //修改为按照projectId匹配
+            if (projectId.equals(p.projectId)) {
+                //匹配到项目了
+                toAddItem.setProjectCode(p.projectCode);
+                toAddItem.setProject(p.project);
+                Double workingTime = (Double) membMap.get("workingTime");
+                String creatorId = (String) membMap.get("creatorId");
+                User us = userList.stream().filter(u->u.getId().equals(creatorId)).findFirst().get();
+                Optional<Finance> first = finances.stream().filter(f -> f.getUserId().equals(creatorId)).findFirst();
+                if (!first.isPresent()) {
+                    logger.info(MessageUtils.message("report.userNull",us.getName()));
+                    continue;
+                }
+                Finance userFinance = first.get();
+
+                BigDecimal cost = userFinance.getTotalCost().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                BigDecimal salary = userFinance.getMonthCost().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                BigDecimal bonus = userFinance.getBonus().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                BigDecimal allowance = userFinance.getAllowance().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                BigDecimal old = userFinance.getInsuranceOld().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                BigDecimal medical = userFinance.getInsuranceMedical().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                BigDecimal loseJob = userFinance.getInsuranceLosejob().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                BigDecimal injury = userFinance.getInsuranceInjury().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                BigDecimal house = userFinance.getHouseFund().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                BigDecimal field1 = userFinance.getCustomField1() == null? new BigDecimal(0):userFinance.getCustomField1().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                BigDecimal field2 = userFinance.getCustomField2() == null? new BigDecimal(0):userFinance.getCustomField2().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                BigDecimal field3 = userFinance.getCustomField3() == null? new BigDecimal(0):userFinance.getCustomField3().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                BigDecimal field4 = userFinance.getCustomField4() == null? new BigDecimal(0):userFinance.getCustomField4().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                BigDecimal field5 = userFinance.getCustomField5() == null? new BigDecimal(0):userFinance.getCustomField5().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                BigDecimal field6 = userFinance.getCustomField6() == null? new BigDecimal(0):userFinance.getCustomField6().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                BigDecimal field7 = userFinance.getCustomField7() == null? new BigDecimal(0):userFinance.getCustomField6().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                //增加部门
+                Optional<Department> findDept = allDepartments.stream().filter(dp -> dp.getDepartmentId().equals(us.getDepartmentId())).findFirst();
+                if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                    toAddItem.setUserName("$userName="+(us.getCorpwxUserid()==null?"":us.getCorpwxUserid())+"$");
+                    if (findDept.isPresent()) {
+                        toAddItem.setDepartmentName("$departmentName="+findDept.get().getDepartmentName()+"$");
+                    } else {
+                        toAddItem.setDepartmentName("");
+                    }
+                }else if(dingding!=null&&dingding.getContactNeedTranslate()==1){
+                    toAddItem.setUserName("$userName="+us.getName()+"$");
+                    if (findDept.isPresent()) {
+                        toAddItem.setDepartmentName("$departmentName="+findDept.get().getDepartmentName()+"$");
+                    } else {
+                        toAddItem.setDepartmentName("");
+                    }
+                }else {
+                    toAddItem.setUserName(us.getName());
+                    if (findDept.isPresent()) {
+                        toAddItem.setDepartmentName(findDept.get().getDepartmentName());
+                    } else {
+                        toAddItem.setDepartmentName("");
+                    }
+                }
+                for (int i = 0; i < userCustoms.size(); i++) {
+                    switch (i){
+                        case 0:
+                            toAddItem.setPlate1(us.getPlate1()==null?"":us.getPlate1());
+                            break;
+                        case 1:
+                            toAddItem.setPlate2(us.getPlate2()==null?"":us.getPlate2());
+                            break;
+                        case 2:
+                            toAddItem.setPlate3(us.getPlate3()==null?"":us.getPlate3());
+                            break;
+                        case 3:
+                            toAddItem.setPlate4(us.getPlate4()==null?"":us.getPlate4());
+                            break;
+                        case 4:
+                            toAddItem.setPlate5(us.getPlate5()==null?"":us.getPlate5());
+                            break;
+                    }
+                }
+                toAddItem.setWorkingTime(workingTime);
+                toAddItem.setSalary(salary);
+                toAddItem.setBonus(bonus);
+                toAddItem.setAllowance(allowance);
+                toAddItem.setOld(old);
+                toAddItem.setMedical(medical);
+                toAddItem.setLoseJob(loseJob);
+                toAddItem.setInjury(injury);
+                toAddItem.setHouse(house);
+                //自定义字段
+                if (cusColList.size() > 0) {
+                    toAddItem.setField1(field1);
+                }
+                if (cusColList.size() > 1) {
+                    toAddItem.setField2(field2);
+                }
+                if (cusColList.size() > 2) {
+                    toAddItem.setField3(field3);
+                }
+                if (cusColList.size() > 3) {
+                    toAddItem.setField4(field4);
+                }
+                if (cusColList.size() > 4) {
+                    toAddItem.setField5(field5);
+                }
+                if (cusColList.size() > 5) {
+
+                    toAddItem.setField6(field6);
+                }
+                if (cusColList.size() > 6) {
+                    toAddItem.setField7(field7);
+                }
+                toAddItem.setCost(cost);
+                resList.add(toAddItem);
+            }
+        }
+        return resList;
+    }
+
     @Override
     public HttpRespMsg getTimeCost(String yearMonth, Boolean assignNoProUser, HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();

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

@@ -1,9 +1,9 @@
 package com.management.platform.service.impl;
 
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.management.platform.entity.TaskFiles;
 import com.management.platform.mapper.TaskFilesMapper;
 import com.management.platform.service.TaskFilesService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.springframework.stereotype.Service;
 
 /**

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

@@ -5,21 +5,26 @@ import com.aliyun.dingtalkcontact_1_0.models.SearchUserResponse;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.github.pagehelper.util.StringUtil;
 import com.management.platform.entity.*;
+import com.management.platform.entity.bo.QueryTaskChargePage;
+import com.management.platform.entity.vo.TaskChargePageVO;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
 import com.management.platform.util.ExcelUtil;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.MessageUtils;
-import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.hssf.usermodel.*;
 import org.apache.poi.ss.usermodel.CellType;
 import org.apache.poi.xssf.usermodel.XSSFCell;
 import org.apache.poi.xssf.usermodel.XSSFRow;
 import org.apache.poi.xssf.usermodel.XSSFSheet;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -85,6 +90,11 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
     private DepartmentOtherManagerMapper departmentOtherManagerMapper;
     @Resource
     private ExcelExportService excelExportService;
+    @Autowired
+    private TaskFilesMapper taskFilesMapper;
+
+    @Resource
+    private TaskExecutorMapper taskExecutorMapper;
 
     @Override
     public HttpRespMsg getExecutorPanel(Integer projectId) {
@@ -767,6 +777,132 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
         return msg;
     }
 
+    @Override
+    @Transactional
+    public HttpRespMsg auditFile(String taskId, String projectId, Integer auditStatus, String reason, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        User user = userMapper.selectById(request.getHeader("Token"));
+        //获取该任务的文件审核阶段
+        Task task = taskMapper.selectById(taskId);
+        if(1 == auditStatus){
+            //通过
+            if(1 == task.getChargeStage()){
+                //阶段一,更新阶段一状态
+                taskMapper.update(null,new LambdaUpdateWrapper<Task>()
+                        .set(Task::getChargeStage,2)
+                        .set(Task::getChargeOneStatus,1)
+                        .set(Task::getChargeOneTime,new Date())
+                        .eq(Task::getId,taskId)
+                );
+            } else if (2 == task.getChargeStage()) {
+                taskMapper.update(null,new LambdaUpdateWrapper<Task>()
+                        .set(Task::getChargeStage,3)
+                        .set(Task::getFinalChargeStatus,1)
+                        .set(Task::getChargeTwoStatus,1)
+                        .set(Task::getChargeTwoTime,new Date())
+                        .eq(Task::getId,taskId)
+                );
+            }
+        } else if (2 == auditStatus) {
+            //驳回
+            WxCorpInfo info = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
+            if(1 == task.getChargeStage()){
+                //阶段一,更新阶段一状态
+                taskMapper.update(null,new LambdaUpdateWrapper<Task>()
+                        .set(Task::getFileRejectReason,reason)
+                        .set(Task::getChargeOneTime,new Date())
+                        .set(Task::getChargeOneStatus,2)
+                        .eq(Task::getId,taskId)
+                );
+            } else if (2 == task.getChargeStage()) {
+                taskMapper.update(null,new LambdaUpdateWrapper<Task>()
+                        .set(Task::getFileRejectReason,reason)
+                        .set(Task::getChargeTwoTime,new Date())
+                        .set(Task::getChargeTwoStatus,2)
+                        .eq(Task::getId,taskId)
+                );
+            }
+            List<TaskFiles> taskFiles = taskFilesMapper.selectList(new LambdaQueryWrapper<TaskFiles>()
+                    .eq(TaskFiles::getTaskId, task.getId())
+            );
+            List<String> creatorIds = taskFiles.stream().filter(t -> StringUtils.isNotBlank(t.getCreatorId()))
+                    .map(TaskFiles::getCreatorId).collect(Collectors.toList());
+            if(CollectionUtils.isNotEmpty(creatorIds)){
+                List<User> users = userMapper.selectList(new LambdaQueryWrapper<User>()
+                        .eq(User::getIsActive, 1)
+                        .in(User::getId, creatorIds)
+                );
+                if(CollectionUtils.isNotEmpty(users)){
+                    List<String> wxCorpIds = users.stream().filter(t -> StringUtils.isNotBlank(t.getCorpwxUserid()))
+                            .map(User::getCorpwxUserid).collect(Collectors.toList());
+                    if(CollectionUtils.isNotEmpty(wxCorpIds)){
+                        String join = StringUtils.join(wxCorpIds, ",");
+                        wxCorpInfoService.sendWXCorpMsg(info,join,"任务:"+task.getName()+"的文件因【"+reason+"】被驳回,请及时处理",null
+                                , WxCorpInfoServiceImpl.TEXT_CARD_MSG_TASK_FILE_REJECT);
+                    }
+                }
+            }
+
+        }
+
+        return msg;
+    }
+
+    @Override
+    public HttpRespMsg getFileRejectReason(String taskId, HttpServletRequest request) {
+        HttpRespMsg msg=new HttpRespMsg();
+        Task task = taskMapper.selectById(taskId);
+        String reason = "";
+        if(null != task){
+            reason = task.getFileRejectReason();
+        }
+//        switch (task.getChargeStage()){
+//            case 1 : reason = task.getChargeOneReason();break;
+//            case 2 : reason = task.getChargeTwoReason();break;
+//        }
+        msg.setData(reason);
+        return msg;
+    }
+
+    @Override
+    public HttpRespMsg getTaskChargePage(QueryTaskChargePage queryBO, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String userId = request.getHeader("Token");
+        User user = userMapper.selectById(userId);
+        Integer companyId = user.getCompanyId();
+        queryBO.setUserId(userId);
+
+        queryBO.setPageIndex((queryBO.getPageIndex()-1)*queryBO.getPageSize());
+
+        List<Integer> branchDepartment=null;
+        if(queryBO.getDeptId()!=null){
+            List<Department> departmentList=departmentService.list(new QueryWrapper<Department>().eq("company_id",companyId));
+            branchDepartment= getBranchDepartment(queryBO.getDeptId(), departmentList);
+        }
+
+        List<TaskChargePageVO> taskChargePage = taskMapper.getTaskChargePage(queryBO, branchDepartment);
+        if(CollectionUtils.isNotEmpty(taskChargePage)){
+            List<Integer> collect = taskChargePage.stream()
+                    .map(TaskChargePageVO::getTaskId).distinct().collect(Collectors.toList());
+
+            List<TaskExecutor> taskExecutorList = taskExecutorMapper.selectList(new QueryWrapper<TaskExecutor>().in("task_id", collect));
+
+            taskChargePage.forEach(t->{
+                List<TaskExecutor> executorList = taskExecutorList.stream()
+                        .filter(te -> te.getTaskId().equals(t.getTaskId())&&te.getExecutorId()!=null).collect(Collectors.toList());
+                t.setExecutorList(executorList);
+            });
+        }
+
+
+        int total = taskMapper.getTaskChargePageTotal(queryBO,branchDepartment);
+        Map<String, Object> map = new HashMap<>();
+        map.put("records", taskChargePage);
+        map.put("total", total);
+        msg.data = map;
+        return msg;
+    }
+
     private List<Integer> getBranchDepartment(Integer departmentId, List<Department> departmentList) {
         List<Integer> list = new ArrayList<>();
         list.add(departmentId);

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

@@ -2437,7 +2437,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
                 return msg;
             }
         }else {
-            QueryWrapper<User> wrapper = new QueryWrapper<User>().select("id, name, phone, job_number, department_id").eq("company_id", user.getCompanyId()).eq("is_active", 1);
+            QueryWrapper<User> wrapper = new QueryWrapper<User>().select("id, name, phone, job_number, department_id, is_active").eq("company_id", user.getCompanyId());
             if (departmentId != null) {
                 //获取全部子部门
                 List<Department> allDeptList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", user.getCompanyId()));

+ 7 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java

@@ -112,6 +112,9 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
 
     public static final int TEXT_CARD_MSG__ASYNC_DWONLOAD = 23;//文件异步下载
 
+    public static final int TEXT_CARD_MSG_TASK_FILE_UPDATE = 24;//任务文件更新
+    public static final int TEXT_CARD_MSG_TASK_FILE_REJECT = 25;//任务文件驳回
+
     private static Object userLock = new Object();
 
     @Value("${suitId}")
@@ -358,6 +361,10 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                     title = "异常提醒";
                 }else if (msgType.equals(TEXT_CARD_MSG_REPORT_EXCEED_LIMIT)) {
                     title = "项目/分组预估工时不足";
+                } else if (msgType.equals(TEXT_CARD_MSG_TASK_FILE_UPDATE)) {
+                    title = "任务文件更新";
+                } else if (msgType.equals(TEXT_CARD_MSG_TASK_FILE_REJECT)) {
+                    title = "任务文件被驳回";
                 }
             } else {
                 jumpUrl = jumpUrl.replace("STATE", pageRouter);

+ 79 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java

@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.management.platform.entity.*;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
+import com.management.platform.service.impl.WxCorpInfoServiceImpl;
 import com.management.platform.util.*;
 import com.management.platform.webservice.po.ProjectQueryResponse;
 import com.management.platform.webservice.po.ProjectTask;
@@ -18,6 +19,7 @@ import me.chanjar.weixin.mp.api.WxMpService;
 import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
 import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
 import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
+import org.apache.commons.collections.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.*;
@@ -173,6 +175,9 @@ public class TimingTask {
     @Resource
     private ParticipationMapper participationMapper;
 
+    @Resource
+    private TaskFilesMapper taskFilesMapper;
+
 
     private static final List<Integer> VALID_TOKEN_CHARS = new ArrayList<>();
     static {
@@ -2310,4 +2315,78 @@ public class TimingTask {
             financialAuditService.save(financialAudit);
         }
     }
+
+    @Scheduled(cron = "0 30 9 ? * *")
+    public void remindTaskFile(){
+        List<Integer> taskIds =  taskFilesMapper.getAllTaskIds();
+        if(CollectionUtils.isNotEmpty(taskIds)){
+            List<WxCorpInfo> wxCorpInfos = wxCorpInfoMapper.selectList(new LambdaQueryWrapper<WxCorpInfo>()
+                    .eq(WxCorpInfo::getSaasSyncContact,1)
+            );
+            Map<Integer, WxCorpInfo> companyWXCorpMap = new HashMap<>();
+            if(CollectionUtils.isNotEmpty(wxCorpInfos)){
+                companyWXCorpMap = wxCorpInfos.stream().collect(Collectors.toMap(WxCorpInfo::getCompanyId,t->t));
+            }
+
+            List<TimeType> timeTypes = timeTypeMapper.selectList(null);
+            Map<Integer, TimeType> companyTimeTypeMap = new HashMap<>();
+            if(CollectionUtils.isNotEmpty(timeTypes)){
+                companyTimeTypeMap = timeTypes.stream().collect(Collectors.toMap(TimeType::getCompanyId,t->t));
+            }
+
+            List<Task> tasks = taskMapper.selectList(new LambdaQueryWrapper<Task>()
+                    .eq(Task::getTaskStatus, 0)
+                    .eq(Task::getFinalChargeStatus,0)
+                    .isNotNull(Task::getChargeOneId)
+                    .ne(Task::getChargeStage,3)
+                    .in(Task::getId, taskIds)
+            );
+            if(CollectionUtils.isNotEmpty(tasks)){
+                Map<Integer, List<Task>> companyTaskMap = tasks.stream().collect(Collectors.groupingBy(Task::getCompanyId));
+                for (Map.Entry<Integer, List<Task>> entry : companyTaskMap.entrySet()) {
+                    if(0 == companyTimeTypeMap.get(entry.getKey()).getTaskFileCharge()){
+                        continue;
+                    }
+                    WxCorpInfo wxCorpInfo = companyWXCorpMap.get(entry.getKey());
+                    List<Task> companyTasks = entry.getValue();
+                    List<String> userIds = new ArrayList<>();
+                    List<String> chargeOneIds = companyTasks.stream().map(Task::getChargeOneId).collect(Collectors.toList());
+                    List<String> chargeTwoIds = companyTasks.stream().filter(t -> org.apache.commons.lang3.StringUtils.isNotBlank(t.getChargeTwoId()))
+                            .map(Task::getChargeTwoId).collect(Collectors.toList());
+                    userIds.addAll(chargeOneIds);
+                    userIds.addAll(chargeTwoIds);
+                    Map<String, String> userIdCorpWxMap = new HashMap<>();
+                    if(CollectionUtils.isNotEmpty(userIds)){
+                        userIds = userIds.stream().distinct().collect(Collectors.toList());
+                        List<User> users = userMapper.selectList(new LambdaQueryWrapper<User>()
+                                .select(User::getId,User::getCorpwxUserid)
+                                .in(User::getId, userIds)
+                        );
+                        userIdCorpWxMap = users.stream().filter(t-> org.apache.commons.lang3.StringUtils.isNotBlank(t.getCorpwxUserid()))
+                                .collect(Collectors.toMap(User::getId, User::getCorpwxUserid));
+                    }
+                    if(null != wxCorpInfo){
+                        for (Task companyTask : companyTasks) {
+                            if(1==companyTask.getChargeStage()){
+                                //阶段一的审核人提示
+                                String corpWxId = userIdCorpWxMap.get(companyTask.getChargeOneId());
+                                if(org.apache.commons.lang3.StringUtils.isNotBlank(corpWxId)){
+                                    wxCorpInfoService.sendWXCorpMsg(wxCorpInfo,corpWxId,"任务:"+companyTask.getName()+"的文件需审核,请及时处理",null
+                                            , WxCorpInfoServiceImpl.TEXT_CARD_MSG_TASK_FILE_UPDATE);
+                                }
+                            } else if (2 == companyTask.getChargeStage()) {
+                                //阶段二的审核人提示
+                                String corpWxId = userIdCorpWxMap.get(companyTask.getChargeTwoId());
+                                if(org.apache.commons.lang3.StringUtils.isNotBlank(corpWxId)){
+                                    wxCorpInfoService.sendWXCorpMsg(wxCorpInfo,corpWxId,"任务:"+companyTask.getName()+"的文件需审核,请及时处理",null
+                                            , WxCorpInfoServiceImpl.TEXT_CARD_MSG_TASK_FILE_UPDATE);
+                                }
+                            }
+                        }
+
+                    }
+                }
+            }
+        }
+    }
 }

+ 6 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TaskFilesMapper.xml

@@ -22,5 +22,11 @@
     <sql id="Base_Column_List">
         id, task_id, project_id, document_name, server_name, url, indate, size, document_type, creator_id, creator_name, document_id
     </sql>
+    <select id="getAllTaskIds" resultType="java.lang.Integer">
+        select task_id
+        from task_files
+        where task_id is not null
+        group by task_id
+    </select>
 
 </mapper>

+ 214 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TaskMapper.xml

@@ -96,6 +96,16 @@
         <result column="sap_task_code" property="sapTaskCode" />
         <result column="stages_name" property="stagesName" />
         <result column="department_name" property="departmentName" />
+
+        <result column="charge_one_id" property="chargeOneId" />
+        <result column="charge_one_status" property="chargeOneStatus" />
+        <result column="charge_one_time" property="chargeOneTime" />
+        <result column="charge_two_id" property="chargeTwoId" />
+        <result column="charge_two_status" property="chargeTwoStatus" />
+        <result column="charge_two_time" property="chargeTwoTime" />
+        <result column="charge_stage" property="chargeStage" />
+        <result column="final_charge_status" property="finalChargeStatus" />
+        <result column="reject_reason" property="rejectReason"></result>
     </resultMap>
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
@@ -226,6 +236,7 @@
     <select id="getTaskWithProjectName" resultMap="RichResultMap">
         SELECT task.id, task.project_id, task.name, task.executor_name, task.start_date, task.`end_date`,task.create_date, task.`creater_id`, task.`creater_name`, task.group_id,
         task.plan_hours, task.task_type, task.task_level, task.task_status, task.`finish_date`, project.`project_name`, stages.stages_name,department.department_name
+        ,task.charge_one_id,task.charge_one_status,task.charge_two_id,task.charge_two_status,task.charge_stage,task.final_charge_status
         FROM task LEFT JOIN project ON project.id = task.`project_id`
         left join stages on stages.id = task.stages_id
         left join department on department.department_id=project.dept_id
@@ -360,4 +371,207 @@
         WHERE t.start_date &lt; #{endDate} AND t.end_date &gt; #{startDate} AND FIND_IN_SET(#{userId},t.`executor_id`) GROUP BY t.`id`
         )as total
     </select>
+    <select id="getTaskWithProjectNameWithCharge" resultMap="RichResultMap">
+        SELECT task.id, task.project_id, task.name, task.executor_name, task.start_date, task.`end_date`,task.create_date, task.`creater_id`, task.`creater_name`, task.group_id,
+        task.plan_hours, task.task_type, task.task_level, task.task_status, task.`finish_date`, project.`project_name`, stages.stages_name,department.department_name
+        ,task.charge_one_id,task.charge_one_status,task.charge_two_id,task.charge_two_status,task.charge_stage,task.final_charge_status
+        FROM task LEFT JOIN project ON project.id = task.`project_id`
+        left join stages on stages.id = task.stages_id
+        left join department on department.department_id=project.dept_id
+        ${ew.customSqlSegment}
+        <if test="deptIds!=null and deptIds.size()>0">
+            and project.dept_id in
+            <foreach collection="deptIds" open="(" close=")" separator="," item="item">
+                #{item}
+            </foreach>
+        </if>
+        <if test="userId != null and userId != ''">
+        and task.final_charge_status = 0
+        and case task.charge_stage
+        when 1 then task.charge_one_id = #{userId} and task.charge_one_status = 0
+        when 2 then task.charge_two_id = #{userId} and task.charge_two_status = 0
+        end
+        </if>
+        ORDER BY task.indate desc
+        <if test="pageStart != null and pageSize != null">
+            limit #{pageStart}, #{pageSize}
+        </if>
+    </select>
+    <select id="selectCountWithCharge" resultType="java.lang.Integer">
+        SELECT count(*)
+        FROM task
+        ${ew.customSqlSegment}
+        <if test="userId != null and userId != ''">
+            and task.final_charge_status = 0
+            and case task.charge_stage
+            when 1 then task.charge_one_id = #{userId} and task.charge_one_status = 0
+            when 2 then task.charge_two_id = #{userId} and task.charge_two_status = 0
+            end
+        </if>
+    </select>
+    <select id="getTaskChargePage" resultType="com.management.platform.entity.vo.TaskChargePageVO">
+        select tmp1.*,user.name as finalChargeName
+        from
+            (
+                select tf.task_id,tf.creator_id,task.name as taskName,task.charge_stage
+                     ,task.charge_one_id,task.charge_one_status,task.executor_id
+                     ,task.charge_two_id,task.charge_two_status,p.id as projectId,p.project_name,
+                    case task.charge_stage
+                        when 1 then task.charge_one_id
+                        when 2 then task.charge_two_id
+                        end as finalChargeId
+                from
+                    task_files tf
+                        left join task on tf.task_id = task.id
+                        left join project p on task.project_id = p.id
+                <where>
+                    task.task_status = 0 and task.final_charge_status = 0
+                    and case task.charge_stage
+                    when 1 then p.incharger_id = task.charge_one_id
+                    when 2 then p.incharger_id = task.charge_two_id
+                    end
+                    <if test="queryBO.projectId != null">
+                        and tf.project_id = #{queryBO.projectId}
+                    </if>
+                    <if test="queryBO.taskId != null">
+                        and tf.task_id = #{queryBO.taskId}
+                    </if>
+                    <if test="deptIds!=null and deptIds.size()>0">
+                        and p.dept_id in
+                        <foreach collection="deptIds" open="(" close=")" separator="," item="item">
+                            #{item}
+                        </foreach>
+                    </if>
+                </where>
+            )
+                tmp1 left join user on tmp1.finalChargeId = user.id
+        where tmp1.finalChargeId = #{queryBO.userId}
+        group by tmp1.task_id
+        union  all
+        select tmp1.*,user.name as finalChargeName
+        from
+            (
+                select tf.task_id,tf.creator_id,task.name as taskName,task.charge_stage
+                     ,task.charge_one_id,task.charge_one_status,task.executor_id
+                     ,task.charge_two_id,task.charge_two_status,project.id as projectId,project.project_name,
+                    case task.charge_stage
+                        when 1 then task.charge_one_id
+                        when 2 then task.charge_two_id
+                        end as finalChargeId
+                from
+                    task_files tf
+                        left join task on tf.task_id = task.id
+                        left join project on task.project_id = project.id
+                        left join user on tf.creator_id = user.id
+                        left join department d on user.department_id = d.department_id
+                <where>
+                    task.task_status = 0 and task.final_charge_status = 0
+                    and case task.charge_stage
+                    when 1 then d.manager_id = task.charge_one_id
+                    when 2 then d.manager_id = task.charge_two_id
+                    end
+                    <if test="queryBO.projectId != null">
+                        and tf.project_id = #{queryBO.projectId}
+                    </if>
+                    <if test="queryBO.taskId != null">
+                        and tf.task_id = #{queryBO.taskId}
+                    </if>
+                    <if test="deptIds!=null and deptIds.size()>0">
+                        and project.dept_id in
+                        <foreach collection="deptIds" open="(" close=")" separator="," item="item">
+                            #{item}
+                        </foreach>
+                    </if>
+                </where>
+            )
+                tmp1 left join user on tmp1.finalChargeId = user.id
+        where tmp1.finalChargeId = #{queryBO.userId}
+        group by tmp1.task_id
+        ORDER BY task_id desc
+        <if test="queryBO.pageIndex != null and queryBO.pageSize != null">
+            limit #{queryBO.pageIndex}, #{queryBO.pageSize}
+        </if>
+    </select>
+    <select id="getTaskChargePageTotal" resultType="java.lang.Integer">
+        select count(*)
+        from(
+        select tmp1.*,user.name as finalChargeName
+        from
+        (
+        select tf.task_id,tf.creator_id,task.name,task.charge_stage
+        ,task.charge_one_id,task.charge_one_status,task.executor_id
+        ,task.charge_two_id,task.charge_two_status,p.id,p.project_name,
+        case task.charge_stage
+        when 1 then task.charge_one_id
+        when 2 then task.charge_two_id
+        end as finalChargeId
+        from
+        task_files tf
+        left join task on tf.task_id = task.id
+        left join project p on task.project_id = p.id
+        <where>
+            task.task_status = 0 and task.final_charge_status = 0
+            and case task.charge_stage
+            when 1 then p.incharger_id = task.charge_one_id
+            when 2 then p.incharger_id = task.charge_two_id
+            end
+            <if test="queryBO.projectId != null">
+                and tf.project_id = #{queryBO.projectId}
+            </if>
+            <if test="queryBO.taskId != null">
+                and tf.task_id = #{queryBO.taskId}
+            </if>
+            <if test="deptIds!=null and deptIds.size()>0">
+                and p.dept_id in
+                <foreach collection="deptIds" open="(" close=")" separator="," item="item">
+                    #{item}
+                </foreach>
+            </if>
+        </where>
+        )
+        tmp1 left join user on tmp1.finalChargeId = user.id
+        where tmp1.finalChargeId = #{queryBO.userId}
+        group by tmp1.task_id
+        union  all
+        select tmp1.*,user.name as finalChargeName
+        from
+        (
+        select tf.task_id,tf.creator_id,task.name,task.charge_stage
+        ,task.charge_one_id,task.charge_one_status,task.executor_id
+        ,task.charge_two_id,task.charge_two_status,project.id,project.project_name,
+        case task.charge_stage
+        when 1 then task.charge_one_id
+        when 2 then task.charge_two_id
+        end as finalChargeId
+        from
+        task_files tf
+        left join task on tf.task_id = task.id
+        left join project on task.project_id = project.id
+        left join user on tf.creator_id = user.id
+        left join department d on user.department_id = d.department_id
+        <where>
+            task.task_status = 0 and task.final_charge_status = 0
+            and case task.charge_stage
+            when 1 then d.manager_id = task.charge_one_id
+            when 2 then d.manager_id = task.charge_two_id
+            end
+            <if test="queryBO.projectId != null">
+                and tf.project_id = #{queryBO.projectId}
+            </if>
+            <if test="queryBO.taskId != null">
+                and tf.task_id = #{queryBO.taskId}
+            </if>
+            <if test="deptIds!=null and deptIds.size()>0">
+                and project.dept_id in
+                <foreach collection="deptIds" open="(" close=")" separator="," item="item">
+                    #{item}
+                </foreach>
+            </if>
+        </where>
+        )
+        tmp1 left join user on tmp1.finalChargeId = user.id
+        where tmp1.finalChargeId = #{queryBO.userId}
+        group by tmp1.task_id
+            )tmpAll
+    </select>
 </mapper>

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

@@ -139,7 +139,7 @@
                                     <el-link v-if="user.timeType.enableNewWeeklyfill == 1" type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;fillInReportCustom()">{{ $t('textLink.fillInAWeek') }}</el-link>
                                     <!-- <el-link type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;fillInReportCustom()">按周填报123</el-link> -->
                                     <el-link type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;weekIndex++,fillWeekDialogVisiCustomTwo=true" v-if="user.timeType.enableNewWeeklyfill==2">按周填报</el-link>
-                                    <el-link type="primary" v-if="user.companyId != 5978 && permissions.reportsFillOut && user.timeType.enableNewWeeklyfill != 1" style="margin-right:10px;" :underline="false" @click="isSubstitude=true; fillInReport(-1,(user.companyId == 5814||user.companyId==5693 || user.companyId==4407)?2:0)">{{$t('textLink.helpToFillIn')}}</el-link>
+                                    <el-link type="primary" v-if="user.companyId != 5978 && permissions.reportsFillOut && user.timeType.enableNewWeeklyfill != 1" style="margin-right:10px;" :underline="false" @click="isSubstitude=true; fillInReport(-1,(user.companyId == 5814||user.companyId==5693 || user.companyId==4407 || user.companyId == 7812)?2:0)">{{$t('textLink.helpToFillIn')}}</el-link>
                                     <!-- 苏州景昱,按周填报的模式进行代填日报 -->
                                     <el-link type="primary" v-if="user.companyId == 5978 && permissions.reportsFillOut && user.timeType.enableNewWeeklyfill != 1" style="margin-right:10px;" :underline="false" @click="isSubstitude=true; fillInReportss();">{{$t('textLink.helpToFillIn')}}</el-link>