sinake
2 天以前 194ecd2dbc3a9c7eccfe5d9809ff947715960465
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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<String> errors = new ArrayList<>();
 
    /** 提示信息(同一专家跨项目取高、第二器官超 500 等) */
    private List<String> 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<String> 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);
        }
 
        /**
         * 费用说明是否包含任一关键字(费用说明可能为空)。
         *
         * <p>同一场景在不同环境/年度的下拉文本不一致(如「市内」与「本市」),
         * 用关键字集合兼容,避免因文案差异导致限额校验静默失效。
         */
        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;
        }
    }
}