李林
2023-10-07 658d4927d468c47208fd012d9128b09249c07eff
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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
package com.chinaztt.mes.warehouse.util;
 
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.chinaztt.ifs.api.feign.IfsFeignClient;
import com.chinaztt.mes.basic.entity.Part;
import com.chinaztt.mes.basic.mapper.PartMapper;
import com.chinaztt.mes.warehouse.dto.IfsMoveLibraryDTO;
import com.chinaztt.mes.warehouse.dto.MoveLibraryBoxDTO;
import com.chinaztt.mes.warehouse.entity.FeederCertificate;
import com.chinaztt.mes.warehouse.entity.Packaging;
import com.chinaztt.mes.warehouse.entity.Stock;
import com.chinaztt.mes.warehouse.entity.StockConfigBean;
import com.chinaztt.mes.warehouse.mapper.FeederCertificateMapper;
import com.chinaztt.mes.warehouse.mapper.PackagingItemMapper;
import com.chinaztt.mes.warehouse.mapper.PackagingMapper;
import com.chinaztt.mes.warehouse.mapper.StockMapper;
import com.chinaztt.mes.warehouse.state.constant.LocationTypeStringValues;
import com.chinaztt.mes.warehouse.state.escort.constant.EscortEvents;
import com.chinaztt.ztt.admin.api.feign.RemoteParamService;
import com.chinaztt.ztt.common.core.constant.SecurityConstants;
import com.chinaztt.ztt.common.core.util.R;
import com.google.gson.Gson;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
 
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
 
/**
 * @Description : 仓库管理工具类
 * @ClassName : WareHouseUtils
 * @Author : sll
 * @Date: 2022-06-02  22:04
 */
@Service
public class WareHouseUtils {
    @Resource
    private PackagingMapper packagingMapper;
    @Resource
    private PackagingItemMapper packagingItemMapper;
    @Resource
    private StockUtils stockUtils;
    @Resource
    private StockConfigBean stockConfigBean;
    @Resource
    private IfsFeignClient ifsFeignClient;
    @Resource
    private RemoteParamService remoteParamService;
    public static final String CONTRACT = "IFS_DOMAIN";
    @Resource
    private PartMapper partMapper;
    @Resource
    private StockMapper stockMapper;
    @Resource
    private FeederCertificateMapper feederMapper;
 
    /**
     * 根据包装主表记录行id获取包装确认状态
     *
     * @param id
     * @return
     */
    public Boolean isPackConfirm(Long id) {
        Packaging packaging = packagingMapper.selectById(id);
        if (packaging == null) {
            throw new RuntimeException("包装主表id=" + id + "->异常->数据库无匹配记录");
        } else {
            return packaging.getIsConfirm();
        }
 
    }
 
    /**
     * 校验mes库位映射ifs库位的对称性
     *
     * @param moveLibraryBoxDTOList
     * @return false:不对称;true:对称
     */
    public Boolean isLocationMapSym(List<MoveLibraryBoxDTO> moveLibraryBoxDTOList) {
        for (MoveLibraryBoxDTO moveLibraryBoxDTO : moveLibraryBoxDTOList) {
            if (StringUtils.isBlank(moveLibraryBoxDTO.getStartLocationNoIfs()) ^ StringUtils.isBlank(moveLibraryBoxDTO.getArriveLocationNoIfs())) {
                return false;
            }
        }
        return true;
    }
 
