李林
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
package com.chinaztt.mes.plan.service.impl;
 
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
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.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.chinaztt.mes.common.handler.StateMachineHandler;
import com.chinaztt.mes.common.numgen.NumberGenerator;
import com.chinaztt.mes.common.util.StateResult;
import com.chinaztt.mes.common.util.WxCpUtils;
import com.chinaztt.mes.plan.dto.MpsRequirementsDTO;
import com.chinaztt.mes.plan.entity.*;
import com.chinaztt.mes.plan.mapper.*;
import com.chinaztt.mes.plan.service.MpsRequirementsService;
import com.chinaztt.mes.plan.state.requirement.MpsRequirementsStateMachineConfig;
import com.chinaztt.mes.plan.state.requirement.constant.MpsRequirementsEvents;
import com.chinaztt.mes.plan.state.requirement.constant.MpsRequirementsStates;
import com.chinaztt.ztt.admin.api.feign.RemoteParamService;
import com.chinaztt.ztt.common.core.constant.SecurityConstants;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
 
/**
 * @ClassName MpsRequirementsServiceImpl
 * @Description TODO
 * @Author luh
 * @Date 2020/8/27 16:51
 * @Version 1.0
 **/
@Service
@Transactional(rollbackFor = Exception.class)
@AllArgsConstructor
public class MpsRequirementsServiceImpl extends ServiceImpl<MpsRequirementsMapper, MpsRequirements> implements MpsRequirementsService {
    private static Logger logger = LoggerFactory.getLogger(MpsRequirementsServiceImpl.class);
    private PlanJoinOrderRequirementsMapper planJoinOrderRequirementsMapper;
    private MpsSourceMapper planMpsSourceMapper;
    private MasterProductionScheduleMapper masterProductionScheduleMapper;
    private NumberGenerator<MpsRequirements> requirementsNumberGenerator;
    private NumberGenerator<MasterProductionSchedule> scheduleNumberGenerator;
    private StateMachineFactory<MpsRequirementsStates, MpsRequirementsEvents> mpsRequirementsStateMachineFactory;
    private StateMachinePersister<MpsRequirementsStates, MpsRequirementsEvents, MpsRequirements> persister;
    private CustomerOrderMapper customerOrderMapper;
    private RemoteParamService remoteParamService;
 
    @Override
    public IPage<List<MpsRequirements>> getMpsRequirementsPage(Page page, QueryWrapper<MpsRequirementsDTO> mpsRequirements, String type) {
        return baseMapper.getMpsRequirementsPage(page, mpsRequirements, type);
    }
 
    @Override
    public boolean deleteById(Long id) {
        // 判断一下是否已生成主计划,若生成无法删除
        List<String> mpsNos = baseMapper.selectScheduleByRequirementsId(id);
        if (CollectionUtil.isNotEmpty(mpsNos)) {
            throw new RuntimeException("已生成对应主计划无法删除:" + mpsNos.stream().collect(Collectors.joining(",")));
        }
        // 1.删除主生产计划需求
        boolean result = SqlHelper.retBool(baseMapper.deleteById(id));
        // 2.删除主生产计划需求和客户订单关联表
        planJoinOrderRequirementsMapper.delete(Wrappers.<PlanJoinOrderRequirements>query().lambda()
                .eq(PlanJoinOrderRequirements::getMpsRequirementsId, id));
        return result;
    }
 
