Bladeren bron

潘所,批量审核代办(报销,仅同意)

徐滕 6 dagen geleden
bovenliggende
commit
f2a3dedf43

+ 18 - 0
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/entity/WorkKnowledgeBasePoint.java

@@ -26,6 +26,8 @@ public class WorkKnowledgeBasePoint extends DataEntity<WorkKnowledgeBasePoint> {
 	private String shareName;	// 文档名称
 	private Integer changeType;	// 变更类型(1:创建;2:审核)
 	private Double point;		// 积分数量
+	private Double monthlyPoint;		// 当月积分数量
+	private String sortRule;			// 排序规则(total-总积分,monthly-当月积分)
 	private String beginDate;	// 开始日期
 	private String endDate;		// 结束日期
 	private String submitterId;	// 经办人ID(查询用)
@@ -390,4 +392,20 @@ public class WorkKnowledgeBasePoint extends DataEntity<WorkKnowledgeBasePoint> {
 	public void setIsManualScore(String isManualScore) {
 		this.isManualScore = isManualScore;
 	}
+
+	public Double getMonthlyPoint() {
+		return monthlyPoint;
+	}
+
+	public void setMonthlyPoint(Double monthlyPoint) {
+		this.monthlyPoint = monthlyPoint;
+	}
+
+	public String getSortRule() {
+		return sortRule;
+	}
+
+	public void setSortRule(String sortRule) {
+		this.sortRule = sortRule;
+	}
 }

+ 26 - 0
src/main/java/com/jeeplus/modules/workinvoice/web/WorkInvoiceAllTwoController.java

@@ -42,6 +42,7 @@ import com.jeeplus.modules.workclientinfo.service.WorkClientInfoService;
 import com.jeeplus.modules.workcontractinfo.entity.WorkContractInfo;
 import com.jeeplus.modules.workcontractinfo.service.WorkContractInfoService;
 import com.jeeplus.modules.workinvoice.entity.WorkInvoice;
+import com.jeeplus.modules.workinvoice.entity.WorkInvoiceCloud;
 import com.jeeplus.modules.workinvoice.entity.WorkInvoiceExport;
 import com.jeeplus.modules.workinvoice.entity.WorkInvoiceProjectRelation;
 import com.jeeplus.modules.workinvoice.service.WorkInvoiceAllService;
@@ -752,6 +753,31 @@ public class WorkInvoiceAllTwoController extends BaseController {
 				}
 			}
 			for (WorkInvoice invoice: workInvoiceList) {
+				if (StringUtils.isNotBlank(invoice.getIsSzCloud()) && invoice.getIsSzCloud().equals("sz")){
+					List<WorkInvoiceCloud> workInvoiceCloud = workInvoiceService.getByInvoiceId(invoice.getId());
+					if (workInvoiceCloud != null){
+						ArrayList<String> names = new ArrayList<>();
+						ArrayList<String> nums = new ArrayList<>();
+						for (WorkInvoiceCloud cloud : workInvoiceCloud) {
+							names.add(cloud.getProjectName());
+							if (StringUtils.isNotBlank(cloud.getReportNo())){
+								nums.add(cloud.getReportNo());
+							}
+
+						}
+						String projectNameStr = String.join(",", names);
+						invoice.setProjectName(projectNameStr);
+						String reprotNos = String.join(",", nums);
+						invoice.setReportNumber(reprotNos);
+						WorkClientInfo workClientInfo = new WorkClientInfo();
+						workClientInfo.setName(Objects.nonNull(invoice.getClient()) ? invoice.getClient().getId() : null);
+						invoice.setClient(workClientInfo);
+
+						if (Objects.nonNull(invoice.getArea())) {
+							invoice.setAccountCheckingArea(invoice.getArea().getId());
+						}
+					}
+				}
 				for (MainDictDetail dictDetail: billingContentList) {
 					if(invoice.getBillingContent().equals(dictDetail.getValue())){
 						invoice.setBillingContent(dictDetail.getLabel());

+ 524 - 0
src/main/java/com/jeeplus/modules/workprojectnotify/web/WorkProjectNotifyBatchController.java

@@ -0,0 +1,524 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.workprojectnotify.web;
+
+import com.jeeplus.common.web.BaseController;
+import com.jeeplus.modules.act.entity.Act;
+import com.jeeplus.modules.act.service.ActTaskService;
+import com.jeeplus.modules.sys.entity.User;
+import com.jeeplus.modules.sys.utils.UserUtils;
+import com.jeeplus.modules.workactivity.dao.WorkActivityProcessDao;
+import com.jeeplus.modules.workactivity.entity.WorkActivityProcess;
+import com.jeeplus.modules.workprojectnotify.entity.WorkProjectNotify;
+import com.jeeplus.modules.workprojectnotify.service.WorkProjectNotifyService;
+import com.jeeplus.modules.workreimbursement.entity.WorkReimbursement;
+import com.jeeplus.modules.workreimbursement.service.WorkReimbursementNewService;
+import com.jeeplus.modules.workreimbursement.service.WorkReimbursementService;
+import org.activiti.engine.runtime.ProcessInstance;
+import org.activiti.engine.task.Task;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.util.*;
+
+/**
+ * 待办管理-批量报销审批Controller
+ * 用于批量处理和一键处理报销待办数据
+ *
+ * 核心设计:从数据库查询每条报销数据的实际processKey,根据processKey分发到对应的处理方法。
+ * 不同type对应不同的BPMN流程定义(processKey),taskDefKey和审批人判定逻辑各不相同,
+ * 不能通过条件猜测processKey,必须从WorkActivityProcess表中读取实际值。
+ *
+ * processKey与处理方法映射关系:
+ * - newReimbursement          → type=13旧报销     → WorkReimbursementService.auditSave
+ * - newReimbursementTwo       → type=102新报销     → WorkReimbursementNewService.auditSave
+ * - newReimbursementThree     → type=108三期报销   → WorkReimbursementNewService.auditSaveThree
+ * - reimbursementThree        → type=112三期报销   → WorkReimbursementNewService.auditSaveReimbursementThree
+ * - electronicInvoiceReimbursement       → type=106电子发票 → WorkReimbursementNewService.electronicInvoiceReimbursementAuditSave
+ * - electronicInvoiceReimbursement(109)  → type=109电子发票三期 → WorkReimbursementNewService.electronicInvoiceReimbursementThreeAuditSave
+ * - specificInvoiceReimbursement         → type=107四部报销 → WorkReimbursementNewService.auditSpecificSave
+ *
+ * @author auto
+ * @version 2026-07-15
+ */
+@Controller
+@RequestMapping(value = "${adminPath}/workprojectnotify/workProjectNotifyBatch")
+public class WorkProjectNotifyBatchController extends BaseController {
+
+	private Logger logger = LoggerFactory.getLogger(WorkProjectNotifyBatchController.class);
+
+	/** 报销相关类型集合 */
+	private static final Set<String> REIMBURSEMENT_TYPES = new HashSet<>(
+			Arrays.asList("13", "102", "106", "107", "108", "109", "112")
+	);
+
+	@Autowired
+	private WorkProjectNotifyService workProjectNotifyService;
+
+	@Autowired
+	private WorkReimbursementService workReimbursementService;
+
+	@Autowired
+	private WorkReimbursementNewService workReimbursementNewService;
+
+	@Autowired
+	private ActTaskService actTaskService;
+
+	@Autowired
+	private WorkActivityProcessDao workActivityProcessDao;
+
+	/**
+	 * 批量审批报销待办(处理勾选的数据)
+	 */
+	@RequestMapping(value = "batchApprove")
+	@ResponseBody
+	@RequiresPermissions("workprojectnotify:batch:approve")
+	public Map<String, Object> batchApprove(@RequestBody List<String> notifyIds) {
+		int successCount = 0;
+		int failCount = 0;
+
+		for (String notifyId : notifyIds) {
+			try {
+				boolean result = processSingleNotify(notifyId);
+				if (result) {
+					successCount++;
+				} else {
+					failCount++;
+				}
+			} catch (Exception e) {
+				failCount++;
+				logger.error("批量审批失败, notifyId: {}, error: {}", notifyId, e.getMessage());
+			}
+		}
+
+		Map<String, Object> resultMap = new HashMap<>();
+		resultMap.put("success", true);
+		resultMap.put("totalCount", notifyIds.size());
+		resultMap.put("successCount", successCount);
+		resultMap.put("failCount", failCount);
+		resultMap.put("msg", "处理完成!成功" + successCount + "条,失败" + failCount + "条");
+		return resultMap;
+	}
+
+	/**
+	 * 一键审批所有报销待办(处理全量数据)
+	 */
+	@RequestMapping(value = "approveAll")
+	@ResponseBody
+	@RequiresPermissions("workprojectnotify:batch:approveAll")
+	public Map<String, Object> approveAll() {
+		List<String> reimbursementNotifyIds = findAllReimbursementNotifyIds();
+		if (reimbursementNotifyIds.isEmpty()) {
+			Map<String, Object> resultMap = new HashMap<>();
+			resultMap.put("success", true);
+			resultMap.put("totalCount", 0);
+			resultMap.put("successCount", 0);
+			resultMap.put("failCount", 0);
+			resultMap.put("msg", "没有需要处理的报销待办");
+			return resultMap;
+		}
+		return batchApprove(reimbursementNotifyIds);
+	}
+
+	/**
+	 * 查询所有待审批的报销通知ID
+	 */
+	private List<String> findAllReimbursementNotifyIds() {
+		User user = UserUtils.getUser();
+		WorkProjectNotify query = new WorkProjectNotify();
+		query.setUser(user);
+		query.setCompanyId(UserUtils.getSelectCompany().getId());
+		query.setRemarks("待审批");
+
+		List<WorkProjectNotify> allList = workProjectNotifyService.findList(query);
+		List<String> result = new ArrayList<>();
+		for (WorkProjectNotify notify : allList) {
+			if (REIMBURSEMENT_TYPES.contains(notify.getType())) {
+				if (notify.getTitle() != null && notify.getTitle().contains("报销")) {
+					result.add(notify.getId());
+				}
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * 处理单条报销待办通知
+	 * 核心逻辑:从WorkActivityProcess表查出实际processKey,根据processKey分发处理
+	 */
+	private boolean processSingleNotify(String notifyId) {
+		WorkProjectNotify notify = workProjectNotifyService.get(notifyId);
+		if (notify == null) {
+			logger.warn("待办记录不存在, notifyId: {}", notifyId);
+			return false;
+		}
+		if (!REIMBURSEMENT_TYPES.contains(notify.getType())) {
+			logger.warn("非报销类型, notifyId: {}, type: {}", notifyId, notify.getType());
+			return false;
+		}
+		if (notify.getTitle() == null || !notify.getTitle().contains("报销")) {
+			logger.warn("标题不包含报销, notifyId: {}, title: {}", notifyId, notify.getTitle());
+			return false;
+		}
+
+		WorkReimbursement workReimbursement = workReimbursementService.get(notify.getNotifyId());
+		if (workReimbursement == null) {
+			logger.warn("报销实体不存在, notifyId: {}, notifyRecordId: {}", notifyId, notify.getNotifyId());
+			return false;
+		}
+
+		Act act = getByAct(workReimbursement.getProcessInstanceId());
+		if (act == null || act.getTaskId() == null) {
+			logger.warn("无法获取流程任务信息, notifyId: {}, processInstanceId: {}", notifyId, workReimbursement.getProcessInstanceId());
+			return false;
+		}
+		workReimbursement.setAct(act);
+		act.setFlag("yes");
+		act.setComment("[批量审批同意]");
+
+		// 从数据库查询实际的processKey
+		String processKey = getProcessKeyFromDb(workReimbursement.getProcessInstanceId());
+		if (StringUtils.isBlank(processKey)) {
+			logger.warn("无法获取processKey, notifyId: {}, processInstanceId: {}", notifyId, workReimbursement.getProcessInstanceId());
+			return false;
+		}
+
+		String taskDefKey = act.getTaskDefKey();
+		String processInstanceId = workReimbursement.getProcessInstanceId();
+
+		// 根据processKey分发到对应的处理方法
+		switch (processKey) {
+			case "newReimbursement":
+				return processByProcessKey_newReimbursement(workReimbursement, taskDefKey, processInstanceId, notifyId);
+			case "newReimbursementTwo":
+				return processByProcessKey_newReimbursementTwo(workReimbursement, taskDefKey, processInstanceId, notifyId);
+			case "newReimbursementThree":
+				return processByProcessKey_newReimbursementThree(workReimbursement, taskDefKey, processInstanceId, notifyId);
+			case "reimbursementThree":
+				return processByProcessKey_reimbursementThree(workReimbursement, taskDefKey, processInstanceId, notifyId);
+			case "electronicInvoiceReimbursement":
+				return processByProcessKey_electronicInvoiceReimbursement(workReimbursement, taskDefKey, processInstanceId, notifyId);
+			case "specificInvoiceReimbursement":
+				return processByProcessKey_specificInvoiceReimbursement(workReimbursement, taskDefKey, processInstanceId, notifyId);
+			default:
+				logger.warn("未知的processKey: {}, notifyId: {}", processKey, notifyId);
+				return false;
+		}
+	}
+
+	/**
+	 * 从WorkActivityProcess表查询实际的processKey
+	 */
+	private String getProcessKeyFromDb(String processInstanceId) {
+		List<WorkActivityProcess> list = workActivityProcessDao.getByProcessInstanceId(processInstanceId);
+		if (list != null && !list.isEmpty()) {
+			for (WorkActivityProcess p : list) {
+				if (StringUtils.isNotBlank(p.getProcessKey())) {
+					return p.getProcessKey();
+				}
+			}
+		}
+		return null;
+	}
+
+	// ====================== processKey=newReimbursement (type=13 旧报销) ======================
+
+	/**
+	 * processKey=newReimbursement,对应type=13旧报销
+	 * save方法: WorkReimbursementService.save
+	 * audit方法: WorkReimbursementService.auditSave
+	 * taskDefKey: bmzr, cw, modifyApply
+	 */
+	private boolean processByProcessKey_newReimbursement(WorkReimbursement wr, String taskDefKey, String procInsId, String notifyId) {
+		List<User> users = null;
+		if ("bmzr".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 2);
+			if (users == null)
+				users = UserUtils.getByRoleActivityEnname("cwzg", 3, wr.getOfficeId(), "8", wr.getCreateBy());
+		} else if ("cw".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 3);
+			if (users == null)
+				users = UserUtils.getByProssType(procInsId, 1);
+		} else if ("modifyApply".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 1);
+		}
+		if (users == null || users.isEmpty()) {
+			logger.warn("newReimbursement 审批人为空, notifyId: {}, taskDefKey: {}", notifyId, taskDefKey);
+			return false;
+		}
+		workReimbursementService.auditSave(wr, users);
+		return true;
+	}
+
+	// ====================== processKey=newReimbursementTwo (type=102) ======================
+
+	/**
+	 * processKey=newReimbursementTwo,对应type=102
+	 * save方法: WorkReimbursementNewService.save
+	 * audit方法: WorkReimbursementNewService.auditSave
+	 * taskDefKey: bmzr, cw, gsld, modifyApply
+	 */
+	private boolean processByProcessKey_newReimbursementTwo(WorkReimbursement wr, String taskDefKey, String procInsId, String notifyId) {
+		List<User> users = null;
+		if ("bmzr".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 2);
+			if (users == null)
+				users = UserUtils.getByRoleActivityEnname("cwzg", 3, wr.getOfficeId(), "8", wr.getCreateBy());
+		} else if ("cw".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 3);
+			if (users == null)
+				users = UserUtils.getByProssType(procInsId, 1);
+		} else if ("gsld".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 3);
+			if (users == null)
+				users = UserUtils.getByProssType(procInsId, 1);
+		} else if ("modifyApply".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 1);
+		}
+		if (users == null || users.isEmpty()) {
+			logger.warn("newReimbursementTwo 审批人为空, notifyId: {}, taskDefKey: {}", notifyId, taskDefKey);
+			return false;
+		}
+		workReimbursementNewService.auditSave(wr, users);
+		return true;
+	}
+
+	// ====================== processKey=newReimbursementThree (type=108/109) ======================
+
+	/**
+	 * processKey=newReimbursementThree,对应type=108或type=109
+	 * save方法: saveReimburseThree(108) 或 electronicInvoiceReimbursementThreeSave(109)
+	 * audit方法: auditSaveThree(108) 或 electronicInvoiceReimbursementThreeAuditSave(109)
+	 * taskDefKey: bmzr, cw, fpglys, dzfpbxshybxsd, gsld, modifyApply
+	 */
+	private boolean processByProcessKey_newReimbursementThree(WorkReimbursement wr, String taskDefKey, String procInsId, String notifyId) {
+		Date nowDate = new Date();
+		LocalDate reimburseLocalDate = LocalDate.of(2024, 2, 21);
+		Date reimburseAuditDate = Date.from(reimburseLocalDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
+		int reimburseResult = wr.getCreateDate().compareTo(reimburseAuditDate);
+
+		List<User> users = null;
+		if ("bmzr".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 3);
+			if (users == null)
+				users = UserUtils.getByProssType(procInsId, 1);
+			if ("0".equals(wr.getReimbursementType())) {
+				if (reimburseResult > 0) {
+					users = UserUtils.getByRoleActivityEnname("dzfpbxshybxsd", 3, wr.getOfficeId(), "8", wr.getCreateBy());
+				} else {
+					users = UserUtils.getByRoleActivityEnname("zjbfzribvf", 3, wr.getOfficeId(), "8", wr.getCreateBy());
+				}
+			} else if ("1".equals(wr.getReimbursementType())) {
+				users = UserUtils.getByRoleActivityEnname("dzfpbxshybxsd", 3, wr.getOfficeId(), "8", wr.getCreateBy());
+			}
+		} else if ("cw".equals(taskDefKey)) {
+			if ("d8cf33fafd2d4f04a603e89f7e28e54c".equals(wr.getOfficeId())) {
+				users = UserUtils.getByRoleActivityEnname("bmzr", 2, "7f776d072d7b4c839cef4e63ce6dbfa5", "8", wr.getCreateBy());
+			} else if ("5adafaaa43ab4a11801f9ad264374a06".equals(wr.getOfficeId())) {
+				users = UserUtils.getByRoleActivityEnname("bmzr", 2, "6c9ca86e941b4a738c1ab9b006976264", "8", wr.getCreateBy());
+			} else {
+				users = UserUtils.getByRoleActivityEnname("bmzr", 2, wr.getOfficeId(), "8", wr.getCreateBy());
+			}
+		} else if ("gsld".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 3);
+			if (users == null)
+				users = UserUtils.getByProssType(procInsId, 1);
+		} else if ("fpglys".equals(taskDefKey) || "dzfpbxshybxsd".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 3);
+			if (reimburseResult > 0) {
+				users = UserUtils.getByRoleActivityEnname("zjbfzribvf", 3, wr.getOfficeId(), "8", wr.getCreateBy());
+			}
+			if (users == null)
+				users = UserUtils.getByProssType(procInsId, 1);
+		} else if ("modifyApply".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 1);
+		}
+		if (users == null || users.isEmpty()) {
+			logger.warn("newReimbursementThree 审批人为空, notifyId: {}, taskDefKey: {}", notifyId, taskDefKey);
+			return false;
+		}
+
+		// 根据reimbursementType区分调用哪个auditSave方法
+		// type=109 电子发票三期 → electronicInvoiceReimbursementThreeAuditSave
+		// type=108 普通三期 → auditSaveThree
+		if ("1".equals(wr.getReimbursementType())) {
+			workReimbursementNewService.electronicInvoiceReimbursementThreeAuditSave(wr, users);
+		} else {
+			workReimbursementNewService.auditSaveThree(wr, users);
+		}
+		return true;
+	}
+
+	// ====================== processKey=reimbursementThree (type=112) ======================
+
+	/**
+	 * processKey=reimbursementThree,对应type=112
+	 * save方法: WorkReimbursementNewService.saveReimbursementThree
+	 * audit方法: WorkReimbursementNewService.auditSaveReimbursementThree
+	 * taskDefKey: cw, bmzr, fpglys, dzfpbxshybxsd, gsld, modifyApply
+	 */
+	private boolean processByProcessKey_reimbursementThree(WorkReimbursement wr, String taskDefKey, String procInsId, String notifyId) {
+		Date nowDate = new Date();
+		LocalDate reimburseLocalDate = LocalDate.of(2024, 2, 21);
+		Date reimburseAuditDate = Date.from(reimburseLocalDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
+		int reimburseResult = wr.getCreateDate().compareTo(reimburseAuditDate);
+
+		List<User> users = null;
+		if ("bmzr".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 3);
+			if (users == null)
+				users = UserUtils.getByProssType(procInsId, 1);
+			if ("0".equals(wr.getReimbursementType())) {
+				if (reimburseResult > 0) {
+					users = UserUtils.getByRoleActivityEnname("dzfpbxshybxsd", 3, wr.getOfficeId(), "8", wr.getCreateBy());
+				} else {
+					users = UserUtils.getByRoleActivityEnname("zjbfzribvf", 3, wr.getOfficeId(), "8", wr.getCreateBy());
+				}
+			} else if ("1".equals(wr.getReimbursementType())) {
+				users = UserUtils.getByRoleActivityEnname("dzfpbxshybxsd", 3, wr.getOfficeId(), "8", wr.getCreateBy());
+			}
+		} else if ("cw".equals(taskDefKey)) {
+			if ("d8cf33fafd2d4f04a603e89f7e28e54c".equals(wr.getOfficeId())) {
+				users = UserUtils.getByRoleActivityEnname("bmzr", 2, "7f776d072d7b4c839cef4e63ce6dbfa5", "8", wr.getCreateBy());
+			} else if ("5adafaaa43ab4a11801f9ad264374a06".equals(wr.getOfficeId())) {
+				users = UserUtils.getByRoleActivityEnname("bmzr", 2, "6c9ca86e941b4a738c1ab9b006976264", "8", wr.getCreateBy());
+			} else {
+				users = UserUtils.getByRoleActivityEnname("bmzr", 2, wr.getOfficeId(), "8", wr.getCreateBy());
+			}
+		} else if ("gsld".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 3);
+			if (users == null)
+				users = UserUtils.getByProssType(procInsId, 1);
+		} else if ("fpglys".equals(taskDefKey) || "dzfpbxshybxsd".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 3);
+			if (reimburseResult > 0) {
+				users = UserUtils.getByRoleActivityEnname("zjbfzribvf", 3, wr.getOfficeId(), "8", wr.getCreateBy());
+			}
+			if (users == null)
+				users = UserUtils.getByProssType(procInsId, 1);
+		} else if ("modifyApply".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 1);
+		}
+		if (users == null || users.isEmpty()) {
+			logger.warn("reimbursementThree 审批人为空, notifyId: {}, taskDefKey: {}", notifyId, taskDefKey);
+			return false;
+		}
+		workReimbursementNewService.auditSaveReimbursementThree(wr, users);
+		return true;
+	}
+
+	// ====================== processKey=electronicInvoiceReimbursement (type=106) ======================
+
+	/**
+	 * processKey=electronicInvoiceReimbursement,对应type=106电子发票报销
+	 * save方法: WorkReimbursementNewService.electronicInvoiceReimbursementSave
+	 * audit方法: WorkReimbursementNewService.electronicInvoiceReimbursementAuditSave
+	 * taskDefKey: bmzr, cw, fpglys, modifyApply
+	 */
+	private boolean processByProcessKey_electronicInvoiceReimbursement(WorkReimbursement wr, String taskDefKey, String procInsId, String notifyId) {
+		List<User> users = null;
+		if ("bmzr".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 2);
+			if (users == null)
+				users = UserUtils.getByRoleActivityEnname("cwzg", 3, wr.getOfficeId(), "8", wr.getCreateBy());
+		} else if ("cw".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 3);
+			if (users == null)
+				users = UserUtils.getByProssType(procInsId, 1);
+			users = UserUtils.getByRoleActivityEnname("cwygevod", 3, wr.getOfficeId(), "8", wr.getCreateBy());
+		} else if ("fpglys".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 3);
+			if (users == null)
+				users = UserUtils.getByProssType(procInsId, 1);
+		} else if ("modifyApply".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 1);
+		}
+		if (users == null || users.isEmpty()) {
+			logger.warn("electronicInvoiceReimbursement 审批人为空, notifyId: {}, taskDefKey: {}", notifyId, taskDefKey);
+			return false;
+		}
+		workReimbursementNewService.electronicInvoiceReimbursementAuditSave(wr, users);
+		return true;
+	}
+
+	// ====================== processKey=specificInvoiceReimbursement (type=107) ======================
+
+	/**
+	 * processKey=specificInvoiceReimbursement,对应type=107四部报销
+	 * save方法: WorkReimbursementNewService.specificInvoiceReimbursementSave
+	 * audit方法: WorkReimbursementNewService.auditSpecificSave
+	 * taskDefKey: bmzr, fpglys, modifyApply
+	 */
+	private boolean processByProcessKey_specificInvoiceReimbursement(WorkReimbursement wr, String taskDefKey, String procInsId, String notifyId) {
+		List<User> users = null;
+		if ("bmzr".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 2);
+			if (users == null)
+				users = UserUtils.getByRoleActivityEnname("cwzg", 3, wr.getOfficeId(), "8", wr.getCreateBy());
+		} else if ("cw".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 3);
+			if (users == null)
+				users = UserUtils.getByProssType(procInsId, 1);
+			users = UserUtils.getByRoleActivityEnname("cwygevod", 3, wr.getOfficeId(), "8", wr.getCreateBy());
+		} else if ("fpglys".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 3);
+			if (users == null)
+				users = UserUtils.getByProssType(procInsId, 1);
+		} else if ("modifyApply".equals(taskDefKey)) {
+			users = UserUtils.getByProssType(procInsId, 1);
+		}
+		if (users == null || users.isEmpty()) {
+			logger.warn("specificInvoiceReimbursement 审批人为空, notifyId: {}, taskDefKey: {}", notifyId, taskDefKey);
+			return false;
+		}
+		workReimbursementNewService.auditSpecificSave(wr, users);
+		return true;
+	}
+
+	// ====================== 公共方法 ======================
+
+	/**
+	 * 获取当前流程任务信息
+	 * 复制自 WorkProjectNotifyController.getByAct
+	 */
+	private Act getByAct(String processInstanceId) {
+		Act act = new Act();
+		ProcessInstance processInstance = actTaskService.getProcIns(processInstanceId);
+		if (processInstance != null) {
+			List<Task> taskList = actTaskService.getCurrentTaskList(processInstance);
+			if (taskList != null && taskList.size() > 1) {
+				for (Task taskInfok : taskList) {
+					if (UserUtils.getUser().getId().equals(taskInfok.getAssignee())) {
+						act.setTaskId(taskInfok.getId());
+						act.setTaskName(taskInfok.getName());
+						act.setTaskDefKey(taskInfok.getTaskDefinitionKey());
+						act.setProcDefId(taskInfok.getProcessDefinitionId());
+						act.setProcInsId(taskInfok.getProcessInstanceId());
+						act.setTask(taskInfok);
+					}
+				}
+			} else if (taskList != null && !taskList.isEmpty()) {
+				Task task = actTaskService.getCurrentTaskInfo(processInstance);
+				act.setTaskId(task.getId());
+				act.setTaskName(task.getName());
+				act.setTaskDefKey(task.getTaskDefinitionKey());
+				act.setProcDefId(task.getProcessDefinitionId());
+				act.setProcInsId(task.getProcessInstanceId());
+				act.setTask(task);
+			} else {
+				return null;
+			}
+		}
+		return act;
+	}
+}