    /**
     * 校验MoveLibraryBoxDTO
     *
     * @param moveLibraryBoxDTOList
     * @param id
     * @return
     */
    public R checkMoveLibraryBox(List<MoveLibraryBoxDTO> moveLibraryBoxDTOList, Long id) {
        Long itemCount = packagingItemMapper.getPackagingItemCountByPackagingId(id);
        //校验SQL查询结果
        if (moveLibraryBoxDTOList.size() != itemCount) {
            return R.failed("实际明细行数=" + moveLibraryBoxDTOList.size() + "->不等于SQL关联查询明细行数=" + itemCount);
        }
        //校验box明细行是否都存在到达库位号且到达库位为成品库位
        List<MoveLibraryBoxDTO> moveLibraryBoxDTOListFilter = moveLibraryBoxDTOList.stream().filter(o -> StringUtils.isBlank(o.getArriveLocationNo()) || !o.getArriveLocationType().equals(LocationTypeStringValues.FINISHLOCATIONCODE)).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(moveLibraryBoxDTOListFilter)) {
            return R.failed("包装明细存在记录行未指定[到达库位]");
        }
        //校验box明细行是否都存在出发库位号且出发库位是否是合格品库位
        moveLibraryBoxDTOListFilter = moveLibraryBoxDTOList.stream().filter(o -> StringUtils.isBlank(o.getStartLocationNo()) || !o.getStartLocationType().equals(LocationTypeStringValues.PRODOUTQUALIFIELDLOCATIONCODE)).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(moveLibraryBoxDTOListFilter)) {
            return R.failed("包装明细存在记录行在实时库位中未找到[出发库位]或[出发库位]为非[产出合格品库位]");
        }
 
 
        //校验库位的对称性
        if (!isLocationMapSym(moveLibraryBoxDTOList)) {
            return R.failed("mes库位映射ifs库位不对称");
        }
 
        return R.ok();
    }
 
    /**
     * 包装模块确认/取消确认后的移库
     *
     * @param moveLibraryBoxDTOList
     * @param escortEvents          COMPLETE:确认;CANCEL:取消确认
     * @param packagingId           包装主表id
     */
    public void packagingMoveLibrary(List<MoveLibraryBoxDTO> moveLibraryBoxDTOList, EscortEvents escortEvents, Long packagingId) {
        //1.mes移库
        for (MoveLibraryBoxDTO moveLibraryBoxDTO : moveLibraryBoxDTOList) {
            switch (escortEvents) {
                case COMPLETE:
                    stockUtils.localMove(moveLibraryBoxDTO.getPartId(), moveLibraryBoxDTO.getSystemNo(), moveLibraryBoxDTO.getBatchNo(), moveLibraryBoxDTO.getMoveQty(), moveLibraryBoxDTO.getStartLocationId(), moveLibraryBoxDTO.getArriveLocationId());
                    break;
                case CANCEL:
                    stockUtils.localMove(moveLibraryBoxDTO.getPartId(), moveLibraryBoxDTO.getSystemNo(), moveLibraryBoxDTO.getBatchNo(), moveLibraryBoxDTO.getMoveQty(), moveLibraryBoxDTO.getArriveLocationId(), moveLibraryBoxDTO.getStartLocationId());
                    break;
                default:
                    throw new RuntimeException("操作码" + escortEvents.name() + "->异常");
            }
        }
 
        //2.ifs移库
        List<MoveLibraryBoxDTO> moveLibraryBoxDTOListFilter = moveLibraryBoxDTOList.stream().filter(o -> StringUtils.isNotBlank(o.getStartLocationNoIfs()) && StringUtils.isNotBlank(o.getArriveLocationNoIfs())).collect(Collectors.toList());
        //将list按照零件号进行分组,去除IFS启用批次管理为true的数据
        Map<Long, List<MoveLibraryBoxDTO>> map = moveLibraryBoxDTOListFilter.stream().filter(x -> !x.getLotTrackingIfs()).collect(Collectors.groupingBy(MoveLibraryBoxDTO::getPartId));
        List<MoveLibraryBoxDTO> ifsList = new ArrayList<>();
        for (Map.Entry<Long, List<MoveLibraryBoxDTO>> entry : map.entrySet()) {
            List<MoveLibraryBoxDTO> moveLibraryBoxDTOByGroupList = entry.getValue();
            //汇总相同零件号的移库数量
            BigDecimal moveQtySum = moveLibraryBoxDTOByGroupList.stream().filter(x -> x.getMoveQty() != null).map(MoveLibraryBoxDTO::getMoveQty).reduce(BigDecimal.ZERO, BigDecimal::add);
            MoveLibraryBoxDTO ifsDTO = new MoveLibraryBoxDTO();
            BeanUtils.copyProperties(moveLibraryBoxDTOByGroupList.get(0), ifsDTO);
            ifsDTO.setMoveQty(moveQtySum);
            ifsList.add(ifsDTO);
        }
 
        //筛选出IFS启用批次管理为true的数据
        List<MoveLibraryBoxDTO> lotTrackingIfsList = moveLibraryBoxDTOListFilter.stream().filter(MoveLibraryBoxDTO::getLotTrackingIfs).collect(Collectors.toList());
        ifsList.addAll(lotTrackingIfsList);
 
        if (CollectionUtil.isNotEmpty(ifsList)) {
            //拼接inAttr
            IfsMoveLibraryDTO ifsMoveLibraryDTO = new IfsMoveLibraryDTO();
            //ifsMoveLibraryDTO.setRECORD_ID(packagingMapper.getPackingById(packagingId).getNo());
            List<IfsMoveLibraryDTO.DataBean> dataBeanList = new ArrayList<>();//批量标识
            for (MoveLibraryBoxDTO moveLibraryBoxDTO : ifsList) {
                // 工序库存不进行IFS移库
                Stock stock = stockMapper.selectById(moveLibraryBoxDTO.getStockId());
                if (BooleanUtil.isTrue(stock.getOperationStockStatus())) {
                    continue;
                }
                IfsMoveLibraryDTO.DataBean batchInfo = new IfsMoveLibraryDTO.DataBean();
                batchInfo.setPART_NO(moveLibraryBoxDTO.getPartNo());//零件号
                batchInfo.setLOT_BATCH_NO(moveLibraryBoxDTO.getIfsBatchNo());//ifs批次号
                batchInfo.setMOVE_QTY(moveLibraryBoxDTO.getMoveQty());//移库数量
                //batchInfo.setSERIAL_NO("*");//序列号
                batchInfo.setENG_CHG_LEVEL(moveLibraryBoxDTO.getEngChgLevel());//版本号
                //判断是否启用批次管理
                if (moveLibraryBoxDTO.getLotTrackingIfs() != null && moveLibraryBoxDTO.getLotTrackingIfs()) {
                    batchInfo.setWAIV_DEV_REJ_NO(moveLibraryBoxDTO.getBatchNo());//wdr号(存mes的sn号)
                } else {
                    batchInfo.setWAIV_DEV_REJ_NO("*");//wdr号
                    batchInfo.setLOT_BATCH_NO("*");
                }
 
                switch (escortEvents) {
                    case COMPLETE:
                        batchInfo.setLOCATION_NO(moveLibraryBoxDTO.getStartLocationNoIfs());//ifs出发库位号
                        batchInfo.setTO_LOCATION_NO(moveLibraryBoxDTO.getArriveLocationNoIfs());//ifs到达库位号
                        break;
                    case CANCEL:
                        batchInfo.setLOCATION_NO(moveLibraryBoxDTO.getArriveLocationNoIfs());//ifs出发库位号
                        batchInfo.setTO_LOCATION_NO(moveLibraryBoxDTO.getStartLocationNoIfs());//ifs到达库位号
                        break;
                }
                String contract = remoteParamService.getByKey(CONTRACT, SecurityConstants.FROM_IN).getData();//从系统参数中获取ifs域
                //batchInfo.setTO_CONTRACT(stockConfigBean.getRegion());//目标域
                // 因为现在多个 mes库位可能对应一个 ifs库位 所以 执行移库操作之前需要判断一下库位是否相同
                // xcg 20230413
                if (StrUtil.equals(batchInfo.getLOCATION_NO(), batchInfo.getTO_LOCATION_NO())) {
                    continue;
                }
                batchInfo.setTO_CONTRACT(contract);//目标域
                dataBeanList.add(batchInfo);
            }
            if (CollectionUtils.isEmpty(dataBeanList)){
                return;
            }
            ifsMoveLibraryDTO.setBATCH_INFO(dataBeanList);
            Gson gson = new Gson();
            String jsonstr = gson.toJson(ifsMoveLibraryDTO);
            JSONObject jsonObject = JSONObject.parseObject(jsonstr);//解决序列化时自动将大写转小写问题
 
            R res = ifsFeignClient.importMovePartStd(jsonObject, true);
            if (res.getCode() != 0) {
                throw new RuntimeException("ifs库存件移库失败->ifs报错信息=" + res.getMsg());
            }
        }
    }
 
    /**
     * 移库(通用)
     *
     * @param moveLibraryBoxDTOList
     */
    public void moveLibrary(List<MoveLibraryBoxDTO> moveLibraryBoxDTOList) {
        List<MoveLibraryBoxDTO> moveLibraryBoxDTOList_tmp = moveLibraryBoxDTOList.stream().filter(o -> StringUtils.isBlank(o.getPlanningMethod())).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(moveLibraryBoxDTOList_tmp)) {
            throw new RuntimeException("存在零件无[计划方法]->无法进行移库");
        }
 
        //1.mes移库
        for (MoveLibraryBoxDTO moveLibraryBoxDTO : moveLibraryBoxDTOList) {
            stockUtils.localMove(moveLibraryBoxDTO.getPartId(), moveLibraryBoxDTO.getSystemNo(), moveLibraryBoxDTO.getBatchNo(), moveLibraryBoxDTO.getMoveQty(), moveLibraryBoxDTO.getStartLocationId(), moveLibraryBoxDTO.getArriveLocationId());
        }
 
        //2.ifs移库
        List<MoveLibraryBoxDTO> moveLibraryBoxDTOListFilter = moveLibraryBoxDTOList.stream().filter(o -> StringUtils.isNotBlank(o.getStartLocationNoIfs()) && StringUtils.isNotBlank(o.getArriveLocationNoIfs()) && !o.getPlanningMethod().equals("K")).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(moveLibraryBoxDTOListFilter)) {
            //拼接inAttr
            IfsMoveLibraryDTO ifsMoveLibraryDTO = new IfsMoveLibraryDTO();
            ifsMoveLibraryDTO.setRECORD_ID(UUID.randomUUID().toString());
            List<IfsMoveLibraryDTO.DataBean> dataBeanList = new ArrayList<>();//批量标识
            for (MoveLibraryBoxDTO moveLibraryBoxDTO : moveLibraryBoxDTOListFilter) {
                // 工序库存不进行移库
                Stock stock = stockMapper.selectById(moveLibraryBoxDTO.getStockId());
                if (BooleanUtil.isTrue(stock.getOperationStockStatus())) {
                    continue;
                }
                IfsMoveLibraryDTO.DataBean batchInfo = new IfsMoveLibraryDTO.DataBean();
                batchInfo.setPART_NO(moveLibraryBoxDTO.getPartNo());//零件号
                batchInfo.setLOT_BATCH_NO(moveLibraryBoxDTO.getIfsBatchNo());//ifs批次号
                batchInfo.setMOVE_QTY(moveLibraryBoxDTO.getMoveQty());//移库数量
                //batchInfo.setSERIAL_NO("*");//序列号
                batchInfo.setENG_CHG_LEVEL(moveLibraryBoxDTO.getEngChgLevel());//版本号
                //batchInfo.setWAIV_DEV_REJ_NO("*");//wdr号
                Part part = partMapper.selectById(moveLibraryBoxDTO.getPartId());
                //判断是否启用批次管理
                if (part.getLotTrackingIfs() != null && part.getLotTrackingIfs()) {
                    FeederCertificate feederCertificate =
                            feederMapper.selectOne(Wrappers.<FeederCertificate>lambdaQuery().eq(FeederCertificate::getSn, moveLibraryBoxDTO.getBatchNo()));
                    if (null != feederCertificate) {
                        batchInfo.setWAIV_DEV_REJ_NO(org.apache.commons.lang3.StringUtils.isNotBlank(feederCertificate.getExaminerAfter()) ? feederCertificate.getExaminerAfter() : feederCertificate.getExaminer());
                    } else {
                        batchInfo.setWAIV_DEV_REJ_NO(moveLibraryBoxDTO.getBatchNo());//wdr号(把mes的sn号放里面)
                    }
                } else {
                    batchInfo.setWAIV_DEV_REJ_NO("*");//wdr号
                }
                batchInfo.setLOCATION_NO(moveLibraryBoxDTO.getStartLocationNoIfs());//ifs出发库位号
                batchInfo.setTO_LOCATION_NO(moveLibraryBoxDTO.getArriveLocationNoIfs());//ifs到达库位号
                batchInfo.setTO_CONTRACT(stockConfigBean.getRegion());//目标域
                // 因为现在多个 mes库位可能对应一个 ifs库位 所以 执行移库操作之前需要判断一下库位是否相同
                // xcg 20230413
                if (StrUtil.equals(batchInfo.getLOCATION_NO(), batchInfo.getTO_LOCATION_NO())) {
                    continue;
                }
                dataBeanList.add(batchInfo);
            }
            if (CollectionUtil.isEmpty(dataBeanList)) {
                return;
            }
            ifsMoveLibraryDTO.setBATCH_INFO(dataBeanList);
            Gson gson = new Gson();
            String jsonstr = gson.toJson(ifsMoveLibraryDTO);
            JSONObject jsonObject = JSONObject.parseObject(jsonstr);//解决序列化时自动将大写转小写问题
 
            R res = ifsFeignClient.importMovePartStd(jsonObject, true);
            if (res.getCode() != 0) {
                throw new RuntimeException("{" + moveLibraryBoxDTOListFilter.get(0).getBatchNo() + "}IFS与MES库存不一致");
            }
        }
    }
 
    /**
     * 精准查询ifs库存(零件号、批次号、wdr号)
     *
     * @param partNo  零件号
     * @param batchNo 批次号
     * @param wdr     wdr号
     * @return
     */
    public R getIfsStockPrecise(String partNo, String batchNo, String wdr) {
        if (StringUtils.isBlank(partNo) || StringUtils.isBlank(batchNo) || StringUtils.isBlank(wdr)) {
            throw new RuntimeException("零件号&&批次号&&wdr号传参不可为空");
        }
 
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("PART_NO", partNo);
        jsonObject.put("QUANTITY_FLAG", ">0");
        jsonObject.put("LOT_BATCH_NO", batchNo);
        jsonObject.put("WDR_NO", wdr);
        R result = ifsFeignClient.queryInventoryInfoStd(jsonObject, true);
        if (result.getCode() == 0) {
            JSONObject data = (JSONObject) JSON.toJSON(result.getData());
            JSONArray array = new JSONArray();
            for (int i = 0; i < data.getJSONArray("LIST_INFO").size(); i++) {
                if (data.getJSONArray("LIST_INFO").getJSONObject(i).getBigDecimal("QTY_AVAILABLE").compareTo(BigDecimal.ZERO) > 0) {
                    array.add(data.getJSONArray("LIST_INFO").getJSONObject(i));
                }
            }
            return R.ok(array, "OK");
        } else {
            throw new RuntimeException(result.getMsg());
        }
    }
}