From 2c18c7b8d1708fd028b8e5093d5f5832c389ed0e Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期五, 22 五月 2026 09:29:22 +0800
Subject: [PATCH] feat(approve): 完善审批实例管理功能并新增报销单模块
---
src/main/java/com/ruoyi/approve/pojo/FinReimbursement.java | 210 +++++++
src/main/java/com/ruoyi/approve/controller/ApprovalInstanceController.java | 2
src/main/java/com/ruoyi/approve/mapper/FinReimbursementDetailMapper.java | 18
src/main/java/com/ruoyi/approve/bean/dto/FinReimbursementDto.java | 21
src/main/java/com/ruoyi/collaborativeApproval/dto/EnterpriseNewsDto.java | 4
src/main/java/com/ruoyi/approve/controller/FinReimbursementDetailController.java | 18
src/main/java/com/ruoyi/approve/pojo/FinReimbursementTravel.java | 162 +++++
src/main/java/com/ruoyi/approve/controller/FinReimbursementController.java | 60 ++
src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java | 157 ++++
src/main/java/com/ruoyi/approve/service/impl/FinReimbursementServiceImpl.java | 537 ++++++++++++++++++
src/main/java/com/ruoyi/approve/service/FinReimbursementDetailService.java | 16
src/main/java/com/ruoyi/approve/service/FinReimbursementService.java | 31 +
src/main/resources/mapper/approve/FinReimbursementDetailMapper.xml | 29 +
src/main/java/com/ruoyi/approve/pojo/FinReimbursementDetail.java | 157 +++++
src/main/resources/mapper/approve/FinReimbursementTravelMapper.xml | 29 +
src/main/java/com/ruoyi/collaborativeApproval/vo/EnterpriseNewsVo.java | 5
src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsServiceImpl.java | 14
src/main/java/com/ruoyi/approve/bean/dto/ApprovalInstanceDto.java | 5
src/main/java/com/ruoyi/approve/service/FinReimbursementTravelService.java | 16
src/main/java/com/ruoyi/approve/controller/FinReimbursementTravelController.java | 18
src/main/java/com/ruoyi/approve/bean/vo/ApprovalInstanceVo.java | 3
src/main/java/com/ruoyi/approve/service/impl/FinReimbursementDetailServiceImpl.java | 20
src/main/java/com/ruoyi/approve/service/impl/FinReimbursementTravelServiceImpl.java | 20
src/main/java/com/ruoyi/approve/bean/vo/FinReimbursementVo.java | 34 +
src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateServiceImpl.java | 1
src/main/java/com/ruoyi/approve/mapper/FinReimbursementTravelMapper.java | 18
src/main/java/com/ruoyi/approve/service/ApprovalInstanceService.java | 2
src/main/java/com/ruoyi/approve/mapper/FinReimbursementMapper.java | 24
src/main/resources/mapper/approve/FinReimbursementMapper.xml | 57 +
src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java | 2
30 files changed, 1,671 insertions(+), 19 deletions(-)
diff --git a/src/main/java/com/ruoyi/approve/bean/dto/ApprovalInstanceDto.java b/src/main/java/com/ruoyi/approve/bean/dto/ApprovalInstanceDto.java
index 17e4921..a2df482 100644
--- a/src/main/java/com/ruoyi/approve/bean/dto/ApprovalInstanceDto.java
+++ b/src/main/java/com/ruoyi/approve/bean/dto/ApprovalInstanceDto.java
@@ -1,7 +1,10 @@
package com.ruoyi.approve.bean.dto;
import com.ruoyi.approve.pojo.ApprovalInstance;
+import com.ruoyi.basic.dto.StorageBlobDTO;
import lombok.Data;
+
+import java.util.List;
@Data
public class ApprovalInstanceDto extends ApprovalInstance {
@@ -13,4 +16,6 @@
private String createTimeEnd;
private String createTimeStart;
+
+ private List<StorageBlobDTO> storageBlobDTOs;
}
diff --git a/src/main/java/com/ruoyi/approve/bean/dto/FinReimbursementDto.java b/src/main/java/com/ruoyi/approve/bean/dto/FinReimbursementDto.java
new file mode 100644
index 0000000..2f14376
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/dto/FinReimbursementDto.java
@@ -0,0 +1,21 @@
+package com.ruoyi.approve.bean.dto;
+
+import com.ruoyi.approve.pojo.FinReimbursement;
+import com.ruoyi.approve.pojo.FinReimbursementDetail;
+import com.ruoyi.approve.pojo.FinReimbursementTravel;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class FinReimbursementDto extends FinReimbursement {
+
+ private String createTimeStart;
+ private String createTimeEnd;
+
+ private FinReimbursementTravel travel;
+ private List<FinReimbursementDetail> details;
+ private List<ApprovalTemplateNodeDto> nodes;
+ private List<StorageBlobDTO> storageBlobDTOs;
+}
diff --git a/src/main/java/com/ruoyi/approve/bean/vo/ApprovalInstanceVo.java b/src/main/java/com/ruoyi/approve/bean/vo/ApprovalInstanceVo.java
index f37c068..552ed0a 100644
--- a/src/main/java/com/ruoyi/approve/bean/vo/ApprovalInstanceVo.java
+++ b/src/main/java/com/ruoyi/approve/bean/vo/ApprovalInstanceVo.java
@@ -3,6 +3,7 @@
import com.ruoyi.approve.pojo.ApprovalInstance;
import com.ruoyi.approve.pojo.ApprovalRecord;
import com.ruoyi.approve.pojo.ApprovalTask;
+import com.ruoyi.basic.dto.StorageBlobVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -22,4 +23,6 @@
@Schema(description = "涓氬姟鍚嶇О")
private String businessName;
+
+ private List<StorageBlobVO> storageBlobVOList;
}
diff --git a/src/main/java/com/ruoyi/approve/bean/vo/FinReimbursementVo.java b/src/main/java/com/ruoyi/approve/bean/vo/FinReimbursementVo.java
new file mode 100644
index 0000000..5706ff3
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/vo/FinReimbursementVo.java
@@ -0,0 +1,34 @@
+package com.ruoyi.approve.bean.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.approve.pojo.*;
+import com.ruoyi.basic.dto.StorageBlobVO;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Data
+public class FinReimbursementVo extends FinReimbursement {
+
+
+ private String createTimeStart;
+ private String createTimeEnd;
+
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime startTime;
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime endTime;
+
+ private FinReimbursementTravel travel;
+ private List<FinReimbursementDetail> details;
+ //瀹℃壒娴佺▼
+ private List<ApprovalTask> tasks;
+
+ //瀹℃壒璁板綍
+ private List<ApprovalRecord> records;
+ private List<StorageBlobVO> storageBlobVOList;
+}
diff --git a/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceController.java b/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceController.java
index f13e1b3..0a32725 100644
--- a/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceController.java
+++ b/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceController.java
@@ -43,7 +43,7 @@
@PutMapping("/update")
@Operation(summary = "鏇存柊")
public R update(@RequestBody ApprovalInstanceDto approvalInstanceDto) {
- return approvalInstanceService.updateById(approvalInstanceDto) ? R.ok() : R.fail();
+ return approvalInstanceService.update(approvalInstanceDto) ? R.ok() : R.fail();
}
@DeleteMapping("/delete")
diff --git a/src/main/java/com/ruoyi/approve/controller/FinReimbursementController.java b/src/main/java/com/ruoyi/approve/controller/FinReimbursementController.java
new file mode 100644
index 0000000..a2eecdb
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/controller/FinReimbursementController.java
@@ -0,0 +1,60 @@
+package com.ruoyi.approve.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.approve.bean.dto.FinReimbursementDto;
+import com.ruoyi.approve.bean.vo.FinReimbursementVo;
+import com.ruoyi.approve.service.FinReimbursementService;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曚富琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:15
+ */
+@RestController
+@RequestMapping("/finReimbursement")
+@Tag(name = "鎶ラ攢鍗曚富琛�", description = "鎶ラ攢鍗曚富琛�")
+@AllArgsConstructor
+public class FinReimbursementController {
+
+ private final FinReimbursementService finReimbursementService;
+
+ @GetMapping("/listPage")
+ @Operation(summary = "鍒嗛〉鏌ヨ")
+ public R listPage(Page<FinReimbursementVo> page, FinReimbursementDto finReimbursementDto) {
+ return R.ok(finReimbursementService.listPage(finReimbursementDto, page));
+ }
+
+ @PostMapping("/save")
+ @Operation(summary = "淇濆瓨")
+ public R save(@RequestBody FinReimbursementDto finReimbursementDto) {
+ return R.ok(finReimbursementService.add(finReimbursementDto));
+ }
+
+ @GetMapping("/detail")
+ @Operation(summary = "璇︽儏")
+ public R detail(Long id) {
+ return R.ok(finReimbursementService.detail(id));
+ }
+
+ @PostMapping("/update")
+ @Operation(summary = "淇敼")
+ public R update(@RequestBody FinReimbursementDto finReimbursementDto) {
+ return R.ok(finReimbursementService.update(finReimbursementDto));
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "鍒犻櫎")
+ public R delete(@RequestBody List<Long> ids) {
+ return R.ok(finReimbursementService.delete(ids));
+ }
+}
diff --git a/src/main/java/com/ruoyi/approve/controller/FinReimbursementDetailController.java b/src/main/java/com/ruoyi/approve/controller/FinReimbursementDetailController.java
new file mode 100644
index 0000000..18e4f73
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/controller/FinReimbursementDetailController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曟槑缁嗚〃 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:38
+ */
+@RestController
+@RequestMapping("/finReimbursementDetail")
+public class FinReimbursementDetailController {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/controller/FinReimbursementTravelController.java b/src/main/java/com/ruoyi/approve/controller/FinReimbursementTravelController.java
new file mode 100644
index 0000000..0e67feb
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/controller/FinReimbursementTravelController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 宸梾鎶ラ攢鎵╁睍琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:47
+ */
+@RestController
+@RequestMapping("/finReimbursementTravel")
+public class FinReimbursementTravelController {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/mapper/FinReimbursementDetailMapper.java b/src/main/java/com/ruoyi/approve/mapper/FinReimbursementDetailMapper.java
new file mode 100644
index 0000000..edc039a
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/mapper/FinReimbursementDetailMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.approve.pojo.FinReimbursementDetail;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曟槑缁嗚〃 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:38
+ */
+@Mapper
+public interface FinReimbursementDetailMapper extends BaseMapper<FinReimbursementDetail> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/mapper/FinReimbursementMapper.java b/src/main/java/com/ruoyi/approve/mapper/FinReimbursementMapper.java
new file mode 100644
index 0000000..19ac354
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/mapper/FinReimbursementMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.approve.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.approve.bean.dto.FinReimbursementDto;
+import com.ruoyi.approve.bean.vo.FinReimbursementVo;
+import com.ruoyi.approve.pojo.FinReimbursement;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曚富琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:15
+ */
+@Mapper
+public interface FinReimbursementMapper extends BaseMapper<FinReimbursement> {
+
+ IPage<FinReimbursementVo> listPage(@Param("ew") FinReimbursementDto finReimbursementDto, Page<FinReimbursementVo> page);
+}
diff --git a/src/main/java/com/ruoyi/approve/mapper/FinReimbursementTravelMapper.java b/src/main/java/com/ruoyi/approve/mapper/FinReimbursementTravelMapper.java
new file mode 100644
index 0000000..bc5e1b8
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/mapper/FinReimbursementTravelMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.approve.pojo.FinReimbursementTravel;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 宸梾鎶ラ攢鎵╁睍琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:47
+ */
+@Mapper
+public interface FinReimbursementTravelMapper extends BaseMapper<FinReimbursementTravel> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/pojo/FinReimbursement.java b/src/main/java/com/ruoyi/approve/pojo/FinReimbursement.java
new file mode 100644
index 0000000..7d5ad9c
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/pojo/FinReimbursement.java
@@ -0,0 +1,210 @@
+package com.ruoyi.approve.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曚富琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:15
+ */
+@Getter
+@Setter
+@ToString
+@TableName("fin_reimbursement")
+@ApiModel(value = "FinReimbursement瀵硅薄", description = "鎶ラ攢鍗曚富琛�")
+public class FinReimbursement implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 涓婚敭ID
+ */
+ @Schema(description = "涓婚敭ID")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 鎶ラ攢鍗曞彿
+ */
+ @Schema(description = "鎶ラ攢鍗曞彿")
+ private String billNo;
+
+ /**
+ * 鎶ラ攢绫诲瀷锛�1-宸梾鎶ラ攢锛�2-璐圭敤鎶ラ攢
+ */
+ @Schema(description = "鎶ラ攢绫诲瀷锛�1-宸梾鎶ラ攢锛�2-璐圭敤鎶ラ攢")
+ private Byte reimbursementType;
+
+ /**
+ * 璐圭敤绫诲瀷锛氬樊鏃呰垂/鍔炲叕閲囪喘/涓氬姟鎷涘緟/浜ら�氳垂/閫氳璐�/鍏朵粬
+ */
+ @Schema(description = "璐圭敤绫诲瀷锛氬樊鏃呰垂/鍔炲叕閲囪喘/涓氬姟鎷涘緟/浜ら�氳垂/閫氳璐�/鍏朵粬")
+ private String expenseType;
+
+ /**
+ * 鐢宠浜篒D
+ */
+ @Schema(description = "鐢宠浜篒D")
+ private Long applicantId;
+
+ /**
+ * 鍛樺伐缂栧彿
+ */
+ @Schema(description = "鍛樺伐缂栧彿")
+ private String applicantCode;
+
+ /**
+ * 鍛樺伐濮撳悕
+ */
+ @Schema(description = "鍛樺伐濮撳悕")
+ private String applicantName;
+
+ /**
+ * 鐢宠閮ㄩ棬ID
+ */
+ @Schema(description = "鐢宠閮ㄩ棬ID")
+ private Long applicantDeptId;
+
+ /**
+ * 鐢宠閮ㄩ棬鍚嶇О
+ */
+ @Schema(description = "鐢宠閮ㄩ棬鍚嶇О")
+ private String applicantDeptName;
+
+ /**
+ * 鎶ラ攢鍘熷洜
+ */
+ @Schema(description = "鎶ラ攢鍘熷洜")
+ private String reason;
+
+ /**
+ * 鐢宠閲戦
+ */
+ @Schema(description = "鐢宠閲戦")
+ private BigDecimal applyAmount;
+
+ /**
+ * 鏄庣粏姹囨�婚噾棰�
+ */
+ @Schema(description = "鏄庣粏姹囨�婚噾棰�")
+ private BigDecimal detailTotalAmount;
+
+ /**
+ * 鏀舵浜�
+ */
+ @Schema(description = "鏀舵浜�")
+ private String payeeName;
+
+ /**
+ * 鏀舵璐﹀彿
+ */
+ @Schema(description = "鏀舵璐﹀彿")
+ private String payeeAccount;
+
+ /**
+ * 寮�鎴锋敮琛�
+ */
+ @Schema(description = "寮�鎴锋敮琛�")
+ private String payeeBank;
+
+ /**
+ * 瀹℃壒瀹炰緥ID锛屽搴� approval_instance.id
+ */
+ @Schema(description = "瀹℃壒瀹炰緥ID锛屽搴� approval_instance.id")
+ private Long approvalInstanceId;
+
+ /**
+ * 瀹℃壒娴佺▼ID锛屽搴� approve_process.id
+ */
+ @Schema(description = "瀹℃壒娴佺▼ID锛屽搴� approve_process.id")
+ private Long approveProcessId;
+
+ /**
+ * 鍗曟嵁鐘舵�侊細DRAFT-鑽夌锛孖N_APPROVAL-瀹℃壒涓紝APPROVED-瀹℃壒閫氳繃锛孯EJECTED-瀹℃壒椹冲洖锛學ITHDRAWN-宸叉挙鍥烇紝PAID-宸蹭粯娆�
+ */
+ @Schema(description = "鍗曟嵁鐘舵�侊細DRAFT-鑽夌锛孖N_APPROVAL-瀹℃壒涓紝APPROVED-瀹℃壒閫氳繃锛孯EJECTED-瀹℃壒椹冲洖锛學ITHDRAWN-宸叉挙鍥烇紝PAID-宸蹭粯娆�")
+ private String billStatus;
+
+ /**
+ * 瀹℃壒閫氳繃鏃堕棿
+ */
+ @Schema(description = "瀹℃壒閫氳繃鏃堕棿")
+ private LocalDateTime approvedTime;
+
+ /**
+ * 浠樻鏃堕棿
+ */
+ @Schema(description = "浠樻鏃堕棿")
+ private LocalDateTime paidTime;
+
+ /**
+ * 鐢熸垚鐨勮储鍔℃敮鍑鸿褰旾D锛屽搴� account_expense.id
+ */
+ @Schema(description = "鐢熸垚鐨勮储鍔℃敮鍑鸿褰旾D锛屽搴� account_expense.id")
+ private Long accountExpenseId;
+
+ /**
+ * 澶囨敞
+ */
+ @Schema(description = "澶囨敞")
+ private String remark;
+
+ /**
+ * 绉熸埛ID
+ */
+ @Schema(description = "绉熸埛ID")
+ private Long tenantId;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @Schema(description = "鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Long createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @Schema(description = "鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ /**
+ * 鏇存柊浜�
+ */
+ @Schema(description = "鏇存柊浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Long updateUser;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ @Schema(description = "鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+ /**
+ * 褰掑睘閮ㄩ棬ID
+ */
+ @Schema(description = "褰掑睘閮ㄩ棬ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+
+ /**
+ * 閫昏緫鍒犻櫎锛�0-鍚︼紝1-鏄�
+ */
+ @Schema(description = "閫昏緫鍒犻櫎锛�0-鍚︼紝1-鏄�")
+ private Byte deleted;
+}
diff --git a/src/main/java/com/ruoyi/approve/pojo/FinReimbursementDetail.java b/src/main/java/com/ruoyi/approve/pojo/FinReimbursementDetail.java
new file mode 100644
index 0000000..5d0220e
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/pojo/FinReimbursementDetail.java
@@ -0,0 +1,157 @@
+package com.ruoyi.approve.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曟槑缁嗚〃
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:38
+ */
+@Getter
+@Setter
+@ToString
+@TableName("fin_reimbursement_detail")
+@ApiModel(value = "FinReimbursementDetail瀵硅薄", description = "鎶ラ攢鍗曟槑缁嗚〃")
+public class FinReimbursementDetail implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 涓婚敭ID
+ */
+ @Schema(description = "涓婚敭ID")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 鎶ラ攢鍗旾D锛屽搴� fin_reimbursement.id
+ */
+ @Schema(description = "鎶ラ攢鍗旾D锛屽搴� fin_reimbursement.id")
+ private Long reimbursementId;
+
+ /**
+ * 鏄庣粏琛屽彿
+ */
+ @Schema(description = "鏄庣粏琛屽彿")
+ private Integer rowNo;
+
+ /**
+ * 鍙戠エ鏃ユ湡
+ */
+ @Schema(description = "鍙戠エ鏃ユ湡")
+ private LocalDate invoiceDate;
+
+ /**
+ * 璐圭敤绉戠洰
+ */
+ @Schema(description = "璐圭敤绉戠洰")
+ private String expenseCategory;
+
+ /**
+ * 閲戦
+ */
+ @Schema(description = "閲戦")
+ private BigDecimal amount;
+
+ /**
+ * 鎻忚堪
+ */
+ @Schema(description = "鎻忚堪")
+ private String description;
+
+ /**
+ * 鍙戠エ鍙风爜
+ */
+ @Schema(description = "鍙戠エ鍙风爜")
+ private String invoiceNo;
+
+ /**
+ * 鍙戠エ绫诲瀷
+ */
+ @Schema(description = "鍙戠エ绫诲瀷")
+ private String invoiceType;
+
+ /**
+ * 绁ㄩ潰閲戦
+ */
+ @Schema(description = "绁ㄩ潰閲戦")
+ private BigDecimal invoiceAmount;
+
+ /**
+ * 绋庣巼
+ */
+ @Schema(description = "绋庣巼")
+ private BigDecimal taxRate;
+
+ /**
+ * 绋庨
+ */
+ @Schema(description = "绋庨")
+ private BigDecimal taxAmount;
+
+ /**
+ * 澶囨敞
+ */
+ @Schema(description = "澶囨敞")
+ private String remark;
+
+ /**
+ * 绉熸埛ID
+ */
+ @Schema(description = "绉熸埛ID")
+ private Long tenantId;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @Schema(description = "鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Long createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @Schema(description = "鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ /**
+ * 鏇存柊浜�
+ */
+ @Schema(description = "鏇存柊浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Long updateUser;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ @Schema(description = "鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+ /**
+ * 褰掑睘閮ㄩ棬ID
+ */
+ @Schema(description = "褰掑睘閮ㄩ棬ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+
+ /**
+ * 閫昏緫鍒犻櫎锛�0-鍚︼紝1-鏄�
+ */
+ @Schema(description = "閫昏緫鍒犻櫎锛�0-鍚︼紝1-鏄�")
+ private Byte deleted;
+}
diff --git a/src/main/java/com/ruoyi/approve/pojo/FinReimbursementTravel.java b/src/main/java/com/ruoyi/approve/pojo/FinReimbursementTravel.java
new file mode 100644
index 0000000..10c607c
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/pojo/FinReimbursementTravel.java
@@ -0,0 +1,162 @@
+package com.ruoyi.approve.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 宸梾鎶ラ攢鎵╁睍琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:47
+ */
+@Getter
+@Setter
+@ToString
+@TableName("fin_reimbursement_travel")
+@ApiModel(value = "FinReimbursementTravel瀵硅薄", description = "宸梾鎶ラ攢鎵╁睍琛�")
+public class FinReimbursementTravel implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 涓婚敭ID
+ */
+ @Schema(description = "涓婚敭ID")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 鎶ラ攢鍗旾D锛屽搴� fin_reimbursement.id
+ */
+ @Schema(description = "鎶ラ攢鍗旾D锛屽搴� fin_reimbursement.id")
+ private Long reimbursementId;
+
+ /**
+ * 鍑哄樊寮�濮嬫椂闂�
+ */
+ @Schema(description = "鍑哄樊寮�濮嬫椂闂�")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime startTime;
+
+ /**
+ * 鍑哄樊缁撴潫鏃堕棿
+ */
+ @Schema(description = "鍑哄樊缁撴潫鏃堕棿")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime endTime;
+
+ /**
+ * 鍑哄樊澶╂暟
+ */
+ @Schema(description = "鍑哄樊澶╂暟")
+ private BigDecimal travelDays;
+
+ /**
+ * 鍑哄樊鍦�/鍑哄彂鍩庡競
+ */
+ @Schema(description = "鍑哄樊鍦�/鍑哄彂鍩庡競")
+ private String departureCity;
+
+ /**
+ * 鐩殑鍦�/鐩殑鍩庡競
+ */
+ @Schema(description = "鐩殑鍦�/鐩殑鍩庡競")
+ private String destinationCity;
+
+ /**
+ * 閰掑簵鏍囧噯
+ */
+ @Schema(description = "閰掑簵鏍囧噯")
+ private BigDecimal hotelStandard;
+
+ /**
+ * 浣忓澶╂暟
+ */
+ @Schema(description = "浣忓澶╂暟")
+ private BigDecimal lodgingDays;
+
+ /**
+ * 鐢熸椿琛ヨ创
+ */
+ @Schema(description = "鐢熸椿琛ヨ创")
+ private BigDecimal mealAllowance;
+
+ /**
+ * 浜ら�氳ˉ璐�
+ */
+ @Schema(description = "浜ら�氳ˉ璐�")
+ private BigDecimal transportAllowance;
+
+ /**
+ * 浣忓闄愰
+ */
+ @Schema(description = "浣忓闄愰")
+ private BigDecimal lodgingLimit;
+
+ /**
+ * 鐗规壒鏍囪鏂囨湰锛屽鍦ㄦ爣鍑嗚寖鍥村唴/瓒呮爣鐗规壒
+ */
+ @Schema(description = "鐗规壒鏍囪鏂囨湰锛屽鍦ㄦ爣鍑嗚寖鍥村唴/瓒呮爣鐗规壒")
+ private String standardTag;
+
+ /**
+ * 鏄惁鍦ㄦ爣鍑嗗唴锛�1-鏄紝0-鍚�
+ */
+ @Schema(description = "鏄惁鍦ㄦ爣鍑嗗唴锛�1-鏄紝0-鍚�")
+ private Byte withinStandard;
+
+ /**
+ * 绉熸埛ID
+ */
+ @Schema(description = "绉熸埛ID")
+ private Long tenantId;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @Schema(description = "鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Long createUser;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @Schema(description = "鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ /**
+ * 鏇存柊浜�
+ */
+ @Schema(description = "鏇存柊浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Long updateUser;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ @Schema(description = "鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+ /**
+ * 褰掑睘閮ㄩ棬ID
+ */
+ @Schema(description = "褰掑睘閮ㄩ棬ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/approve/service/ApprovalInstanceService.java b/src/main/java/com/ruoyi/approve/service/ApprovalInstanceService.java
index fe24839..dfb9517 100644
--- a/src/main/java/com/ruoyi/approve/service/ApprovalInstanceService.java
+++ b/src/main/java/com/ruoyi/approve/service/ApprovalInstanceService.java
@@ -23,6 +23,8 @@
Boolean add(ApprovalInstanceDto approvalInstanceDto);
+ Boolean update(ApprovalInstanceDto approvalInstanceDto);
+
Boolean delete(List<Long> ids);
R approve(ApprovalInstanceDto approvalInstanceDto);
diff --git a/src/main/java/com/ruoyi/approve/service/FinReimbursementDetailService.java b/src/main/java/com/ruoyi/approve/service/FinReimbursementDetailService.java
new file mode 100644
index 0000000..0279c25
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/FinReimbursementDetailService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.approve.service;
+
+import com.ruoyi.approve.pojo.FinReimbursementDetail;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曟槑缁嗚〃 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:38
+ */
+public interface FinReimbursementDetailService extends IService<FinReimbursementDetail> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/service/FinReimbursementService.java b/src/main/java/com/ruoyi/approve/service/FinReimbursementService.java
new file mode 100644
index 0000000..c14b943
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/FinReimbursementService.java
@@ -0,0 +1,31 @@
+package com.ruoyi.approve.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.approve.bean.dto.FinReimbursementDto;
+import com.ruoyi.approve.bean.vo.FinReimbursementVo;
+import com.ruoyi.approve.pojo.FinReimbursement;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曚富琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:15
+ */
+public interface FinReimbursementService extends IService<FinReimbursement> {
+
+ IPage<FinReimbursementVo> listPage(FinReimbursementDto finReimbursementDto, Page<FinReimbursementVo> page);
+
+ Boolean add(FinReimbursementDto finReimbursementDto);
+
+ FinReimbursementVo detail(Long id);
+
+ Boolean update(FinReimbursementDto finReimbursementDto);
+
+ Boolean delete(List<Long> ids);
+}
diff --git a/src/main/java/com/ruoyi/approve/service/FinReimbursementTravelService.java b/src/main/java/com/ruoyi/approve/service/FinReimbursementTravelService.java
new file mode 100644
index 0000000..0733d1b
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/FinReimbursementTravelService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.approve.service;
+
+import com.ruoyi.approve.pojo.FinReimbursementTravel;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 宸梾鎶ラ攢鎵╁睍琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:47
+ */
+public interface FinReimbursementTravelService extends IService<FinReimbursementTravel> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java
index c15ccb7..3e710a8 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java
@@ -10,15 +10,20 @@
import com.ruoyi.approve.bean.dto.ApprovalInstanceDto;
import com.ruoyi.approve.bean.vo.ApprovalInstanceVo;
import com.ruoyi.approve.mapper.ApprovalInstanceMapper;
+import com.ruoyi.approve.mapper.ApprovalTemplateNodeApproverMapper;
+import com.ruoyi.approve.mapper.FinReimbursementMapper;
import com.ruoyi.approve.pojo.*;
import com.ruoyi.approve.service.*;
import com.ruoyi.approve.utils.ApproveProcessConfigNodeUtils;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.utils.FileUtil;
+import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsMapper;
+import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeDeptMapper;
+import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeUserMapper;
import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept;
import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser;
-import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeDeptService;
-import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeUserService;
-import com.ruoyi.collaborativeApproval.service.EnterpriseNewsService;
import com.ruoyi.common.enums.*;
import com.ruoyi.common.utils.OrderUtils;
import com.ruoyi.common.utils.SecurityUtils;
@@ -40,6 +45,8 @@
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.sales.pojo.SalesQuotation;
import com.ruoyi.sales.pojo.ShippingInfo;
+import com.ruoyi.staff.mapper.HolidayApplicationMapper;
+import com.ruoyi.staff.pojo.HolidayApplication;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -69,7 +76,8 @@
private final ApprovalTaskService approvalTaskService;
private final ApprovalRecordService approvalRecordService;
private final ApprovalTemplateNodeService approvalTemplateNodeService;
- private final ApprovalTemplateNodeApproverService approvalTemplateNodeApproverService;
+ private final FinReimbursementMapper finReimbursementMapper;
+ private final FileUtil fileUtil;
private final ISysNoticeService sysNoticeService;
private final PurchaseLedgerMapper purchaseLedgerMapper;
private final SalesLedgerProductMapper salesLedgerProductMapper;
@@ -77,12 +85,14 @@
private final SalesQuotationMapper salesQuotationMapper;
private final ShippingInfoMapper shippingInfoMapper;
private final QualityInspectHelper qualityInspectHelper;
- private final EnterpriseNewsService enterpriseNewsService;
- private final EnterpriseNewsScopeDeptService enterpriseNewsScopeDeptService;
- private final EnterpriseNewsScopeUserService enterpriseNewsScopeUserService;
+ private final EnterpriseNewsScopeUserMapper enterpriseNewsScopeUserMapper;
private final SysUserMapper sysUserMapper;
private final SysUserDeptMapper sysUserDeptMapper;
private final SysDeptMapper sysDeptMapper;
+ private final HolidayApplicationMapper holidayApplicationMapper;
+ private final EnterpriseNewsMapper enterpriseNewsMapper;
+ private final EnterpriseNewsScopeDeptMapper enterpriseNewsScopeDeptMapper;
+ private final ApprovalTemplateNodeApproverMapper approvalTemplateNodeApproverMapper;
@Override
public R listPage(Page<ApprovalInstanceVo> page, ApprovalInstanceDto approvalInstanceDto) {
@@ -119,6 +129,7 @@
vo.setIsApprove(approveProcessConfigNodeUtils.isCurrentApprover(vo.getId(), currentUserId));
vo.setRecords(recordMap.getOrDefault(vo.getId(), new ArrayList<>()));
vo.setTasks(taskMap.getOrDefault(vo.getId(), new ArrayList<>()));
+ vo.setStorageBlobVOList(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.APPROVAL_INSTANCE, vo.getId()));
}
}
@@ -137,7 +148,22 @@
return false;
}
approveProcessConfigNodeUtils.createCurrentNodeAndTasks(approvalInstanceDto);
+ fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVAL_INSTANCE, approvalInstanceDto.getId(), approvalInstanceDto.getStorageBlobDTOs());
sendApproveNotice(approvalInstanceDto, approveProcessConfigNodeUtils.getCurrentPendingTasks(approvalInstanceDto.getId()));
+ return true;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean update(ApprovalInstanceDto approvalInstanceDto) {
+ if (approvalInstanceDto == null || approvalInstanceDto.getId() == null) {
+ return false;
+ }
+ boolean updated = this.updateById(approvalInstanceDto);
+ if (!updated) {
+ return false;
+ }
+ fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVAL_INSTANCE, approvalInstanceDto.getId(), approvalInstanceDto.getStorageBlobDTOs());
return true;
}
@@ -147,6 +173,7 @@
if (ids == null || ids.isEmpty()) {
return false;
}
+ fileUtil.deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordIds(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVAL_INSTANCE, ids);
int instanceRows = approvalInstanceMapper.update(
null,
@@ -221,11 +248,10 @@
approveAction,
approvalInstanceDto.getApproveComment()
);
-
+ //瀹℃壒鎷掔粷鐨勫鐞�
if ("REJECTED".equals(approveAction)) {
return rejectCurrentNode(instance, currentNode, now);
}
-
if (!approveProcessConfigNodeUtils.canProceedToNextLevel(instance.getId(), currentNode.getApproveType())) {
return R.ok("瀹℃壒鎴愬姛锛岀瓑寰呭叾浠栧鎵逛汉澶勭悊");
}
@@ -278,6 +304,20 @@
instance.setStatus("REJECTED");
instance.setFinishTime(now);
this.updateById(instance);
+ // 椹冲洖瀵瑰簲鐨勪紒涓氭柊闂伙紝 宸梾鎶ラ攢
+ if (instance.getBusinessType().equals(TypeEnums.ENTERPRISE_NEWS_APPROVAL.getCode())) {
+ enterpriseNewsMapper.update(
+ new LambdaUpdateWrapper<EnterpriseNews>()
+ .eq(EnterpriseNews::getId, instance.getBusinessId())
+ .set(EnterpriseNews::getStatus, "REJECTED")
+ );
+ }else if (instance.getBusinessType().equals(TypeEnums.TRAVEL_REIMBURSEMENT_APPROVAL.getCode())||instance.getBusinessType().equals(TypeEnums.EXPENSE_APPROVAL.getCode())) {
+ finReimbursementMapper.update(
+ new LambdaUpdateWrapper<FinReimbursement>()
+ .eq(FinReimbursement::getId, instance.getBusinessId())
+ .set(FinReimbursement::getBillStatus, "REJECTED")
+ );
+ }
return R.ok("瀹℃壒宸查┏鍥�");
}
@@ -292,6 +332,33 @@
closePendingTasks(instance.getId(), currentNode.getId());
int nextLevel = currentNode.getLevelNo() + 1;
+ ApprovalInstanceNode nextInstanceNode = approvalInstanceNodeService.getOne(
+ new LambdaQueryWrapper<ApprovalInstanceNode>()
+ .eq(ApprovalInstanceNode::getInstanceId, instance.getId())
+ .eq(ApprovalInstanceNode::getLevelNo, nextLevel)
+ .eq(ApprovalInstanceNode::getDeleted, 0)
+ .orderByAsc(ApprovalInstanceNode::getId)
+ .last("LIMIT 1")
+ );
+
+ if (nextInstanceNode != null) {
+ if (!activateNextInstanceNode(nextInstanceNode.getId(), now)) {
+ return R.ok("涓嬩竴瀹℃壒鑺傜偣宸茶婵�娲伙紝璇峰埛鏂板悗閲嶈瘯");
+ }
+ instance.setCurrentLevel(nextLevel);
+ instance.setStatus("PENDING");
+ this.updateById(instance);
+ List<ApprovalTask> nextTasks = approvalTaskService.list(
+ Wrappers.<ApprovalTask>lambdaQuery()
+ .eq(ApprovalTask::getInstanceId, instance.getId())
+ .eq(ApprovalTask::getNodeId, nextInstanceNode.getId())
+ .eq(ApprovalTask::getTaskStatus, "PENDING")
+ .eq(ApprovalTask::getDeleted, 0)
+ );
+ sendApproveNotice(instance, nextTasks);
+ return R.ok("瀹℃壒鎴愬姛锛屽凡娴佽浆鍒颁笅涓�鑺傜偣");
+ }
+
ApprovalTemplateNode nextTemplateNode = approvalTemplateNodeService.getOne(
new LambdaQueryWrapper<ApprovalTemplateNode>()
.eq(ApprovalTemplateNode::getTemplateId, instance.getTemplateId())
@@ -314,6 +381,17 @@
approveProcessConfigNodeUtils.createCurrentNodeAndTasks(instance, false);
sendApproveNotice(instance, approveProcessConfigNodeUtils.getCurrentPendingTasks(approvalInstanceDto.getId()));
return R.ok("瀹℃壒鎴愬姛锛屽凡娴佽浆鍒颁笅涓�鑺傜偣");
+ }
+
+ private boolean activateNextInstanceNode(Long nodeId, LocalDateTime now) {
+ return approvalInstanceNodeService.update(
+ Wrappers.<ApprovalInstanceNode>lambdaUpdate()
+ .eq(ApprovalInstanceNode::getId, nodeId)
+ .eq(ApprovalInstanceNode::getStatus, "WAITING")
+ .eq(ApprovalInstanceNode::getDeleted, 0)
+ .set(ApprovalInstanceNode::getStatus, "PENDING")
+ .set(ApprovalInstanceNode::getStartTime, now)
+ );
}
private boolean updateCurrentNodeStatus(Long nodeId, String targetStatus, LocalDateTime now) {
@@ -343,9 +421,40 @@
handleShippingApprovalFinished(instance, status);
return;
}
+ if (TypeEnums.TRAVEL_REIMBURSEMENT_APPROVAL.getCode().equals(businessType)
+ || TypeEnums.EXPENSE_APPROVAL.getCode().equals(businessType)) {
+ handleReimbursementApprovalFinished(instance, status);
+ return;
+ }
+ // 椹冲洖瀵瑰簲鐨勪紒涓氭柊闂汇�佸姞鐝敵璇枫�佽鍋囩敵璇峰彲浠ラ噸鏂板啀鎻愪氦
+ if (TypeEnums.LEAVE_APPROVAL.getCode().equals(businessType)
+ || TypeEnums.OVERTIME_APPROVAL.getCode().equals(businessType)) {
+ handleHolidayApplicationApprovalFinished(instance, status);
+ return;
+ }
if (TypeEnums.ENTERPRISE_NEWS_APPROVAL.getCode().equals(businessType)) {
handleNewsApprovalFinished(instance, status);
}
+ }
+
+ private void handleReimbursementApprovalFinished(ApprovalInstance instance, String status) {
+ if (instance == null || instance.getBusinessId() == null) {
+ return;
+ }
+
+ FinReimbursement reimbursement = new FinReimbursement();
+ reimbursement.setId(instance.getBusinessId());
+ if ("APPROVED".equals(status)) {
+ reimbursement.setBillStatus("APPROVED");
+ reimbursement.setApprovedTime(instance.getFinishTime());
+ } else if ("REJECTED".equals(status)) {
+ reimbursement.setBillStatus("REJECTED");
+ } else if ("PENDING".equals(status)) {
+ reimbursement.setBillStatus("IN_APPROVAL");
+ } else {
+ return;
+ }
+ finReimbursementMapper.updateById(reimbursement);
}
private void handleNewsApprovalFinished(ApprovalInstance instance, String status) {
@@ -356,14 +465,32 @@
enterpriseNews.setId(instance.getBusinessId());
if ("APPROVED".equals(status)) {
enterpriseNews.setStatus(ENTERPRISE_NEWS_STATUS_PUBLISHED);
- enterpriseNewsService.updateById(enterpriseNews);
+ enterpriseNewsMapper.updateById(enterpriseNews);
sendEnterpriseNewsNotice(instance.getBusinessId());
return;
}
if ("REJECTED".equals(status)) {
enterpriseNews.setStatus(ENTERPRISE_NEWS_STATUS_REJECTED);
- enterpriseNewsService.updateById(enterpriseNews);
+ enterpriseNewsMapper.updateById(enterpriseNews);
}
+ }
+
+ private void handleHolidayApplicationApprovalFinished(ApprovalInstance instance, String status) {
+ if (instance == null || instance.getBusinessId() == null) {
+ return;
+ }
+ HolidayApplication holidayApplication = new HolidayApplication();
+ holidayApplication.setId(instance.getBusinessId());
+ if ("APPROVED".equals(status)) {
+ holidayApplication.setStatus("APPROVED");
+ } else if ("REJECTED".equals(status)) {
+ holidayApplication.setStatus("REJECTED");
+ } else if ("PENDING".equals(status)) {
+ holidayApplication.setStatus("PENDING");
+ } else {
+ return;
+ }
+ holidayApplicationMapper.updateById(holidayApplication);
}
private void handlePurchaseApprovalFinished(ApprovalInstance instance, String status) {
@@ -449,7 +576,7 @@
}
private List<ApprovalTask> createNodeAndTasks(ApprovalInstance instance, ApprovalTemplateNode templateNode) {
- List<ApprovalTemplateNodeApprover> approvers = approvalTemplateNodeApproverService.list(
+ List<ApprovalTemplateNodeApprover> approvers = approvalTemplateNodeApproverMapper.selectList(
new LambdaQueryWrapper<ApprovalTemplateNodeApprover>()
.eq(ApprovalTemplateNodeApprover::getTemplateId, instance.getTemplateId())
.eq(ApprovalTemplateNodeApprover::getNodeId, templateNode.getId())
@@ -507,7 +634,7 @@
}
private void sendEnterpriseNewsNotice(Long newsId) {
- EnterpriseNews enterpriseNews = enterpriseNewsService.getById(newsId);
+ EnterpriseNews enterpriseNews = enterpriseNewsMapper.selectById(newsId);
if (enterpriseNews == null) {
return;
}
@@ -537,7 +664,7 @@
.collect(Collectors.toList());
}
if ("dept".equals(readScope)) {
- List<Long> deptIds = enterpriseNewsScopeDeptService.list(
+ List<Long> deptIds = enterpriseNewsScopeDeptMapper.selectList(
new LambdaQueryWrapper<EnterpriseNewsScopeDept>()
.eq(EnterpriseNewsScopeDept::getNewsId, enterpriseNews.getId()))
.stream()
@@ -551,7 +678,7 @@
return sysUserDeptMapper.selectDistinctUserIdsByDeptIds(collectDeptIdsWithChildren(deptIds));
}
if ("custom".equals(readScope)) {
- return enterpriseNewsScopeUserService.list(
+ return enterpriseNewsScopeUserMapper.selectList(
new LambdaQueryWrapper<EnterpriseNewsScopeUser>()
.eq(EnterpriseNewsScopeUser::getNewsId, enterpriseNews.getId()))
.stream()
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateServiceImpl.java
index db1f378..af5a774 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateServiceImpl.java
@@ -107,7 +107,6 @@
new LambdaQueryWrapper<ApprovalTemplate>()
.eq(ApprovalTemplate::getDeleted, 0)
.eq(ApprovalTemplate::getEnabled, 1)
- .eq(type != null, ApprovalTemplate::getTemplateType, type)
.orderByDesc(ApprovalTemplate::getTemplateType)
.orderByDesc(ApprovalTemplate::getId)
);
diff --git a/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementDetailServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementDetailServiceImpl.java
new file mode 100644
index 0000000..1897440
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementDetailServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.approve.service.impl;
+
+import com.ruoyi.approve.pojo.FinReimbursementDetail;
+import com.ruoyi.approve.mapper.FinReimbursementDetailMapper;
+import com.ruoyi.approve.service.FinReimbursementDetailService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曟槑缁嗚〃 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:38
+ */
+@Service
+public class FinReimbursementDetailServiceImpl extends ServiceImpl<FinReimbursementDetailMapper, FinReimbursementDetail> implements FinReimbursementDetailService {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementServiceImpl.java
new file mode 100644
index 0000000..a69bb76
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementServiceImpl.java
@@ -0,0 +1,537 @@
+package com.ruoyi.approve.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.approve.bean.dto.ApprovalInstanceDto;
+import com.ruoyi.approve.bean.dto.ApprovalTemplateNodeApproverDto;
+import com.ruoyi.approve.bean.dto.ApprovalTemplateNodeDto;
+import com.ruoyi.approve.bean.dto.FinReimbursementDto;
+import com.ruoyi.approve.bean.vo.FinReimbursementVo;
+import com.ruoyi.approve.mapper.ApprovalInstanceMapper;
+import com.ruoyi.approve.mapper.FinReimbursementDetailMapper;
+import com.ruoyi.approve.mapper.FinReimbursementMapper;
+import com.ruoyi.approve.mapper.FinReimbursementTravelMapper;
+import com.ruoyi.approve.pojo.*;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.utils.FileUtil;
+import com.ruoyi.approve.service.*;
+import com.ruoyi.common.enums.TypeEnums;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.OrderUtils;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.project.system.service.ISysNoticeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 鎶ラ攢鍗曚富琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:15
+ */
+@Service
+@RequiredArgsConstructor
+public class FinReimbursementServiceImpl extends ServiceImpl<FinReimbursementMapper, FinReimbursement> implements FinReimbursementService {
+
+ private static final String BILL_STATUS_DRAFT = "DRAFT";
+ private static final String BILL_STATUS_IN_APPROVAL = "IN_APPROVAL";
+ private static final String NODE_STATUS_WAITING = "WAITING";
+
+ private final ApprovalInstanceMapper approvalInstanceMapper;
+ private final ApprovalInstanceService approvalInstanceService;
+ private final ApprovalInstanceNodeService approvalInstanceNodeService;
+ private final ApprovalTaskService approvalTaskService;
+ private final ApprovalRecordService approvalRecordService;
+ private final FinReimbursementMapper finReimbursementMapper;
+ private final FinReimbursementTravelMapper finReimbursementTravelMapper;
+ private final FinReimbursementDetailMapper finReimbursementDetailMapper;
+ private final FileUtil fileUtil;
+ private final ISysNoticeService sysNoticeService;
+ @Override
+ public IPage<FinReimbursementVo> listPage(FinReimbursementDto finReimbursementDto, Page<FinReimbursementVo> page) {
+ IPage<FinReimbursementVo> finReimbursementVoIPage = finReimbursementMapper.listPage(finReimbursementDto, page);
+ finReimbursementVoIPage.getRecords().forEach(vo -> {
+ vo.setStorageBlobVOList(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.FIN_REIMBURSEMENT, vo.getId()));
+ });
+
+ return finReimbursementVoIPage;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean add(FinReimbursementDto finReimbursementDto) {
+ String billStatus = validateAddParam(finReimbursementDto);
+
+ // 鐢熸垚鎶ラ攢鍗曞彿
+ String billNo = OrderUtils.countTodayByCreateTime(finReimbursementMapper, "BXD", "bill_no");
+ List<FinReimbursementDetail> details = finReimbursementDto.getDetails();
+ BigDecimal totalAmount = details.stream()
+ .map(FinReimbursementDetail::getAmount)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+ FinReimbursement reimbursement = buildReimbursement(finReimbursementDto, billNo, totalAmount, billStatus);
+ // 淇濆瓨鎶ラ攢鍗曚富琛�
+ boolean saved = this.save(reimbursement);
+ if (!saved || reimbursement.getId() == null) {
+ throw new ServiceException("鏂板鎶ラ攢鍗曞け璐�");
+ }
+ Long reimbursementId = reimbursement.getId();
+
+ // 淇濆瓨宸梾鎶ラ攢鎵╁睍淇℃伅锛堟姤閿�绫诲瀷涓哄樊鏃呮姤閿�鏃讹級
+ FinReimbursementTravel travel = finReimbursementDto.getTravel();
+ if (isTravelReimbursement(finReimbursementDto.getReimbursementType())) {
+ travel.setReimbursementId(reimbursementId);
+ int travelRows = finReimbursementTravelMapper.insert(travel);
+ if (travelRows != 1) {
+ throw new ServiceException("鏂板宸梾鎶ラ攢鎵╁睍淇℃伅澶辫触");
+ }
+ }
+
+ // 淇濆瓨鎶ラ攢鍗曟槑缁�
+ for (int i = 0; i < details.size(); i++) {
+ FinReimbursementDetail detail = details.get(i);
+ detail.setId(null);
+ detail.setReimbursementId(reimbursementId);
+ detail.setRowNo(i + 1);
+ int detailRows = finReimbursementDetailMapper.insert(detail);
+ if (detailRows != 1) {
+ throw new ServiceException("鏂板鎶ラ攢鍗曟槑缁嗗け璐�");
+ }
+ }
+
+ if (BILL_STATUS_IN_APPROVAL.equals(billStatus)) {
+ startApproval(reimbursement, finReimbursementDto);
+ }
+ fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.FIN_REIMBURSEMENT, reimbursementId, finReimbursementDto.getStorageBlobDTOs());
+ return true;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean update(FinReimbursementDto finReimbursementDto) {
+ String billStatus = validateUpdateParam(finReimbursementDto);
+
+ Long reimbursementId = finReimbursementDto.getId();
+ FinReimbursement existing = finReimbursementMapper.selectById(reimbursementId);
+ if (existing == null) {
+ throw new ServiceException("鎶ラ攢鍗曚笉瀛樺湪");
+ }
+
+ // 璁$畻鏄庣粏姹囨�婚噾棰�
+ List<FinReimbursementDetail> details = finReimbursementDto.getDetails();
+ BigDecimal totalAmount = details.stream()
+ .map(FinReimbursementDetail::getAmount)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+ // 鏇存柊涓昏〃
+ FinReimbursement reimbursement = buildReimbursement(
+ finReimbursementDto,
+ existing.getBillNo(),
+ totalAmount,
+ billStatus
+ );
+ reimbursement.setId(reimbursementId);
+ int mainRows = finReimbursementMapper.updateById(reimbursement);
+ if (mainRows != 1) {
+ throw new ServiceException("鏇存柊鎶ラ攢鍗曚富琛ㄥけ璐�");
+ }
+
+ // 鏌ヨ鏁版嵁搴撲腑宸叉湁鐨勬槑缁�
+ List<FinReimbursementDetail> existingDetails = finReimbursementDetailMapper.selectList(
+ new LambdaQueryWrapper<FinReimbursementDetail>()
+ .eq(FinReimbursementDetail::getReimbursementId, reimbursementId));
+ Set<Long> existingDetailIds = existingDetails.stream()
+ .map(FinReimbursementDetail::getId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+
+ // 鏂版槑缁嗕腑鏈塈D鐨� 鈫� 鏇存柊锛涙棤ID鐨� 鈫� 鏂板
+ Set<Long> submittedDetailIds = new HashSet<>();
+ for (int i = 0; i < details.size(); i++) {
+ FinReimbursementDetail detail = details.get(i);
+ detail.setReimbursementId(reimbursementId);
+ detail.setRowNo(i + 1);
+ if (detail.getId() != null && existingDetailIds.contains(detail.getId())) {
+ finReimbursementDetailMapper.updateById(detail);
+ submittedDetailIds.add(detail.getId());
+ } else {
+ detail.setId(null);
+ finReimbursementDetailMapper.insert(detail);
+ }
+ }
+
+ // 鏁版嵁搴撲腑宸叉湁浣嗘柊鏄庣粏涓病鏈夌殑 鈫� 鍒犻櫎
+ for (Long existingId : existingDetailIds) {
+ if (!submittedDetailIds.contains(existingId)) {
+ finReimbursementDetailMapper.deleteById(existingId);
+ }
+ }
+
+ // 宸梾鎵╁睍锛氭湁鍒欐洿鏂帮紝鏃犲垯鏂板
+ FinReimbursementTravel existingTravel = finReimbursementTravelMapper.selectOne(
+ new LambdaQueryWrapper<FinReimbursementTravel>()
+ .eq(FinReimbursementTravel::getReimbursementId, reimbursementId)
+ .last("LIMIT 1"));
+ FinReimbursementTravel travel = finReimbursementDto.getTravel();
+ if (isTravelReimbursement(finReimbursementDto.getReimbursementType()) && travel != null) {
+ travel.setReimbursementId(reimbursementId);
+ if (existingTravel != null) {
+ travel.setId(existingTravel.getId());
+ finReimbursementTravelMapper.updateById(travel);
+ } else {
+ travel.setId(null);
+ finReimbursementTravelMapper.insert(travel);
+ }
+ }
+
+ resetApprovalFlow(existing.getApprovalInstanceId(), reimbursementId);
+ if (BILL_STATUS_IN_APPROVAL.equals(billStatus)) {
+ reimbursement.setApprovalInstanceId(null);
+ startApproval(reimbursement, finReimbursementDto);
+ }
+ fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.FIN_REIMBURSEMENT, reimbursementId, finReimbursementDto.getStorageBlobDTOs());
+
+ return true;
+ }
+
+ @Override
+ public FinReimbursementVo detail(Long id) {
+ if (id == null ) {
+ throw new ServiceException("鎶ラ攢鍗旾D涓嶈兘涓虹┖");
+ }
+
+ FinReimbursement reimbursement = finReimbursementMapper.selectById(id);
+ if (reimbursement == null) {
+ throw new ServiceException("鎶ラ攢鍗曚笉瀛樺湪");
+ }
+
+ FinReimbursementVo vo = new FinReimbursementVo();
+ vo.setId(reimbursement.getId());
+ vo.setBillNo(reimbursement.getBillNo());
+ vo.setReimbursementType(reimbursement.getReimbursementType());
+ vo.setExpenseType(reimbursement.getExpenseType());
+ vo.setApplicantId(reimbursement.getApplicantId());
+ vo.setApplicantCode(reimbursement.getApplicantCode());
+ vo.setApplicantName(reimbursement.getApplicantName());
+ vo.setApplicantDeptId(reimbursement.getApplicantDeptId());
+ vo.setApplicantDeptName(reimbursement.getApplicantDeptName());
+ vo.setReason(reimbursement.getReason());
+ vo.setApplyAmount(reimbursement.getApplyAmount());
+ vo.setDetailTotalAmount(reimbursement.getDetailTotalAmount());
+ vo.setPayeeName(reimbursement.getPayeeName());
+ vo.setPayeeAccount(reimbursement.getPayeeAccount());
+ vo.setPayeeBank(reimbursement.getPayeeBank());
+ vo.setApprovalInstanceId(reimbursement.getApprovalInstanceId());
+ vo.setApproveProcessId(reimbursement.getApproveProcessId());
+ vo.setBillStatus(reimbursement.getBillStatus());
+ vo.setApprovedTime(reimbursement.getApprovedTime());
+ vo.setPaidTime(reimbursement.getPaidTime());
+ vo.setAccountExpenseId(reimbursement.getAccountExpenseId());
+ vo.setRemark(reimbursement.getRemark());
+ vo.setTenantId(reimbursement.getTenantId());
+ vo.setCreateUser(reimbursement.getCreateUser());
+ vo.setCreateTime(reimbursement.getCreateTime());
+ vo.setUpdateUser(reimbursement.getUpdateUser());
+ vo.setUpdateTime(reimbursement.getUpdateTime());
+ vo.setDeptId(reimbursement.getDeptId());
+ vo.setDeleted(reimbursement.getDeleted());
+
+ vo.setDetails(finReimbursementDetailMapper.selectList(
+ new LambdaQueryWrapper<FinReimbursementDetail>()
+ .eq(FinReimbursementDetail::getReimbursementId, reimbursement.getId())
+ .orderByAsc(FinReimbursementDetail::getRowNo)
+ ));
+
+ if (isTravelReimbursement(reimbursement.getReimbursementType())) {
+ vo.setTravel(finReimbursementTravelMapper.selectOne(
+ new LambdaQueryWrapper<FinReimbursementTravel>()
+ .eq(FinReimbursementTravel::getReimbursementId, reimbursement.getId())
+ .last("LIMIT 1")
+ ));
+ }
+ vo.setStorageBlobVOList(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.FIN_REIMBURSEMENT, reimbursement.getId()));
+ //瀹℃壒璁板綍杩斿洖
+ vo.setTasks(approvalTaskService.list(new LambdaQueryWrapper<ApprovalTask>().eq(ApprovalTask::getInstanceId, reimbursement.getApprovalInstanceId())));
+ vo.setRecords(approvalRecordService.list(new LambdaQueryWrapper<ApprovalRecord>().eq(ApprovalRecord::getInstanceId, reimbursement.getApprovalInstanceId())));
+ return vo;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean delete(List<Long> ids) {
+ fileUtil.deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordIds(ApplicationTypeEnum.FILE, RecordTypeEnum.FIN_REIMBURSEMENT, ids);
+ //鍏堝垹闄ゆ槑缁�
+ finReimbursementDetailMapper.delete(new LambdaQueryWrapper<FinReimbursementDetail>().in(FinReimbursementDetail::getReimbursementId, ids));
+ //鍒犻櫎宸梾
+ finReimbursementTravelMapper.delete(new LambdaQueryWrapper<FinReimbursementTravel>().in(FinReimbursementTravel::getReimbursementId, ids));
+ //鍒犻櫎涓昏〃
+ int rows = finReimbursementMapper.delete(new LambdaQueryWrapper<FinReimbursement>().in(FinReimbursement::getId, ids));
+ return rows == ids.size();
+ }
+
+ private String validateUpdateParam(FinReimbursementDto finReimbursementDto) {
+ if (finReimbursementDto == null || finReimbursementDto.getId() == null) {
+ throw new ServiceException("鎶ラ攢鍗旾D涓嶈兘涓虹┖");
+ }
+ if (finReimbursementDto.getReimbursementType() == null) {
+ throw new ServiceException("鎶ラ攢绫诲瀷涓嶈兘涓虹┖");
+ }
+ String billStatus = normalizeBillStatus(finReimbursementDto.getBillStatus());
+ if (billStatus == null) {
+ throw new ServiceException("鍗曟嵁鐘舵�佸彧鏀寔 DRAFT 鎴� IN_APPROVAL");
+ }
+ if (BILL_STATUS_IN_APPROVAL.equals(billStatus)) {
+ validateApprovalNodes(finReimbursementDto.getNodes());
+ }
+ List<FinReimbursementDetail> details = finReimbursementDto.getDetails();
+ if (details == null || details.isEmpty()) {
+ throw new ServiceException("鎶ラ攢鍗曟槑缁嗕笉鑳戒负绌�");
+ }
+ for (FinReimbursementDetail detail : details) {
+ if (detail == null) {
+ throw new ServiceException("鎶ラ攢鍗曟槑缁嗕笉鑳戒负绌�");
+ }
+ if (detail.getAmount() == null || detail.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
+ throw new ServiceException("鎶ラ攢鍗曟槑缁嗛噾棰濆繀椤诲ぇ浜�0");
+ }
+ }
+ if (isTravelReimbursement(finReimbursementDto.getReimbursementType()) && finReimbursementDto.getTravel() == null) {
+ throw new ServiceException("宸梾鎶ラ攢蹇呴』濉啓宸梾鎵╁睍淇℃伅");
+ }
+ if (!isTravelReimbursement(finReimbursementDto.getReimbursementType()) && finReimbursementDto.getTravel() != null) {
+ throw new ServiceException("闈炲樊鏃呮姤閿�涓嶅厑璁稿~鍐欏樊鏃呮墿灞曚俊鎭�");
+ }
+ return billStatus;
+ }
+
+ private String validateAddParam(FinReimbursementDto finReimbursementDto) {
+ if (finReimbursementDto == null) {
+ throw new ServiceException("鎶ラ攢鍗曟暟鎹笉鑳戒负绌�");
+ }
+ if (finReimbursementDto.getReimbursementType() == null) {
+ throw new ServiceException("鎶ラ攢绫诲瀷涓嶈兘涓虹┖");
+ }
+ String billStatus = normalizeBillStatus(finReimbursementDto.getBillStatus());
+ if (billStatus == null) {
+ throw new ServiceException("鍗曟嵁鐘舵�佸彧鏀寔 DRAFT 鎴� IN_APPROVAL");
+ }
+ if (BILL_STATUS_IN_APPROVAL.equals(billStatus)) {
+ validateApprovalNodes(finReimbursementDto.getNodes());
+ }
+ List<FinReimbursementDetail> details = finReimbursementDto.getDetails();
+ if (details == null || details.isEmpty()) {
+ throw new ServiceException("鎶ラ攢鍗曟槑缁嗕笉鑳戒负绌�");
+ }
+ for (FinReimbursementDetail detail : details) {
+ if (detail == null) {
+ throw new ServiceException("鎶ラ攢鍗曟槑缁嗕笉鑳戒负绌�");
+ }
+ if (detail.getAmount() == null || detail.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
+ throw new ServiceException("鎶ラ攢鍗曟槑缁嗛噾棰濆繀椤诲ぇ浜�0");
+ }
+ }
+ if (isTravelReimbursement(finReimbursementDto.getReimbursementType()) && finReimbursementDto.getTravel() == null) {
+ throw new ServiceException("宸梾鎶ラ攢蹇呴』濉啓宸梾鎵╁睍淇℃伅");
+ }
+ if (!isTravelReimbursement(finReimbursementDto.getReimbursementType()) && finReimbursementDto.getTravel() != null) {
+ throw new ServiceException("闈炲樊鏃呮姤閿�涓嶅厑璁稿~鍐欏樊鏃呮墿灞曚俊鎭�");
+ }
+ return billStatus;
+ }
+
+ private FinReimbursement buildReimbursement(FinReimbursementDto finReimbursementDto, String billNo, BigDecimal totalAmount, String billStatus) {
+ FinReimbursement reimbursement = new FinReimbursement();
+ reimbursement.setId(null);
+ reimbursement.setBillNo(billNo);
+ reimbursement.setReimbursementType(finReimbursementDto.getReimbursementType());
+ reimbursement.setExpenseType(finReimbursementDto.getExpenseType());
+ reimbursement.setApplicantId(finReimbursementDto.getApplicantId());
+ reimbursement.setApplicantCode(finReimbursementDto.getApplicantCode());
+ reimbursement.setApplicantName(finReimbursementDto.getApplicantName());
+ reimbursement.setApplicantDeptId(finReimbursementDto.getApplicantDeptId());
+ reimbursement.setApplicantDeptName(finReimbursementDto.getApplicantDeptName());
+ reimbursement.setReason(finReimbursementDto.getReason());
+ reimbursement.setApplyAmount(finReimbursementDto.getApplyAmount());
+ reimbursement.setDetailTotalAmount(totalAmount);
+ reimbursement.setPayeeName(finReimbursementDto.getPayeeName());
+ reimbursement.setPayeeAccount(finReimbursementDto.getPayeeAccount());
+ reimbursement.setPayeeBank(finReimbursementDto.getPayeeBank());
+ reimbursement.setRemark(finReimbursementDto.getRemark());
+ reimbursement.setTenantId(finReimbursementDto.getTenantId());
+ reimbursement.setApproveProcessId(null);
+ reimbursement.setBillStatus(billStatus);
+ return reimbursement;
+ }
+
+ private void startApproval(FinReimbursement reimbursement, FinReimbursementDto finReimbursementDto) {
+ Long businessType = resolveBusinessType(finReimbursementDto.getReimbursementType());
+ ApprovalInstanceDto approvalInstanceDto = new ApprovalInstanceDto();
+ approvalInstanceDto.setInstanceNo(OrderUtils.countTodayByCreateTime(approvalInstanceMapper, "SP", "instance_no"));
+ approvalInstanceDto.setBusinessId(reimbursement.getId());
+ approvalInstanceDto.setTemplateId(null);
+ approvalInstanceDto.setTemplateName(TypeEnums.getLabelByValue(businessType) + "瀹℃壒");
+ approvalInstanceDto.setBusinessType(businessType);
+ approvalInstanceDto.setTitle("鎶ラ攢鍗曞彿锛�" + reimbursement.getBillNo());
+ approvalInstanceDto.setApplicantId(reimbursement.getApplicantId() != null ? reimbursement.getApplicantId() : SecurityUtils.getUserId());
+ approvalInstanceDto.setApplicantName(reimbursement.getApplicantName() != null ? reimbursement.getApplicantName() : SecurityUtils.getLoginUser().getNickName());
+ approvalInstanceDto.setApplyTime(LocalDateTime.now());
+ approvalInstanceDto.setStatus("PENDING");
+ approvalInstanceDto.setCurrentLevel(1);
+
+ boolean approvalSaved = approvalInstanceService.save(approvalInstanceDto);
+ if (!approvalSaved || approvalInstanceDto.getId() == null) {
+ throw new ServiceException("鍙戣捣瀹℃壒澶辫触");
+ }
+ List<ApprovalTask> firstTasks = createApprovalNodes(approvalInstanceDto, finReimbursementDto.getNodes());
+ sendApproveNotice(approvalInstanceDto, firstTasks);
+
+ FinReimbursement update = new FinReimbursement();
+ update.setId(reimbursement.getId());
+ update.setApprovalInstanceId(approvalInstanceDto.getId());
+ update.setBillStatus(BILL_STATUS_IN_APPROVAL);
+ int rows = finReimbursementMapper.updateById(update);
+ if (rows != 1) {
+ throw new ServiceException("鍥炲~瀹℃壒瀹炰緥澶辫触");
+ }
+ }
+
+ private List<ApprovalTask> createApprovalNodes(ApprovalInstanceDto approvalInstanceDto, List<ApprovalTemplateNodeDto> nodes) {
+ List<ApprovalTask> firstTasks = Collections.emptyList();
+ for (int i = 0; i < nodes.size(); i++) {
+ ApprovalTemplateNodeDto nodeDto = nodes.get(i);
+ ApprovalInstanceNode instanceNode = new ApprovalInstanceNode();
+ instanceNode.setInstanceId(approvalInstanceDto.getId());
+ instanceNode.setLevelNo(nodeDto.getLevelNo());
+ instanceNode.setApproveType(nodeDto.getApproveType());
+ instanceNode.setStatus(i == 0 ? "PENDING" : NODE_STATUS_WAITING);
+ instanceNode.setStartTime(i == 0 ? LocalDateTime.now() : null);
+ instanceNode.setDeleted((byte) 0);
+ approvalInstanceNodeService.save(instanceNode);
+
+ List<ApprovalTask> tasks = nodeDto.getApprovers().stream().map(approver -> {
+ ApprovalTask task = new ApprovalTask();
+ task.setInstanceId(approvalInstanceDto.getId());
+ task.setNodeId(instanceNode.getId());
+ task.setLevelNo(instanceNode.getLevelNo());
+ task.setApproverId(approver.getApproverId());
+ task.setApproverName(approver.getApproverName());
+ task.setTaskStatus("PENDING");
+ task.setIsRead((byte) 0);
+ task.setDeleted((byte) 0);
+ return task;
+ }).collect(Collectors.toList());
+ approvalTaskService.saveBatch(tasks);
+
+ if (i == 0) {
+ firstTasks = tasks;
+ ApprovalRecord record = new ApprovalRecord();
+ record.setInstanceId(approvalInstanceDto.getId());
+ record.setNodeId(instanceNode.getId());
+ record.setOperatorId(approvalInstanceDto.getApplicantId());
+ record.setOperatorName(approvalInstanceDto.getApplicantName());
+ record.setAction("SUBMIT");
+ record.setComment("鍙戣捣瀹℃壒");
+ record.setDeleted((byte) 0);
+ approvalRecordService.save(record);
+ }
+ }
+ return firstTasks;
+ }
+
+ private void validateApprovalNodes(List<ApprovalTemplateNodeDto> nodes) {
+ if (nodes == null || nodes.isEmpty()) {
+ throw new ServiceException("鎻愪氦瀹℃壒鏃跺鎵硅妭鐐逛笉鑳戒负绌�");
+ }
+ for (int i = 0; i < nodes.size(); i++) {
+ ApprovalTemplateNodeDto node = nodes.get(i);
+ if (node == null) {
+ throw new ServiceException("瀹℃壒鑺傜偣涓嶈兘涓虹┖");
+ }
+ if (node.getLevelNo() == null) {
+ node.setLevelNo(i + 1);
+ }
+ if (!StringUtils.hasText(node.getApproveType())) {
+ throw new ServiceException("瀹℃壒鑺傜偣瀹℃壒鏂瑰紡涓嶈兘涓虹┖");
+ }
+ List<ApprovalTemplateNodeApproverDto> approvers = node.getApprovers();
+ if (approvers == null || approvers.isEmpty()) {
+ throw new ServiceException("瀹℃壒鑺傜偣瀹℃壒浜轰笉鑳戒负绌�");
+ }
+ for (ApprovalTemplateNodeApproverDto approver : approvers) {
+ if (approver == null || approver.getApproverId() == null) {
+ throw new ServiceException("瀹℃壒浜轰笉鑳戒负绌�");
+ }
+ }
+ }
+ }
+
+ private void sendApproveNotice(ApprovalInstanceDto instance, List<ApprovalTask> tasks) {
+ if (instance == null || tasks == null || tasks.isEmpty()) {
+ return;
+ }
+ List<Long> approverIds = tasks.stream()
+ .map(ApprovalTask::getApproverId)
+ .filter(id -> id != null && id > 0)
+ .distinct()
+ .collect(Collectors.toList());
+ if (approverIds.isEmpty()) {
+ return;
+ }
+ String title = "鎶ラ攢瀹℃壒";
+ String message = "瀹℃壒鍗曞彿 " + instance.getInstanceNo() + " 闇�瑕佹偍瀹℃壒";
+ String jumpPath = "/approvalInstance?id=" + instance.getId();
+ sysNoticeService.simpleNoticeByUser(title, message, approverIds, jumpPath);
+ }
+
+ private void resetApprovalFlow(Long approvalInstanceId, Long reimbursementId) {
+ if (approvalInstanceId == null) {
+ return;
+ }
+ approvalInstanceService.delete(Collections.singletonList(approvalInstanceId));
+ int rows = finReimbursementMapper.update(
+ null,
+ Wrappers.<FinReimbursement>lambdaUpdate()
+ .eq(FinReimbursement::getId, reimbursementId)
+ .set(FinReimbursement::getApprovalInstanceId, null)
+ );
+ if (rows != 1) {
+ throw new ServiceException("閲嶇疆瀹℃壒娴佺▼澶辫触");
+ }
+ }
+
+ private Long resolveBusinessType(Byte reimbursementType) {
+ return isTravelReimbursement(reimbursementType)
+ ? TypeEnums.TRAVEL_REIMBURSEMENT_APPROVAL.getCode()
+ : TypeEnums.EXPENSE_APPROVAL.getCode();
+ }
+
+ private String normalizeBillStatus(String billStatus) {
+ if (billStatus == null) {
+ return BILL_STATUS_DRAFT;
+ }
+ String normalized = billStatus.trim().toUpperCase();
+ if (BILL_STATUS_DRAFT.equals(normalized) || BILL_STATUS_IN_APPROVAL.equals(normalized)) {
+ return normalized;
+ }
+ return null;
+ }
+
+ private boolean isTravelReimbursement(Byte reimbursementType) {
+ return Byte.valueOf((byte) 1).equals(reimbursementType);
+ }
+}
diff --git a/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementTravelServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementTravelServiceImpl.java
new file mode 100644
index 0000000..3329f9a
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/impl/FinReimbursementTravelServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.approve.service.impl;
+
+import com.ruoyi.approve.pojo.FinReimbursementTravel;
+import com.ruoyi.approve.mapper.FinReimbursementTravelMapper;
+import com.ruoyi.approve.service.FinReimbursementTravelService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 宸梾鎶ラ攢鎵╁睍琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-21 09:56:47
+ */
+@Service
+public class FinReimbursementTravelServiceImpl extends ServiceImpl<FinReimbursementTravelMapper, FinReimbursementTravel> implements FinReimbursementTravelService {
+
+}
diff --git a/src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java b/src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java
index 073a798..6613d3e 100644
--- a/src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java
+++ b/src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java
@@ -204,8 +204,10 @@
SALES_REFUND_AMOUNT_ORDER("sales_refund_amount_order"),
SALES_RECEIPT_RETURN("sales_receipt_return"),
ACCOUNT_EXPENSE("account_expense"),
+ FIN_REIMBURSEMENT("fin_reimbursement"),
FIN_VOUCHER("fin_voucher"),
ACCOUNT_FILE("account_file"),
+ ENTERPRISE_NEWS("enterprise_news"),
APPROVAL_INSTANCE("approval_instance");
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/dto/EnterpriseNewsDto.java b/src/main/java/com/ruoyi/collaborativeApproval/dto/EnterpriseNewsDto.java
index 3cde773..108cf66 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/dto/EnterpriseNewsDto.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/dto/EnterpriseNewsDto.java
@@ -1,5 +1,6 @@
package com.ruoyi.collaborativeApproval.dto;
+import com.ruoyi.basic.dto.StorageBlobDTO;
import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
import lombok.Data;
@@ -19,4 +20,7 @@
private String createTimeStart;
private String createTimeEnd;
+
+ private List<StorageBlobDTO> storageBlobDTOs;
+
}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsServiceImpl.java b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsServiceImpl.java
index 2cf7fae..cb155fe 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsServiceImpl.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsServiceImpl.java
@@ -10,6 +10,9 @@
import com.ruoyi.approve.pojo.ApprovalTask;
import com.ruoyi.approve.pojo.ApprovalTemplate;
import com.ruoyi.approve.utils.ApproveProcessConfigNodeUtils;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.utils.FileUtil;
import com.ruoyi.collaborativeApproval.dto.EnterpriseNewsDto;
import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsMapper;
import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
@@ -72,10 +75,15 @@
private final ApprovalTemplateMapper approvalTemplateMapper;
private final ApproveProcessConfigNodeUtils approveProcessConfigNodeUtils;
private final ISysNoticeService sysNoticeService;
+ private final FileUtil fileUtil;
@Override
public IPage<EnterpriseNewsVo> listPage(Page<EnterpriseNewsVo> page, EnterpriseNewsDto enterpriseNewsDto) {
- return enterpriseNewsMapper.listPage(page, enterpriseNewsDto);
+ IPage<EnterpriseNewsVo> enterpriseNewsVoIPage = enterpriseNewsMapper.listPage(page, enterpriseNewsDto);
+ enterpriseNewsVoIPage.getRecords().forEach(enterpriseNewsVo -> {
+ enterpriseNewsVo.setStorageBlobDTOs(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.ENTERPRISE_NEWS, enterpriseNewsVo.getId()));
+ });
+ return enterpriseNewsVoIPage;
}
@Override
@@ -107,6 +115,8 @@
if (STATUS_PENDING.equals(enterpriseNews.getStatus())) {
startEnterpriseNewsApproval(enterpriseNews, enterpriseNewsDto);
}
+ //娣诲姞闄勪欢
+ fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.ENTERPRISE_NEWS, enterpriseNews.getId(), enterpriseNewsDto.getStorageBlobDTOs());
return true;
}
@@ -148,7 +158,7 @@
clearReadScopeRelations(enterpriseNews.getId());
saveReadScopeRelations(enterpriseNews.getId(), readScope, deptIds, userIds);
-
+ fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.ENTERPRISE_NEWS, enterpriseNews.getId(), enterpriseNewsDto.getStorageBlobDTOs());
if (STATUS_PENDING.equals(enterpriseNews.getStatus())) {
startEnterpriseNewsApproval(enterpriseNews, enterpriseNewsDto);
}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/vo/EnterpriseNewsVo.java b/src/main/java/com/ruoyi/collaborativeApproval/vo/EnterpriseNewsVo.java
index ef40e65..66123b9 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/vo/EnterpriseNewsVo.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/vo/EnterpriseNewsVo.java
@@ -1,10 +1,15 @@
package com.ruoyi.collaborativeApproval.vo;
+import com.ruoyi.basic.dto.StorageBlobVO;
import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
import lombok.Data;
+
+import java.util.List;
@Data
public class EnterpriseNewsVo extends EnterpriseNews {
private String createUserName;
+
+ private List<StorageBlobVO> storageBlobDTOs;
}
diff --git a/src/main/resources/mapper/approve/FinReimbursementDetailMapper.xml b/src/main/resources/mapper/approve/FinReimbursementDetailMapper.xml
new file mode 100644
index 0000000..f8a67bb
--- /dev/null
+++ b/src/main/resources/mapper/approve/FinReimbursementDetailMapper.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.approve.mapper.FinReimbursementDetailMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.approve.pojo.FinReimbursementDetail">
+ <id column="id" property="id" />
+ <result column="reimbursement_id" property="reimbursementId" />
+ <result column="row_no" property="rowNo" />
+ <result column="invoice_date" property="invoiceDate" />
+ <result column="expense_category" property="expenseCategory" />
+ <result column="amount" property="amount" />
+ <result column="description" property="description" />
+ <result column="invoice_no" property="invoiceNo" />
+ <result column="invoice_type" property="invoiceType" />
+ <result column="invoice_amount" property="invoiceAmount" />
+ <result column="tax_rate" property="taxRate" />
+ <result column="tax_amount" property="taxAmount" />
+ <result column="remark" property="remark" />
+ <result column="tenant_id" property="tenantId" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_user" property="updateUser" />
+ <result column="update_time" property="updateTime" />
+ <result column="dept_id" property="deptId" />
+ <result column="deleted" property="deleted" />
+ </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/approve/FinReimbursementMapper.xml b/src/main/resources/mapper/approve/FinReimbursementMapper.xml
new file mode 100644
index 0000000..75ca038
--- /dev/null
+++ b/src/main/resources/mapper/approve/FinReimbursementMapper.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.approve.mapper.FinReimbursementMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.approve.pojo.FinReimbursement">
+ <id column="id" property="id" />
+ <result column="bill_no" property="billNo" />
+ <result column="reimbursement_type" property="reimbursementType" />
+ <result column="expense_type" property="expenseType" />
+ <result column="applicant_id" property="applicantId" />
+ <result column="applicant_code" property="applicantCode" />
+ <result column="applicant_name" property="applicantName" />
+ <result column="applicant_dept_id" property="applicantDeptId" />
+ <result column="applicant_dept_name" property="applicantDeptName" />
+ <result column="reason" property="reason" />
+ <result column="apply_amount" property="applyAmount" />
+ <result column="detail_total_amount" property="detailTotalAmount" />
+ <result column="payee_name" property="payeeName" />
+ <result column="payee_account" property="payeeAccount" />
+ <result column="payee_bank" property="payeeBank" />
+ <result column="approval_instance_id" property="approvalInstanceId" />
+ <result column="approve_process_id" property="approveProcessId" />
+ <result column="bill_status" property="billStatus" />
+ <result column="approved_time" property="approvedTime" />
+ <result column="paid_time" property="paidTime" />
+ <result column="account_expense_id" property="accountExpenseId" />
+ <result column="remark" property="remark" />
+ <result column="tenant_id" property="tenantId" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_user" property="updateUser" />
+ <result column="update_time" property="updateTime" />
+ <result column="dept_id" property="deptId" />
+ <result column="deleted" property="deleted" />
+ </resultMap>
+ <select id="listPage" resultType="com.ruoyi.approve.bean.vo.FinReimbursementVo">
+ select fin_reimbursement.*,
+ fin_reimbursement_travel.start_time ,
+ fin_reimbursement_travel.end_time
+ from
+ fin_reimbursement
+ left join fin_reimbursement_travel on fin_reimbursement.id = fin_reimbursement_travel.reimbursement_id
+ <where>
+ <if test="ew.billNo != null and ew.billNo != ''">
+ bill_no like concat('%',#{ew.billNo},'%')
+ </if>
+ <if test="ew.applicantName != null and ew.applicantName != ''">
+ and applicant_name like concat('%',#{ew.applicantName},'%')
+ </if>
+ <if test="ew.createTimeStart != null and ew.createTimeStart !=''">
+ and create_time between to_date(#{ew.createTimeStart}) and to_date(#{ew.createTimeEnd})
+ </if>
+ </where>
+ </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/approve/FinReimbursementTravelMapper.xml b/src/main/resources/mapper/approve/FinReimbursementTravelMapper.xml
new file mode 100644
index 0000000..dc42863
--- /dev/null
+++ b/src/main/resources/mapper/approve/FinReimbursementTravelMapper.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.approve.mapper.FinReimbursementTravelMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.approve.pojo.FinReimbursementTravel">
+ <id column="id" property="id" />
+ <result column="reimbursement_id" property="reimbursementId" />
+ <result column="start_time" property="startTime" />
+ <result column="end_time" property="endTime" />
+ <result column="travel_days" property="travelDays" />
+ <result column="departure_city" property="departureCity" />
+ <result column="destination_city" property="destinationCity" />
+ <result column="hotel_standard" property="hotelStandard" />
+ <result column="lodging_days" property="lodgingDays" />
+ <result column="meal_allowance" property="mealAllowance" />
+ <result column="transport_allowance" property="transportAllowance" />
+ <result column="lodging_limit" property="lodgingLimit" />
+ <result column="standard_tag" property="standardTag" />
+ <result column="within_standard" property="withinStandard" />
+ <result column="tenant_id" property="tenantId" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_user" property="updateUser" />
+ <result column="update_time" property="updateTime" />
+ <result column="dept_id" property="deptId" />
+ </resultMap>
+
+</mapper>
--
Gitblit v1.9.3