    @Override
    public boolean updateById(MpsRequirements mpsRequirements) {
        boolean result = SqlHelper.retBool(baseMapper.updateById(mpsRequirements));
        // 更新来源对应的主生产计划的最新时间
        masterProductionScheduleMapper.updateRequiredDateBySource(mpsRequirements);
        try {
            String staffStr = remoteParamService.getByKey("MPS_REQUIMENT_UPDATE_STAFF", SecurityConstants.FROM_IN).getData();
            if (StringUtils.isNotBlank(staffStr)) {
                WxCpUtils.inform(staffStr, mpsRequirements.getUpdateUser() + "编辑了主需求:" + mpsRequirements.getIndeRequNo(), null);
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw new RuntimeException("编辑主需求消息推送失败");
        }
        return result;
    }
 
    @Override
    public boolean save(MpsRequirements mpsRequirements) {
        mpsRequirements.setSourceType("01");
        mpsRequirements.setIndeRequNo(requirementsNumberGenerator.generateNumberWithPrefix(MpsRequirements.DIGIT, MpsRequirements.PREFIX, MpsRequirements::getIndeRequNo));
        boolean result = SqlHelper.retBool(baseMapper.insert(mpsRequirements));
        try {
            String staffStr = remoteParamService.getByKey("MPS_REQUIMENT_INSERT_STAFF", SecurityConstants.FROM_IN).getData();
            if (StringUtils.isNotBlank(staffStr)) {
                WxCpUtils.inform(staffStr, mpsRequirements.getUpdateUser() + "创建了主需求:" + mpsRequirements.getIndeRequNo(), null);
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw new RuntimeException("新增主需求消息推送失败");
        }
        return result;
    }
 
    @Override
    public MpsRequirementsDTO selectById(Long id) {
        return baseMapper.selectDtoById(id);
    }
 
    @Override
    public void checkOverageOrder(MpsRequirements mpsRequirements) {
        BigDecimal qtyRequiredSum = baseMapper.getQtyRequiredSumById(mpsRequirements.getId());
        if (BigDecimal.ZERO.compareTo(qtyRequiredSum) == 0) {
            // 1.不存在客户订单
            return;
        } else {
            // 2.查询对应客户订单的数量
            BigDecimal orderQuantity = baseMapper.getOrderQuantityById(mpsRequirements.getId());
            qtyRequiredSum = qtyRequiredSum.add(mpsRequirements.getQtyRequired());
            if (qtyRequiredSum.compareTo(orderQuantity) == 1) {
                // 超出数量
                throw new RuntimeException("修改后的总计划需求数量超出订单数量:" + qtyRequiredSum.subtract(orderQuantity).stripTrailingZeros().toPlainString());
            }
        }
    }
 
    @Override
    public boolean changeState(List<Long> ids, String event) {
        if (CollectionUtil.isEmpty(ids)) {
            throw new RuntimeException("请选择主生产计划需求");
        }
        for (Long id : ids) {
            MpsRequirements mpsRequirements = baseMapper.selectById(id);
            Message<MpsRequirementsEvents> message = MessageBuilder.withPayload(MpsRequirementsEvents.valueOf(event)).setHeader("mpsRequirements", mpsRequirements).build();
            StateMachineHandler handler = new StateMachineHandler(mpsRequirementsStateMachineFactory, persister, MpsRequirementsStateMachineConfig.MACHINE_ID, mpsRequirements);
            StateResult res = handler.sendEvent(message, mpsRequirements.getId());
            if (!res.isSuccess()) {
                throw new RuntimeException(res.getMsg());
            }
        }
        return true;
    }
 
    @Override
    public boolean createMasterProductionSchedule(List<MpsRequirementsDTO> mpsRequirementsDTOList) {
        if (CollectionUtil.isEmpty(mpsRequirementsDTOList)) {
            throw new RuntimeException("请选择主生产计划需求");
        }
        List<List<MpsRequirementsDTO>> partList = new ArrayList<>();
        // 1.先按零件分组
        List<List<MpsRequirementsDTO>> groupList = new ArrayList<>();
        mpsRequirementsDTOList.stream().collect(Collectors.groupingBy(MpsRequirementsDTO::getPartId, Collectors.toList()))
                .forEach((part, listByPart) -> {
                    groupList.add(listByPart);
                });
        try {
            for (List<MpsRequirementsDTO> listByPart : groupList) {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                Long id = listByPart.get(0).getPartId();
                LocalDateTime requiredDate = listByPart.get(0).getRequiredDate();
                String date = formatter.format(listByPart.get(0).getCreateTime());
                MasterProductionSchedule newMasterProductionSchedule = masterProductionScheduleMapper.getPlanProduction(id, date);
                if (newMasterProductionSchedule != null) {
                    if (newMasterProductionSchedule.getRequiredDate().isBefore(listByPart.get(0).getRequiredDate())) {
                        requiredDate = newMasterProductionSchedule.getRequiredDate();
                    }
                    newMasterProductionSchedule.setQtyRequired(newMasterProductionSchedule.getQtyRequired().add(listByPart.get(0).getQtyPlaned()));
                    newMasterProductionSchedule.setRequiredDate(requiredDate);
                    newMasterProductionSchedule.setSource("主需求");
                    masterProductionScheduleMapper.updateById(newMasterProductionSchedule);
                    // 2.3.保存主生产计划来源
                    for (MpsRequirementsDTO mpsRequirementsDTO : listByPart) {
                        save(mpsRequirementsDTO, newMasterProductionSchedule.getId());
                    }
                } else {
                    partList.add(listByPart);
                }
            }
 
        } catch (Exception e) {
            log.error("创建主生产计划失败", e);
            throw new RuntimeException("创建主生产计划失败");
        }
        // 2.再合并生成主计划
        try {
            for (List<MpsRequirementsDTO> listByPart : partList) {
                // 2.1合并计划数量,取最早的需求日期
                BigDecimal totalQuantity = BigDecimal.ZERO;
                LocalDateTime requiredDate = listByPart.get(0).getRequiredDate();
                for (MpsRequirementsDTO mpsRequirementsDTO : listByPart) {
                    totalQuantity = totalQuantity.add(mpsRequirementsDTO.getQtyPlaned());
                    if (mpsRequirementsDTO.getRequiredDate().isBefore(requiredDate)) {
                        requiredDate = mpsRequirementsDTO.getRequiredDate();
                    }
                }
                // 2.2.保存主生产计划
                MasterProductionSchedule masterProductionSchedule = new MasterProductionSchedule();
                masterProductionSchedule.setMpsNo(scheduleNumberGenerator.generateNumberWithPrefix(MasterProductionSchedule.DIGIT, MasterProductionSchedule.PREFIX, MasterProductionSchedule::getMpsNo));
                masterProductionSchedule.setPartId(listByPart.get(0).getPartId());
                masterProductionSchedule.setQtyRequired(totalQuantity);
                masterProductionSchedule.setRequiredDate(requiredDate);
                masterProductionSchedule.setSource("主需求");
                masterProductionScheduleMapper.insert(masterProductionSchedule);
                // 2.3.保存主生产计划来源
                for (MpsRequirementsDTO mpsRequirementsDTO : listByPart) {
                    save(mpsRequirementsDTO, masterProductionSchedule.getId());
                }
            }
 
        } catch (Exception e) {
            log.error("创建主生产计划失败", e);
            throw new RuntimeException("创建主生产计划失败");
        }
        return true;
    }
 
    @Override
    public List<CustomerOrder> getCustomer(Long id) {
        return customerOrderMapper.getCustomer(id);
    }
 
    private void save(MpsRequirementsDTO mpsRequirementsDTO, Long id) {
        try {
            MpsSource planMpsSource = new MpsSource();
            planMpsSource.setMpsId(id);
            planMpsSource.setMpsRequId(mpsRequirementsDTO.getId());
            planMpsSource.setQtyPlaned(mpsRequirementsDTO.getQtyPlaned());
            planMpsSource.setRemark(mpsRequirementsDTO.getRemark());
            planMpsSourceMapper.insert(planMpsSource);
            // 2.4.更新对应的主生产计划需求-已计划数量
            baseMapper.updatePlanRequiredById(mpsRequirementsDTO);
        } catch (Exception e) {
            log.error("保存主生产计划来源失败", e);
            throw new RuntimeException("保存主生产计划来源失败");
        }
    }
}