+ 29 - 0
src/main/java/com/jeeplus/modules/workreimbursement/entity/WorkReimbursement.java

@@ -177,6 +177,9 @@ public class WorkReimbursement extends ActEntity<WorkReimbursement> {
 	private String home;
 	private Date startDate;
 	private Date endDate;
+	private Date reimbursementStartDate;	//报销开始时间(筛选条件)
+	private Date reimbursementEndDate;		//报销结束时间(筛选条件)
+	private Date reimbursementDate;		//报销日期(第一个审核节点通过时间)
 	private Task task;
 	private Map<String, Object> variables;
 	// 运行中的流程实例
@@ -787,4 +790,30 @@ public class WorkReimbursement extends ActEntity<WorkReimbursement> {
 	public void setSubmitterOfficeIdList(List<String> submitterOfficeIdList) {
 		this.submitterOfficeIdList = submitterOfficeIdList;
 	}
+
+	public Date getReimbursementStartDate() {
+		return reimbursementStartDate;
+	}
+
+	public void setReimbursementStartDate(Date reimbursementStartDate) {
+		this.reimbursementStartDate = reimbursementStartDate;
+	}
+
+	public Date getReimbursementEndDate() {
+		return reimbursementEndDate;
+	}
+
+	public void setReimbursementEndDate(Date reimbursementEndDate) {
+		this.reimbursementEndDate = reimbursementEndDate;
+	}
+
+	@JsonFormat(pattern = "yyyy-MM-dd")
+	@ExcelField(title="报销日期", align=2, sort=14)
+	public Date getReimbursementDate() {
+		return reimbursementDate;
+	}
+
+	public void setReimbursementDate(Date reimbursementDate) {
+		this.reimbursementDate = reimbursementDate;
+	}
 }

+ 5 - 4
src/main/resources/mappings/modules/WorkKnowledgeBase/WorkKnowledgeBasePointDetailDao.xml

@@ -124,7 +124,8 @@
             u.mobile    AS "mobile",
             u.phone     AS "phone",
             o.name      AS "officeName",
-            COALESCE(SUM(d.point), 0) AS "totalPoint"
+            COALESCE(SUM(d.point), 0) AS "totalPoint",
+            COALESCE(SUM(CASE WHEN DATE_FORMAT(d.create_date, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m') THEN d.point ELSE 0 END), 0) AS "monthlyPoint"
         FROM sys_user u
         LEFT JOIN work_knowledge_base_point_detail d ON d.user_id = u.id AND d.del_flag = '0'
         LEFT JOIN work_knowledge_point_category cat ON cat.id = d.category_id AND cat.del_flag = '0'
@@ -171,11 +172,11 @@
         </where>
         GROUP BY u.id, u.name, u.mobile, u.phone, o.name
         <choose>
-            <when test="page !=null and page.orderBy != null and page.orderBy != ''">
-                ORDER BY ${page.orderBy}
+            <when test="sortRule != null and sortRule == 'monthly'">
+                ORDER BY monthlyPoint DESC
             </when>
             <otherwise>
-                ORDER BY MAX(d.create_date) DESC
+                ORDER BY totalPoint DESC
             </otherwise>
         </choose>
     </select>

+ 6 - 6
src/main/resources/mappings/modules/workprojectnotify/WorkProjectNotifyDao.xml

@@ -807,13 +807,13 @@
 			and a.create_by is not null
 
 			<!-- 原有条件保留,用OR连接新增条件 -->
-			and (
+			<!--and (
 			a.process_instance_id in(
 			select process_instance_id from work_activity_process
 			where process_instance_id in(select process_id from work_activity_process_user where user_id = #{user.id} and type=1)
 			and del_flag = 0 and (remarks !='[强制撤销]' or remarks is null) and is_approval != 0
 			)
-			<!-- 新增条件:处理无process_instance_id的情况 -->
+			&lt;!&ndash; 新增条件:处理无process_instance_id的情况 &ndash;&gt;
 			or (
 			a.process_instance_id is null
 			and a.status = 1
@@ -823,7 +823,7 @@
 			<if test="dbName == 'mssql'">'%修改档案信息%'</if>
 			<if test="dbName == 'mysql'">concat('%','修改档案信息','%')</if>
 			)
-			)
+			)-->
 			and a.remarks != '待通知'
 			and a.notify_user = #{user.id}
 		</where>
@@ -900,13 +900,13 @@
 			and a.create_by is not null
 
 			<!-- 原有条件保留,用OR连接新增条件 -->
-			and (
+			<!--and (
 			a.process_instance_id in(
 			select process_instance_id from work_activity_process
 			where process_instance_id in(select process_id from work_activity_process_user where user_id = #{user.id} and type=1)
 			and del_flag = 0 and (remarks !='[强制撤销]' or remarks is null) and is_approval != 0
 			)
-			<!-- 新增条件:处理无process_instance_id的情况 -->
+			&lt;!&ndash; 新增条件:处理无process_instance_id的情况 &ndash;&gt;
 			or (
 			a.process_instance_id is null
 			and a.status = 1
@@ -916,7 +916,7 @@
 			<if test="dbName == 'mssql'">'%修改档案信息%'</if>
 			<if test="dbName == 'mysql'">concat('%','修改档案信息','%')</if>
 			)
-			)
+			)-->
 			and remarks != '待通知'
 			and a.notify_user = #{user.id}
 		</where>

+ 73 - 0
src/main/resources/mappings/modules/workreimbursement/WorkReimbursementDao.xml

@@ -77,6 +77,17 @@
 		,wrr.create_by as "replenishUserId"
 		,wrr.status as "replenishStatus"
 		,wrr.audit_pass_date as "replenishDate"
+		,CASE WHEN a.status IN ('2', '5') THEN 
+			(SELECT MIN(wap.create_date) 
+			 FROM work_activity_process wap 
+			 WHERE wap.process_instance_id = a.process_instance_id 
+			 AND wap.is_approval = '1' 
+			 AND wap.count = 1
+			 AND wap.create_date > COALESCE(
+				 (SELECT MAX(wap2.create_date) FROM work_activity_process wap2 WHERE wap2.process_instance_id = a.process_instance_id AND wap2.is_approval = '2'),
+				 '1970-01-01'
+			 ))
+		ELSE NULL END as "reimbursementDate"
 		FROM work_reimbursement a
 		left join work_account wa on wa.work_reimbursement_id =a.id
 		left join work_reimbursement_type_info wrt on wrt.id =wa.type
@@ -173,6 +184,37 @@
 				AND rvt.invoice_number like concat('%',#{invoiceNumber},'%')
 				)
 			</if>
+			<!-- 报销时间筛选:取最后一个驳回后的第一个审核节点通过时间 -->
+			<if test="reimbursementStartDate != null and reimbursementStartDate != ''">
+				AND a.status IN ('2', '5')
+				AND EXISTS (
+					SELECT 1 FROM work_activity_process wap
+					WHERE wap.process_instance_id = a.process_instance_id
+					AND wap.is_approval = '1'
+					AND wap.count = 1
+					AND wap.create_date > COALESCE(
+						(SELECT MAX(wap2.create_date) FROM work_activity_process wap2 WHERE wap2.process_instance_id = a.process_instance_id AND wap2.is_approval = '2'),
+						'1970-01-01'
+					)
+					GROUP BY wap.process_instance_id
+					HAVING MIN(wap.create_date) &gt;= #{reimbursementStartDate}
+				)
+			</if>
+			<if test="reimbursementEndDate != null and reimbursementEndDate != ''">
+				AND a.status IN ('2', '5')
+				AND EXISTS (
+					SELECT 1 FROM work_activity_process wap
+					WHERE wap.process_instance_id = a.process_instance_id
+					AND wap.is_approval = '1'
+					AND wap.count = 1
+					AND wap.create_date > COALESCE(
+						(SELECT MAX(wap2.create_date) FROM work_activity_process wap2 WHERE wap2.process_instance_id = a.process_instance_id AND wap2.is_approval = '2'),
+						'1970-01-01'
+					)
+					GROUP BY wap.process_instance_id
+					HAVING MIN(wap.create_date) &lt; DATE_ADD(#{reimbursementEndDate}, INTERVAL 1 DAY)
+				)
+			</if>
 			<if test="sqlMap.dsf !=null and sqlMap.dsf!=''">
 				and (${sqlMap.dsf}
 				<!--<if test="submitterIdList != null and submitterIdList.size() > 0">
@@ -283,6 +325,37 @@
 				AND rvt.invoice_number like concat('%',#{invoiceNumber},'%')
 				)
 			</if>
+			<!-- 报销时间筛选:取最后一个驳回后的第一个审核节点通过时间 -->
+			<if test="reimbursementStartDate != null and reimbursementStartDate != ''">
+				AND a.status IN ('2', '5')
+				AND EXISTS (
+					SELECT 1 FROM work_activity_process wap
+					WHERE wap.process_instance_id = a.process_instance_id
+					AND wap.is_approval = '1'
+					AND wap.count = 1
+					AND wap.create_date > COALESCE(
+						(SELECT MAX(wap2.create_date) FROM work_activity_process wap2 WHERE wap2.process_instance_id = a.process_instance_id AND wap2.is_approval = '2'),
+						'1970-01-01'
+					)
+					GROUP BY wap.process_instance_id
+					HAVING MIN(wap.create_date) &gt;= #{reimbursementStartDate}
+				)
+			</if>
+			<if test="reimbursementEndDate != null and reimbursementEndDate != ''">
+				AND a.status IN ('2', '5')
+				AND EXISTS (
+					SELECT 1 FROM work_activity_process wap
+					WHERE wap.process_instance_id = a.process_instance_id
+					AND wap.is_approval = '1'
+					AND wap.count = 1
+					AND wap.create_date > COALESCE(
+						(SELECT MAX(wap2.create_date) FROM work_activity_process wap2 WHERE wap2.process_instance_id = a.process_instance_id AND wap2.is_approval = '2'),
+						'1970-01-01'
+					)
+					GROUP BY wap.process_instance_id
+					HAVING MIN(wap.create_date) &lt; DATE_ADD(#{reimbursementEndDate}, INTERVAL 1 DAY)
+				)
+			</if>
 			<if test="sqlMap.dsf !=null and sqlMap.dsf!=''">
 				and (${sqlMap.dsf}
 				<!--<if test="submitterIdList != null and submitterIdList.size() > 0">

+ 21 - 0
src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBasePointList.jsp

@@ -33,12 +33,20 @@
 				$("#searchForm").submit();
 			});
 
+			// 初始化排序单选项
+			layui.form.on('radio(sortRule)', function(data){
+				$('#sortRule').val(data.value);
+				search();
+			});
+
 			// 初始化获取时间 laydate 日期选择器
 			layui.use('laydate', function() {
 				var laydate = layui.laydate;
 				laydate.render({ elem: '#gainBeginDate', event: 'focus', type: 'date', format: 'yyyy-MM-dd', trigger: 'click' });
 				laydate.render({ elem: '#gainEndDate', event: 'focus', type: 'date', format: 'yyyy-MM-dd', trigger: 'click' });
 			});
+
+			layui.form.render('radio');
 		});
 		
 		function openUserDetailDialog(userId, userName) {
@@ -98,6 +106,9 @@
             $('#searchForm div.query input[type=hidden]').val('');
             $('#searchForm div.query select').val('');
             $("#columnId").val(currentColumnId);
+            $('#sortRule').val('total');
+            $('input[name="sortRadio"][value="total"]').prop('checked', true);
+            layui.form.render('radio');
             $('#searchForm').submit();
         }
 	</script>
@@ -120,6 +131,7 @@
 					<input id="pageNo" name="pageNo" type="hidden" value="${page.pageNo}"/>
 					<input id="pageSize" name="pageSize" type="hidden" value="${page.pageSize}"/>
 					<input id="columnId" name="columnId" type="hidden" value="${workKnowledgeBasePoint.columnId}"/>
+					<input id="sortRule" name="sortRule" type="hidden" value="${not empty workKnowledgeBasePoint.sortRule ? workKnowledgeBasePoint.sortRule : 'total'}"/>
 					<form:hidden path="toflag" value="${workKnowledgeBasePoint.toflag}"/>
 					<div class="commonQuery lw7">
 						<div class="layui-item query athird" style="width: 25%">
@@ -176,6 +188,11 @@
 							<button type="button" data-toggle="tooltip" data-placement="top" class="layui-btn layui-btn-sm layui-bg-blue" id="exportPointUser"> 下载积分兑换人员信息</button>
 						</shiro:hasPermission>
 					</div>
+					<div style="float: right;margin-right: 30px;">
+						<label class="layui-form-label double-line">排序规则:</label>
+						<input type="radio" name="sortRadio" value="total" lay-filter="sortRule" title="总积分" <c:if test="${empty workKnowledgeBasePoint.sortRule || workKnowledgeBasePoint.sortRule == 'total'}">checked</c:if> />
+						<input type="radio" name="sortRadio" value="monthly" lay-filter="sortRule" title="当月积分" <c:if test="${workKnowledgeBasePoint.sortRule == 'monthly'}">checked</c:if> />
+					</div>
 					<div style="clear: both;"></div>
 				</div>
 				<table class="oa-table layui-table" id="contentTable"></table>
@@ -205,6 +222,9 @@
                 ,{field:'totalPoint', align: 'center', title: '积分数量', width: 110, templet: function(d) {
                     return '<span style="color:#1aa094;font-weight:bold;">' + (d.totalPoint || 0) + '</span>';
                 }}
+				,{field:'monthlyPoint', align: 'center', title: '当月积分数量', width: 110, templet: function(d) {
+                    return '<span style="color:#1aa094;font-weight:bold;">' + parseInt(d.monthlyPoint || 0) + '</span>';
+                }}
             ]]
             ,data: [
                 <c:choose>
@@ -219,6 +239,7 @@
                                 ,"mobile": "<c:out value='${row.mobile}'/>"
                                 ,"phone": "<c:out value='${row.phone}'/>"
                                 ,"totalPoint": "${row.totalPoint}"
+                                ,"monthlyPoint": "${row.monthlyPoint}"
                             }
                         </c:forEach>
                     </c:when>

+ 81 - 2
src/main/webapp/webpage/modules/workprojectnotify/workProjectNotifyList.jsp

@@ -795,10 +795,16 @@
 					<div class="layui-btn-group">
 						<button class="layui-btn layui-btn-sm" data-toggle="tooltip" data-placement="left" onclick="sortOrRefresh()" title="刷新"> 刷新</button>
 					</div>
+					<shiro:hasPermission name="workprojectnotify:batch:approve">
+						<button class="layui-btn layui-btn-sm layui-btn-normal" data-toggle="tooltip" data-placement="left" onclick="batchApproveSelected()" title="批量处理勾选的报销待办"> 批量处理</button>
+					</shiro:hasPermission>
+					<shiro:hasPermission name="workprojectnotify:batch:approveAll">
+						<button class="layui-btn layui-btn-sm layui-btn-warm" data-toggle="tooltip" data-placement="left" onclick="batchApproveAll()" title="一键处理所有报销待办"> 一键处理</button>
+					</shiro:hasPermission>
 <%--					<button class="nav-btn nav-btn-refresh" data-toggle="tooltip" data-placement="left" onclick="sortOrRefresh()" title="刷新"><i class="glyphicon glyphicon-repeat"></i>&nbsp;刷新</button>--%>
 					<div style="clear: both;"></div>
 				</div>
-				<table class="oa-table layui-table" id="contentTable"></table>
+				<table class="oa-table layui-table" id="contentTable" lay-filter="contentTable"></table>
 
 				<!-- 分页代码 -->
 				<table:page page="${page}"></table:page>
@@ -816,7 +822,7 @@
             ,elem: '#contentTable'
             ,page: false
             ,cols: [[
-                // {checkbox: true, fixed: true},
+                {checkbox: true, fixed: true},
                 {field:'index',align:'center',  width:40,title: '序号'}
                 ,{align:'center', title: '类型', width:100,templet:function(d){
 						if (d.belongProject == "cpa") {
@@ -1503,5 +1509,78 @@
         resizeListWindow1();
     });
 </script>
+<script>
+    /**
+     * 批量处理 - 处理勾选的报销待办
+     */
+    function batchApproveSelected() {
+        var checkStatus = layui.table.checkStatus('contentTable');
+        var data = checkStatus.data;
+        if (data.length === 0) {
+            top.layer.msg('请至少选择一条数据', {icon: 0});
+            return;
+        }
+        // 筛选出报销类型的勾选数据
+        var reimbursementTypes = ['13','102','106','107','108','109','112'];
+        var notifyIds = [];
+        for (var i = 0; i < data.length; i++) {
+            if (reimbursementTypes.indexOf(data[i].type) !== -1 && data[i].title && data[i].title.indexOf('报销') !== -1) {
+                notifyIds.push(data[i].id);
+            }
+        }
+        if (notifyIds.length === 0) {
+            top.layer.msg('勾选的数据中没有报销类型的待办', {icon: 0});
+            return;
+        }
+        top.layer.confirm('确认批量审批通过 ' + notifyIds.length + ' 条报销待办吗?', {icon: 3, title: '确认'}, function(index) {
+            top.layer.close(index);
+            top.layer.msg('正在处理中,请稍候...', {icon: 16, shade: 0.3, time: 0});
+            $.ajax({
+                url: '${ctx}/workprojectnotify/workProjectNotifyBatch/batchApprove',
+                type: 'POST',
+                contentType: 'application/json',
+                data: JSON.stringify(notifyIds),
+                dataType: 'json',
+                success: function(res) {
+                    top.layer.closeAll();
+                    top.layer.msg(res.msg, {icon: 1, time: 3000});
+                    setTimeout(function() {
+                        location.reload();
+                    }, 1500);
+                },
+                error: function() {
+                    top.layer.closeAll();
+                    top.layer.msg('请求失败,请重试', {icon: 2});
+                }
+            });
+        });
+    }
+
+    /**
+     * 一键处理 - 处理所有报销待办(全量数据)
+     */
+    function batchApproveAll() {
+        top.layer.confirm('确认一键审批通过所有报销待办吗?此操作将处理全量数据,处理失败的记录会自动跳过。', {icon: 3, title: '确认'}, function(index) {
+            top.layer.close(index);
+            top.layer.msg('正在处理中,请稍候...', {icon: 16, shade: 0.3, time: 0});
+            $.ajax({
+                url: '${ctx}/workprojectnotify/workProjectNotifyBatch/approveAll',
+                type: 'POST',
+                dataType: 'json',
+                success: function(res) {
+                    top.layer.closeAll();
+                    top.layer.msg(res.msg, {icon: 1, time: 3000});
+                    setTimeout(function() {
+                        location.reload();
+                    }, 1500);
+                },
+                error: function() {
+                    top.layer.closeAll();
+                    top.layer.msg('请求失败,请重试', {icon: 2});
+                }
+            });
+        });
+    }
+</script>
 </body>
 </html>

+ 30 - 3
src/main/webapp/webpage/modules/workreimbursement/workReimbursementAllList.jsp

@@ -89,7 +89,7 @@
                     <div id="moresees" style="clear:both;display:none;">
 
                         <div class="layui-item query athird">
-                            <label class="layui-form-label">报销时间:</label>
+                            <label class="layui-form-label">创建时间:</label>
                             <div class="layui-input-block readOnlyFFF">
                                 <input id="startDate" placeholder="开始时间" name="startDate" type="text" readonly="readonly" maxlength="20" class="laydate-icondate form-control layer-date layui-input laydate-icon query-group"
                                        value="<fmt:formatDate value="${workReimbursement.startDate}" pattern="yyyy-MM-dd"/>"/>
@@ -101,6 +101,18 @@
                             </div>
                         </div>
                         <div class="layui-item query athird">
+                            <label class="layui-form-label">报销时间:</label>
+                            <div class="layui-input-block readOnlyFFF">
+                                <input id="reimbursementStartDate" placeholder="开始时间" name="reimbursementStartDate" type="text" readonly="readonly" maxlength="20" class="laydate-icondate form-control layer-date layui-input laydate-icon query-group"
+                                       value="<fmt:formatDate value="${workReimbursement.reimbursementStartDate}" pattern="yyyy-MM-dd"/>"/>
+                                </input>
+                                <span class="group-sep">-</span>
+                                <input id="reimbursementEndDate" placeholder="结束时间" name="reimbursementEndDate" type="text" readonly="readonly" maxlength="20" class="laydate-icondate form-control layer-date layui-input laydate-icon query-group"
+                                       value="<fmt:formatDate value="${workReimbursement.reimbursementEndDate}" pattern="yyyy-MM-dd"/>"/>
+                                </input>
+                            </div>
+                        </div>
+                        <div class="layui-item query athird">
                             <label class="layui-form-label">经办人:</label>
                             <div class="layui-input-block with-icon">
                                 <sys:inquireselectUser id="handleId" name="handleId" value="${workReimbursement.handleId}" labelName="handleName" labelValue="${workReimbursement.handleName}"
@@ -265,7 +277,8 @@
             {field:'officeId', align:'center', title: '报销部门', width:130, templet:function(d){
                     return "<span title='"+ d.officeId +"'>" + d.officeId + "</span>";
                 }},
-            {field:'submitterDate', align:'center', title: '报销日期', width:80},
+            {field:'createDate', align:'center', title: '创建日期', width:80},
+            {field:'reimbursementDate', align:'center', title: '报销日期', width:80},
             {field:'money', align:'center', title: '报销金额(元)', width:150, templet:function(d){
                     return "<span title='"+ d.money +"'>" + d.money + "</span>";
                 }},
@@ -413,7 +426,8 @@
                     <c:if test="${empty workReimbursement.project || empty workReimbursement.project.leaderNameStr}">
                     ""
                     </c:if>
-                    ,"submitterDate":"<fmt:formatDate value="${workReimbursement.submitterDate}" pattern="yyyy-MM-dd"/>"
+                    ,"createDate":"<fmt:formatDate value="${workReimbursement.createDate}" pattern="yyyy-MM-dd"/>"
+                    ,"reimbursementDate":"<fmt:formatDate value="${workReimbursement.reimbursementDate}" pattern="yyyy-MM-dd"/>"
                     ,"money":"<fmt:formatNumber value="${workReimbursement.money}" pattern="#,##0.00"/>"
                     ,"status":"${workReimbursement.status}"
                     <shiro:hasPermission name="workreimbursement:workReimbursementAll:del">
@@ -514,6 +528,19 @@
             type : 'date'
 , trigger: 'click'
         });
+
+        laydate.render({
+            elem: '#reimbursementStartDate', //目标元素。由于laydate.js封装了一个轻量级的选择器引擎,因此elem还允许你传入class、tag但必须按照这种方式 '#id .class'
+            event: 'focus', //响应事件。如果没有传入event,则按照默认的click
+            type : 'date'
+, trigger: 'click'
+        });
+        laydate.render({
+            elem: '#reimbursementEndDate', //目标元素。由于laydate.js封装了一个轻量级的选择器引擎,因此elem还允许你传入class、tag但必须按照这种方式 '#id .class'
+            event: 'focus', //响应事件。如果没有传入event,则按照默认的click
+            type : 'date'
+, trigger: 'click'
+        });
     });
     function switchInput(obj){
         $("#"+obj).show();