package com.ruoyi.project.service; import com.ruoyi.project.domain.ServiceFunddetailVO; import lombok.Data; import java.util.ArrayList; import java.util.List; /** * 专家劳务费校验结果 * * 区分两类结果: * - errors 阻断性问题:经办人不能保存、审批人不能审批通过 * - warnings 提示性问题:不阻断流程,仅提示经办人自行处理(规则 5、6) * * @author ruoyi */ @Data public class ExpertFeeCheckResult { /** 阻断性错误(超限额等) */ private List errors = new ArrayList<>(); /** 提示信息(同一专家跨项目取高、第二器官超 500 等) */ private List warnings = new ArrayList<>(); public void addError(String message) { this.errors.add(message); } public void addWarning(String message) { this.warnings.add(message); } /** 是否存在阻断性问题 */ public boolean hasError() { return !this.errors.isEmpty(); } public boolean hasWarning() { return !this.warnings.isEmpty(); } /** 错误信息拼为一行,便于接口直接返回 */ public String errorMessage() { return String.join(";", this.errors); } /** 提示信息拼为一行 */ public String warningMessage() { return String.join(";", this.warnings); } /** 错误 + 提示合并(用于前端一次性展示) */ public String allMessage() { List all = new ArrayList<>(); all.addAll(this.errors); all.addAll(this.warnings); return String.join(";", all); } /** * 校验用的明细行(把金额统一成 BigDecimal,避免后续 double 运算) */ @Data public static class DetailRow { /** 明细主键(落库后才有值) */ private Long id; private Long fundid; private Long infoid; private Long itemid; private String itemname; private String idcardno; private String servicesscopename; /** 税前金额 */ private java.math.BigDecimal amount; /** 税后金额 */ private java.math.BigDecimal taxedamount; public static DetailRow of(ServiceFunddetailVO vo) { DetailRow row = new DetailRow(); row.setId(vo.getId()); row.setFundid(vo.getFundid()); row.setInfoid(vo.getInfoid()); row.setItemid(vo.getItemid()); row.setItemname(vo.getItemname()); row.setIdcardno(vo.getIdcardno()); row.setServicesscopename(vo.getServicesscopename()); row.setAmount(toDecimal(vo.getAmount())); row.setTaxedamount(toDecimal(vo.getTaxedamount())); return row; } private static java.math.BigDecimal toDecimal(Double value) { return value == null ? java.math.BigDecimal.ZERO : java.math.BigDecimal.valueOf(value); } /** 费用说明是否包含关键字(费用说明可能为空) */ public boolean scopeContains(String keyword) { return this.servicesscopename != null && this.servicesscopename.contains(keyword); } /** * 费用说明是否包含任一关键字(费用说明可能为空)。 * *

同一场景在不同环境/年度的下拉文本不一致(如「市内」与「本市」), * 用关键字集合兼容,避免因文案差异导致限额校验静默失效。 */ public boolean scopeContainsAny(String... keywords) { if (this.servicesscopename == null || keywords == null) { return false; } for (String keyword : keywords) { if (keyword != null && this.servicesscopename.contains(keyword)) { return true; } } return false; } } }