23 小时以前 eccad5a129106377a275be4f7cdc58e99e9b95d4
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package cn.iocoder.yudao.module.mes.enums.wm;
 
import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants;
 
import java.util.*;
 
/**
 * 单据状态流转校验工具
 *
 * 定义各业务单据的合法状态流转,防止非法状态跳转
 */
public class WmStatusTransitionUtils {
 
    /**
     * 通用状态常量(便于阅读)
     */
    private static final int PREPARE = MesOrderStatusConstants.PREPARE;       // 草稿
    private static final int APPROVING = MesOrderStatusConstants.APPROVING;   // 待审批/待上架/待拣货
    private static final int CONFIRMED = MesOrderStatusConstants.CONFIRMED;   // 待确认/待检测
    private static final int APPROVED = MesOrderStatusConstants.APPROVED;     // 已审批/待执行
    private static final int FINISHED = MesOrderStatusConstants.FINISHED;     // 已完成
    private static final int CANCELLED = MesOrderStatusConstants.CANCELLED;   // 已取消
    private static final int SHIPPING = 10; // 待填写运单(销售出库专用)
 
    /**
     * 状态流转规则定义
     * Key: 当前状态, Value: 允许流转到的状态集合
     */
    private static final Map<String, Map<Integer, Set<Integer>>> TRANSITION_RULES = new HashMap<>();
 
    static {
        // 采购入库单状态流转
        registerTransition("ITEM_RECEIPT",
                PREPARE, APPROVING, CANCELLED);
        registerTransition("ITEM_RECEIPT",
                APPROVING, APPROVED, CANCELLED);
        registerTransition("ITEM_RECEIPT",
                APPROVED, FINISHED, CANCELLED);
        // 已完成和已取消不允许流转
 
        // 销售出库单状态流转
        registerTransition("PRODUCT_SALES",
                PREPARE, CONFIRMED, APPROVING, CANCELLED);  // 提交时可能去待检测或待拣货
        registerTransition("PRODUCT_SALES",
                CONFIRMED, APPROVING, CANCELLED);           // OQC通过后去待拣货
        registerTransition("PRODUCT_SALES",
                APPROVING, SHIPPING, CANCELLED);            // 拣货后去待填写运单
        registerTransition("PRODUCT_SALES",
                SHIPPING, APPROVED, CANCELLED);             // 填写运单后去待执行出库
        registerTransition("PRODUCT_SALES",
                APPROVED, FINISHED, CANCELLED);             // 出库后去已完成
 
        // 转移调拨单状态流转
        registerTransition("TRANSFER",
                PREPARE, CONFIRMED, APPROVING, CANCELLED);  // 提交时可能去待确认或待上架
        registerTransition("TRANSFER",
                CONFIRMED, APPROVING, CANCELLED);           // 确认后去待上架
        registerTransition("TRANSFER",
                APPROVING, APPROVED, CANCELLED);            // 上架后去待执行
        registerTransition("TRANSFER",
                APPROVED, FINISHED, CANCELLED);             // 执行后去已完成
 
        // 生产领料单状态流转
        registerTransition("PRODUCT_ISSUE",
                PREPARE, APPROVING, CANCELLED);
        registerTransition("PRODUCT_ISSUE",
                APPROVING, APPROVED, CANCELLED);
        registerTransition("PRODUCT_ISSUE",
                APPROVED, FINISHED, CANCELLED);
 
        // 生产入库单状态流转
        registerTransition("PRODUCT_RECEIPT",
                PREPARE, APPROVING, CANCELLED);
        registerTransition("PRODUCT_RECEIPT",
                APPROVING, APPROVED, CANCELLED);
        registerTransition("PRODUCT_RECEIPT",
                APPROVED, FINISHED, CANCELLED);
 
        // 杂项入库单状态流转
        registerTransition("MISC_RECEIPT",
                PREPARE, APPROVING, CANCELLED);
        registerTransition("MISC_RECEIPT",
                APPROVING, APPROVED, CANCELLED);
        registerTransition("MISC_RECEIPT",
                APPROVED, FINISHED, CANCELLED);
 
        // 杂项出库单状态流转
        registerTransition("MISC_ISSUE",
                PREPARE, APPROVING, CANCELLED);
        registerTransition("MISC_ISSUE",
                APPROVING, APPROVED, CANCELLED);
        registerTransition("MISC_ISSUE",
                APPROVED, FINISHED, CANCELLED);
 
        // 供应商退货单状态流转
        registerTransition("RETURN_VENDOR",
                PREPARE, APPROVING, CANCELLED);
        registerTransition("RETURN_VENDOR",
                APPROVING, APPROVED, CANCELLED);
        registerTransition("RETURN_VENDOR",
                APPROVED, FINISHED, CANCELLED);
 
        // 销售退货单状态流转
        registerTransition("RETURN_SALES",
                PREPARE, APPROVING, CANCELLED);
        registerTransition("RETURN_SALES",
                APPROVING, APPROVED, CANCELLED);
        registerTransition("RETURN_SALES",
                APPROVED, FINISHED, CANCELLED);
 
        // 外协发料单状态流转
        registerTransition("OUTSOURCE_ISSUE",
                PREPARE, APPROVING, CANCELLED);
        registerTransition("OUTSOURCE_ISSUE",
                APPROVING, APPROVED, CANCELLED);
        registerTransition("OUTSOURCE_ISSUE",
                APPROVED, FINISHED, CANCELLED);
 
        // 外协入库单状态流转
        registerTransition("OUTSOURCE_RECEIPT",
                PREPARE, APPROVING, CANCELLED);
        registerTransition("OUTSOURCE_RECEIPT",
                APPROVING, APPROVED, CANCELLED);
        registerTransition("OUTSOURCE_RECEIPT",
                APPROVED, FINISHED, CANCELLED);
    }
 
