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; } 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; } 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; } 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; } 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") 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)); } } 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 { } 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 { } 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> { } 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); } 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> { } 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; /** * ç³è¯·äººID */ @Schema(description = "ç³è¯·äººID") 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-è稿ï¼IN_APPROVAL-审æ¹ä¸ï¼APPROVED-审æ¹éè¿ï¼REJECTED-审æ¹é©³åï¼WITHDRAWN-å·²æ¤åï¼PAID-已仿¬¾ */ @Schema(description = "åæ®ç¶æï¼DRAFT-è稿ï¼IN_APPROVAL-审æ¹ä¸ï¼APPROVED-审æ¹éè¿ï¼REJECTED-审æ¹é©³åï¼WITHDRAWN-å·²æ¤åï¼PAID-已仿¬¾") private String billStatus; /** * 审æ¹éè¿æ¶é´ */ @Schema(description = "审æ¹éè¿æ¶é´") private LocalDateTime approvedTime; /** * 仿¬¾æ¶é´ */ @Schema(description = "仿¬¾æ¶é´") private LocalDateTime paidTime; /** * çæçè´¢å¡æ¯åºè®°å½IDï¼å¯¹åº account_expense.id */ @Schema(description = "çæçè´¢å¡æ¯åºè®°å½IDï¼å¯¹åº 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; } 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; /** * æ¥éåIDï¼å¯¹åº fin_reimbursement.id */ @Schema(description = "æ¥éåIDï¼å¯¹åº 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; } 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; /** * æ¥éåIDï¼å¯¹åº fin_reimbursement.id */ @Schema(description = "æ¥éåIDï¼å¯¹åº 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; } 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); 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> { } 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); } 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> { } 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() 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) ); 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 { } 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()); // æ°æç»ä¸æIDç â æ´æ°ï¼æ 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("æ¥éåIDä¸è½ä¸ºç©º"); } 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("æ¥éåIDä¸è½ä¸ºç©º"); } 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); } } 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 { } 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"); 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; } 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); } 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; } 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> 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> 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>