diff --git a/doc/四算项目流程图说明文档.docx b/doc/四算项目流程图说明文档.docx
new file mode 100644
index 0000000..2d71867
Binary files /dev/null and b/doc/四算项目流程图说明文档.docx differ
diff --git a/src/main/java/cn/palmte/work/controller/backend/ActProcInsController.java b/src/main/java/cn/palmte/work/controller/backend/ActProcInsController.java
index c40d708..d2c264c 100644
--- a/src/main/java/cn/palmte/work/controller/backend/ActProcInsController.java
+++ b/src/main/java/cn/palmte/work/controller/backend/ActProcInsController.java
@@ -2,19 +2,25 @@ package cn.palmte.work.controller.backend;
 
 
 import cn.palmte.work.bean.ResponseMsg;
+import cn.palmte.work.config.activiti.ActApproveTypeEnum;
 import cn.palmte.work.config.activiti.ActConstant;
 import cn.palmte.work.service.ActProcInsService;
+import cn.palmte.work.service.ActTaskDefService;
 import cn.palmte.work.utils.InterfaceUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import org.activiti.engine.TaskService;
+import org.activiti.engine.task.Task;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
+import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletResponse;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -29,6 +35,12 @@ public class ActProcInsController extends BaseController {
 
     @Autowired
     private ActProcInsService actProcInsService;
+    @Autowired
+    private ActTaskDefService actTaskDefService;
+
+    @Autowired
+    private TaskService taskService;
+
 
     /**
      * 列表
@@ -88,7 +100,7 @@ public class ActProcInsController extends BaseController {
         JSONObject json = JSON.parseObject(body);
         Map<String, Object> variables = new HashMap<>();
         for (Object key : json.keySet()) {
-            variables.put((String)key, json.get(key));
+            variables.put((String) key, json.get(key));
         }
 
         variables.put(ActConstant.START_PROCESS_USERID, InterfaceUtil.getAdminId());
@@ -103,4 +115,37 @@ public class ActProcInsController extends BaseController {
     }
 
 
+    /**
+     * 流程测试使用
+     * http://localhost:8282/fourcal/actProcIns/test?procDefKey=final&params=typeVVV1FFFprojectTypeVVV1FFFcontractAmountVVV10000FFFcooperationTypeVVV1FFFisPrepaidVVVtrueFFFrepaidAmountVVV10000
+     */
+    @ResponseBody
+    @GetMapping(value = "/test")
+    public ResponseMsg test(@RequestParam String procDefKey, @RequestParam String params) {
+        try {
+            HashMap<String, Object> variables = new HashMap<>();
+            for (String s : params.split("FFF")) {
+                String[] split = s.split("VVV");
+                variables.put(split[0], split[1]);
+            }
+            String procInsId = actProcInsService.startProcessInstance(procDefKey, "0", variables);
+            logger.info("==============> startProcessInstance procInsId:{}", procInsId);
+
+            List<Task> taskList = taskService.createTaskQuery().processInstanceId(procInsId).list();
+            int i = 1;
+            while (!CollectionUtils.isEmpty(taskList)) {
+                for (Task task : taskList) {
+                    logger.info("==============> completeTaskByProcInsId procInsId:{}, taskName:{}, i:{}", procInsId, task.getName(), i++);
+                    actTaskDefService.completeTask(task.getId(), procInsId, "sysTest", ActApproveTypeEnum.APPROVAL_PASSED, "");
+                }
+
+                taskList = taskService.createTaskQuery().processInstanceId(procInsId).list();
+            }
+        } catch (Exception e) {
+            logger.error("", e);
+            return ResponseMsg.buildFailedMsg(e.getMessage());
+        }
+        return ResponseMsg.buildSuccessMsg("ok");
+    }
+
 }
diff --git a/src/main/java/cn/palmte/work/controller/backend/AdminController.java b/src/main/java/cn/palmte/work/controller/backend/AdminController.java
index 1aa6517..94e32c0 100644
--- a/src/main/java/cn/palmte/work/controller/backend/AdminController.java
+++ b/src/main/java/cn/palmte/work/controller/backend/AdminController.java
@@ -138,7 +138,8 @@ public class AdminController extends BaseController {
                 request.getSession().setAttribute("message", "");
             }
 