    /**
     * 注册状态流转规则
     */
    private static void registerTransition(String bizType, int fromStatus, int... toStatuses) {
        TRANSITION_RULES
                .computeIfAbsent(bizType, k -> new HashMap<>())
                .computeIfAbsent(fromStatus, k -> new HashSet<>())
                .addAll(Arrays.stream(toStatuses).boxed().toList());
    }
 
    /**
     * 校验状态流转是否合法
     *
     * @param bizType    业务类型(如 ITEM_RECEIPT, PRODUCT_SALES)
     * @param fromStatus 当前状态
     * @param toStatus   目标状态
     * @return 是否允许流转
     */
    public static boolean isValidTransition(String bizType, int fromStatus, int toStatus) {
        Map<Integer, Set<Integer>> bizRules = TRANSITION_RULES.get(bizType);
        if (bizRules == null) {
            return false;
        }
        Set<Integer> allowedToStatuses = bizRules.get(fromStatus);
        return allowedToStatuses != null && allowedToStatuses.contains(toStatus);
    }
 
    /**
     * 校验状态流转,非法则抛出异常
     *
     * @param bizType      业务类型
     * @param fromStatus   当前状态
     * @param toStatus     目标状态
     * @param documentName 单据名称(用于错误提示)
     */
    public static void validateTransition(String bizType, int fromStatus, int toStatus, String documentName) {
        if (!isValidTransition(bizType, fromStatus, toStatus)) {
            throw new IllegalStateException(String.format(
                    "%s状态流转非法:不允许从状态[%d]流转到状态[%d]", documentName, fromStatus, toStatus));
        }
    }
 
    /**
     * 获取单据允许的下一步状态列表
     *
     * @param bizType    业务类型
     * @param fromStatus 当前状态
     * @return 允许流转的状态列表
     */
    public static Set<Integer> getAllowedNextStatuses(String bizType, int fromStatus) {
        Map<Integer, Set<Integer>> bizRules = TRANSITION_RULES.get(bizType);
        if (bizRules == null) {
            return Collections.emptySet();
        }
        return bizRules.getOrDefault(fromStatus, Collections.emptySet());
    }
 
}