-            message = login(userName, admin.getPassword(), false, false);
+            // message = login(userName, admin.getPassword(), false, false);
+            message = login(userName, newPassword, false, false);
             if (!message.isEmpty()) {
                 attr.addAttribute("errorMessages", message);
 
diff --git a/src/main/java/cn/palmte/work/controller/backend/ProjectController.java b/src/main/java/cn/palmte/work/controller/backend/ProjectController.java
index be0e6ea..963b642 100644
--- a/src/main/java/cn/palmte/work/controller/backend/ProjectController.java
+++ b/src/main/java/cn/palmte/work/controller/backend/ProjectController.java
@@ -267,7 +267,7 @@ public class ProjectController extends BaseController {
         exportExcelUtils.exportPlanDetailExcel(headers5, row5, project, budgetBean, projectBudgetPlanDetails, projectBudgetPlanDetailTotal, "yyyy-MM-dd", 0, "资金计划表", outputStream);
 
         CashFlowBean cashFlowBean = projectBudgetService.getCashFlowBean(project, projectBudgetPlanDetails);
-        exportExcelUtils.exportBudgetExcel(budgetBean, cashFlowBean, 0, "项目预算信息", outputStream, project.getOtherName(), incomeTaxRates, costTaxRates);
+        exportExcelUtils.exportBudgetExcel(budgetBean, null, 0, "项目预算信息", outputStream, project.getOtherName(), incomeTaxRates, costTaxRates);
 
         List<String> timeList = projectSettleIncomeRepository.findAllByProjectIdAndGroupByTime(project.getId());
         for (String time : timeList) {
@@ -1412,8 +1412,8 @@ public class ProjectController extends BaseController {
         }
         List<ProjectBudgetPlanDetail> projectBudgetPlanDetails = projectBudgetService.getProjectBudgetPlanDetails(project);
         BudgetBean budgetBean = projectBudgetService.getBudget(project);
-        CashFlowBean cashFlowBean = projectBudgetService.getCashFlowBean(project, projectBudgetPlanDetails);
-        exportExcelUtils.exportBudgetExcel(budgetBean, cashFlowBean, 0, "项目预算信息", outputStream, project.getOtherName(), incomeTaxRates, costTaxRates);
+        // CashFlowBean cashFlowBean = projectBudgetService.getCashFlowBean(project, projectBudgetPlanDetails);
+        exportExcelUtils.exportBudgetExcel(budgetBean, null, 0, "项目预算信息", outputStream, project.getOtherName(), incomeTaxRates, costTaxRates);
 
         exportExcelUtils.end(outputStream);
     }
diff --git a/src/main/java/cn/palmte/work/service/ActListenerService.java b/src/main/java/cn/palmte/work/service/ActListenerService.java
index 80efeb9..cf63770 100644
--- a/src/main/java/cn/palmte/work/service/ActListenerService.java
+++ b/src/main/java/cn/palmte/work/service/ActListenerService.java
@@ -1,6 +1,7 @@
 package cn.palmte.work.service;
 
 
+import cn.palmte.work.config.activiti.ActApproveTypeEnum;
 import cn.palmte.work.config.activiti.ActTaskIndexEnum;
 import cn.palmte.work.model.ActTaskDef;
 import cn.palmte.work.model.Admin;
@@ -48,6 +49,7 @@ public class ActListenerService {
 
     /**
      * 任务节点创建后监听 动态设置审批人
+     * @see ActModelService#setTaskListener
      *
      * @param delegateTask
      * @throws Exception
@@ -77,6 +79,8 @@ public class ActListenerService {
 
     /**
      * 流程结束监听 更新项目状态为审批通过
+     * @see ActModelService#setExecutionListener
+     *
      *
      * @param delegateExecution
      */
@@ -84,11 +88,15 @@ public class ActListenerService {
         String procInsId = delegateExecution.getProcessInstanceId();
         ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(procInsId).singleResult();
         int projectId = Integer.parseInt(processInstance.getBusinessKey());
-
         String procDefId = processInstance.getProcessDefinitionId();
+        String procDefKey = procDefId.split(":")[0];
+        logger.info("**** lcjsjt 流程结束监听 更新项目状态为审批通过 ****  procInsId:{}, procDefId:{}, procDefKey:{}, projectId:{}", procInsId, procDefId, procDefKey, projectId);
         if (actUtil.isNewProcess(procDefId)) {
-            logger.info("**** lcjsjt 流程结束监听 更新项目状态为审批通过 ****  procInsId:{}, procDefId:{}, projectId:{}", procInsId, procDefId, projectId);
+            logger.info("newProcess passed");
             projectProcessService.updateProcessStatus(projectId, ProcessStatus.audit_passed);
+        }else if (actUtil.isFourcalProcess(procDefId)){
+            logger.info("fourcalProcess passed");
+            projectInstanceService.updateApproveStatus(projectId, procDefKey, ActApproveTypeEnum.APPROVAL_PASSED);
         }
     }
 
diff --git a/src/main/java/cn/palmte/work/service/ActModelService.java b/src/main/java/cn/palmte/work/service/ActModelService.java
index 20c36b2..01e7872 100644
--- a/src/main/java/cn/palmte/work/service/ActModelService.java
+++ b/src/main/java/cn/palmte/work/service/ActModelService.java
@@ -192,6 +192,11 @@ public class ActModelService {
     }
 
 
+    /**
+     * 设置节点创建监听
+     *
+     * @param userTaskElement
+     */
     private void setTaskListener(UserTask userTaskElement) {
         ActivitiListener taskListener = new ActivitiListener();
         taskListener.setEvent(TaskListener.EVENTNAME_CREATE);
@@ -202,6 +207,11 @@ public class ActModelService {
         userTaskElement.setTaskListeners(taskListenerList);
     }
 
+    /**
+     * 设置流程结束时监听
+     *
+     * @param process
+     */
     private void setExecutionListener(Process process) {
         ActivitiListener executionListener = new ActivitiListener();
         executionListener.setEvent(BaseExecutionListener.EVENTNAME_END);
diff --git a/src/main/java/cn/palmte/work/service/ActTaskDefService.java b/src/main/java/cn/palmte/work/service/ActTaskDefService.java
index 1dfc88f..ef5bdd4 100644
--- a/src/main/java/cn/palmte/work/service/ActTaskDefService.java
+++ b/src/main/java/cn/palmte/work/service/ActTaskDefService.java
@@ -7,6 +7,7 @@ import cn.palmte.work.model.*;
 import cn.palmte.work.model.enums.ProcessStatus;
 import cn.palmte.work.pojo.ActHisTask;
 import cn.palmte.work.utils.ActUtil;
+import cn.palmte.work.utils.DateKit;
 import cn.palmte.work.utils.InterfaceUtil;
 import com.alibaba.fastjson.JSONObject;
 import org.activiti.engine.*;
@@ -64,7 +65,7 @@ public class ActTaskDefService {
         completeTask(taskId, procInsId, message, ActApproveTypeEnum.ofType(type), "");
     }
 
-    private void completeTask(String taskId, String procInsId, String message, ActApproveTypeEnum approveEnum, String fileUrl) {
+    public void completeTask(String taskId, String procInsId, String message, ActApproveTypeEnum approveEnum, String fileUrl) {
         String userId = InterfaceUtil.getAdminId() + "";
         Authentication.setAuthenticatedUserId(userId);
         taskService.addComment(taskId, procInsId, message);
@@ -178,10 +179,16 @@ public class ActTaskDefService {
             //审批通过
             taskService.complete(taskId);
 
-            if (actUtil.isFourcalProcess(processInstance.getProcessDefinitionId())) {
+            //6月17前的流程没有设置流程结束监听(结束监听里更新项目状态为审批通过)  后面此逻辑可删除
+            Date date = DateKit.getDate("2024-06-18 00:00:00");
+            Date startTime = processInstance.getStartTime();
+            logger.info("procStartTime:{}", startTime);
+            if (startTime.getTime() < date.getTime()
+                    && actUtil.isFourcalProcess(processInstance.getProcessDefinitionId())) {
                 //四算项目 最后一个任务完成后 更新项目状态为审批通过 其他项目通过监听器更新
                 updateProjectPassed(processInstance, actTaskDef, procDefKey);
             }
+
         } else if (ActApproveTypeEnum.APPROVAL_UN_PASS == approveEnum) {
             //驳回
             String rollbackTaskKey = actTaskDef.getRollbackTaskKey();
@@ -366,7 +373,7 @@ public class ActTaskDefService {
 
     /**
      * 通过类型查找审批人
-     * 
+     *
      * @param types
      * @param procInsId
      * @return
@@ -394,7 +401,7 @@ public class ActTaskDefService {
                     String deptLeaderId = record.getStr("text");
                     userIdList.add(deptLeaderId);
                     logger.info("queryCandidatesByType deptLeader:{}, procInsId:{} ", deptLeaderId, procInsId);
-                }else{
+                } else {
                     logger.error("queryCandidatesByType not find deptLeader procInsId:{} ", procInsId);
                 }
             }
diff --git a/src/main/java/cn/palmte/work/service/ProjectBudgetService.java b/src/main/java/cn/palmte/work/service/ProjectBudgetService.java
index 531e64f..6d49b46 100644
--- a/src/main/java/cn/palmte/work/service/ProjectBudgetService.java
+++ b/src/main/java/cn/palmte/work/service/ProjectBudgetService.java
@@ -688,9 +688,15 @@ public class ProjectBudgetService {
                     engineerCost = engineerCost.add(budgetPlan.getEngineerCost());
                 }
 
-                projectCost = projectCost.add(budgetPlan.getProjectCost());
-                serviceCost = serviceCost.add(budgetPlan.getServiceCost());
-                otherCost = otherCost.add(budgetPlan.getOtherCost());
+                if (budgetPlan.getProjectCost()!=null) {
+                    projectCost = projectCost.add(budgetPlan.getProjectCost());
+                }
+                if (budgetPlan.getServiceCost()!=null) {
+                    serviceCost = serviceCost.add(budgetPlan.getServiceCost());
+                }
+                if (budgetPlan.getOtherCost()!=null) {
+                    otherCost = otherCost.add(budgetPlan.getOtherCost());
+                }
                 totalCost = totalCost.add(budgetPlan.getTotalCost());
                 saleIncome = saleIncome.add(budgetPlan.getSaleIncome());
                 earnestMoneyIncome = earnestMoneyIncome.add(budgetPlan.getEarnestMoneyIncome());
diff --git a/src/main/java/cn/palmte/work/service/ProjectInstanceService.java b/src/main/java/cn/palmte/work/service/ProjectInstanceService.java
index c0abe4f..084c30d 100644
--- a/src/main/java/cn/palmte/work/service/ProjectInstanceService.java
+++ b/src/main/java/cn/palmte/work/service/ProjectInstanceService.java
@@ -152,6 +152,10 @@ public class ProjectInstanceService {
      */
     public void updateApproveStatus(int projectId, String processKey, ActApproveTypeEnum approveTypeEnum){
         Project project = projectRepository.findOne(projectId);
+        if(project == null){
+            logger.error("updateApproveStatusError projectIsNull :{}", project);
+            return;
+        }
         if(ActProcessKeyEnum.ESTIMATE.getKey().equals(processKey)){
             project.setApproveStatusEstimate(approveTypeEnum.getType());
         }else if(ActProcessKeyEnum.BUDGET.getKey().equals(processKey)){
diff --git a/src/main/resources/templates/admin/act_proc_def_list.ftl b/src/main/resources/templates/admin/act_proc_def_list.ftl
index 88a407f..16a1df9 100644
--- a/src/main/resources/templates/admin/act_proc_def_list.ftl
+++ b/src/main/resources/templates/admin/act_proc_def_list.ftl
@@ -81,6 +81,13 @@
                                         流程图片
                                     </button>
 
+                                    <button type="button"
+                                            class="am-btn am-btn-default am-btn-xs am-text-secondary"
+                                            onclick="xmlView('${list.deploymentId!}')">
+                                        <span class="am-icon-pencil-square-o"></span>
+                                        流程xml
+                                    </button>
+
                                 </td>
                                 <td>
                                     <div class="switch-button">