| | |
| | | package com.zy.asrs.task.handler; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.core.common.Cools; |
| | | import com.core.exception.CoolException; |
| | | import com.zy.asrs.entity.Order; |
| | | import com.zy.asrs.entity.WrkMast; |
| | | import com.zy.asrs.mapper.OrderMapper; |
| | | import com.zy.asrs.mapper.WrkMastMapper; |
| | | import com.zy.asrs.entity.*; |
| | | import com.zy.asrs.mapper.*; |
| | | import com.zy.asrs.service.ApiLogService; |
| | | import com.zy.asrs.service.WorkService; |
| | | import com.zy.asrs.service.WrkDetlService; |
| | | import com.zy.asrs.utils.Utils; |
| | | import com.zy.common.constant.MesConstant; |
| | | import com.zy.common.properties.SlaveProperties; |
| | | import com.zy.common.utils.HttpHandler; |
| | | import com.zy.system.entity.Config; |
| | | import com.zy.system.mapper.ConfigMapper; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * @author pang.jiabao |
| | |
| | | @Resource |
| | | private WrkMastMapper wrkMastMapper; |
| | | |
| | | @Resource |
| | | private WrkDetlService wrkDetlService; |
| | | |
| | | @Resource |
| | | private OrderDetlMapper orderDetlMapper; |
| | | |
| | | @Resource |
| | | private LocDetlMapper locDetlMapper; |
| | | |
| | | @Resource |
| | | private LocMastMapper locMastMapper; |
| | | |
| | | @Resource |
| | | private WorkService workService; |
| | | |
| | | @Resource |
| | | private ConfigMapper configMapper; |
| | | |
| | | @Autowired |
| | | private SlaveProperties slaveProperties; |
| | | |
| | | @Transactional |
| | | public void startCkrwPushGwcs(WrkMast wrkMast) { |
| | | |
| | |
| | | Map<String, Object> headers = new HashMap<>(); |
| | | headers.put("Content-Type", "application/json;charset=UTF-8"); |
| | | |
| | | // 下发给gwcs要走的路径标识 |
| | | int descFlag = getDescToGwcs(wrkMast); |
| | | |
| | | // 构造请求体 |
| | | JSONObject jsonObject = new JSONObject(); |
| | | jsonObject.put("workNo", wrkMast.getWrkNo()); |
| | | jsonObject.put("staNo", wrkMast.getStaNo()); |
| | | jsonObject.put("sourceStaNo", wrkMast.getSourceStaNo()); |
| | | jsonObject.put("staNo", wrkMast.getIoType() == 3 ? 3013 :wrkMast.getStaNo()); |
| | | jsonObject.put("barcode", wrkMast.getBarcode()); |
| | | jsonObject.put("sourceStaNo", wrkMast.getIoType() == 3 ? wrkMast.getStaNo() : wrkMast.getSourceStaNo()); |
| | | jsonObject.put("descFlag", descFlag); // 101出库时用,0只有一条路径,1理货贴标路径,2贴标打带路径 |
| | | String body = jsonObject.toJSONString(); |
| | | |
| | | boolean success = false; |
| | | String response = ""; |
| | | try { |
| | | response = new HttpHandler.Builder() |
| | | .setUri(MesConstant.URL) |
| | | .setPath(MesConstant.PAKIN_URL) |
| | | .setUri(MesConstant.GWCS_IP_PORT) |
| | | .setPath(MesConstant.GWCS_DCKK_URL) |
| | | .setHeaders(headers) |
| | | .setJson(body) |
| | | .build() |
| | | .doPost(); |
| | | if (!Cools.isEmpty(response)) { |
| | | wrkMast.setWrkSts(2L); // 更新为设备上走 |
| | | if (wrkMast.getIoType() == 110) { // 空托盘出库直接完成任务 |
| | | wrkMast.setWrkSts(14L); |
| | | } else if (wrkMast.getIoType() == 3) { |
| | | // 修改工作主档状态 |
| | | wrkMast.setWrkSts(15L); |
| | | wrkMast.setModiTime(new Date()); |
| | | } else if(wrkMast.getIoType() == 12) { // 跨巷道转移 |
| | | wrkMast.setWrkSts(1L); // 状态改为1.生成入库id |
| | | wrkMast.setModiTime(new Date()); |
| | | } |
| | | wrkMastMapper.updateById(wrkMast); |
| | | success = true; |
| | | } else { |
| | |
| | | } |
| | | } |
| | | |
| | | @Transactional |
| | | public void OutBoundCompleteReport(Order order) { |
| | | /** |
| | | * 全板出库到3077或3106的任务,判断出库要走的路径 |
| | | * @param wrkMast 工作主档 |
| | | * @return 1.直接出库,只有一条路径 2.理货贴标出库 3.贴标打带出库 4.贴标出库 |
| | | */ |
| | | private int getDescToGwcs(WrkMast wrkMast) { |
| | | // todo 两条路线怎么选 |
| | | int flag = 1; |
| | | List<WrkDetl> wrkDetls = wrkDetlService.selectList(new EntityWrapper<WrkDetl>().eq("wrk_no", wrkMast.getWrkNo())); |
| | | List<String> collect = wrkDetls.stream().map(WrkDetl::getBrand).distinct().collect(Collectors.toList()); |
| | | |
| | | // 获取请求头 |
| | | Map<String, Object> headers = new HashMap<>(); |
| | | headers.put("Content-Type", "application/json;charset=UTF-8"); |
| | | if (wrkMast.getIoType() == 101 && (wrkMast.getStaNo() == 3077 || wrkMast.getStaNo() == 3106)) { |
| | | // 有几个木箱 |
| | | if (collect.size() == 1) { // 一箱 |
| | | if (wrkDetls.size() == 1) { // 一卷去贴标 |
| | | flag = 4; |
| | | } else { // 多卷直接出 |
| | | |
| | | // 构造请求体 |
| | | JSONObject jsonObject = new JSONObject(); |
| | | jsonObject.put("orderNo", order.getOrderNo()); |
| | | jsonObject.put("complete", 1); // 订单完成为1,其他... |
| | | String body = jsonObject.toJSONString(); |
| | | } |
| | | } else if(collect.size() == 2) { // 两箱去贴标打带 |
| | | |
| | | boolean success = false; |
| | | String response = ""; |
| | | try { |
| | | response = new HttpHandler.Builder() |
| | | .setUri(MesConstant.URL) |
| | | .setPath(MesConstant.PAKIN_URL) |
| | | .setHeaders(headers) |
| | | .setJson(body) |
| | | .build() |
| | | .doPost(); |
| | | if (!Cools.isEmpty(response)) { |
| | | order.setSettle(6L); |
| | | orderMapper.updateById(order); |
| | | success = true; |
| | | } else { |
| | | log.error("请求接口失败!!!url:{};request:{};response:{}", MesConstant.URL + MesConstant.PAKIN_URL, body, response); |
| | | throw new CoolException("下发出库任务给GWCS(从出库码头到出库口)失败"); |
| | | // 两箱肯定都是单卷情况 同型号(木箱型号-管芯类型-实测宽幅-生箔厚度-分切下料时间)去贴标,打带,不同型号贴标出库 |
| | | WrkDetl wrkDetl1 = wrkDetls.get(0); |
| | | WrkDetl wrkDetl2 = wrkDetls.get(1); |
| | | if (wrkDetl1.getColor().equals(wrkDetl2.getColor())&& |
| | | wrkDetl1.getSku().equals(wrkDetl2.getSku())&& |
| | | wrkDetl1.getManu().equals(wrkDetl2.getManu())&& |
| | | wrkDetl1.getItemNum().equals(wrkDetl2.getItemNum())) { |
| | | flag = 3; |
| | | } else { |
| | | flag = 4; |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("出库订单完成上报MES异常,工作号:{},{}", order.getOrderNo(), e.getMessage()); |
| | | } finally { |
| | | try { |
| | | // 保存接口日志 |
| | | apiLogService.save( |
| | | "出库订单完成上报MES", |
| | | MesConstant.URL + MesConstant.PAKIN_URL, |
| | | null, |
| | | "127.0.0.1", |
| | | jsonObject.toJSONString(), |
| | | response, |
| | | success |
| | | ); |
| | | } catch (Exception e) { |
| | | log.error("接口日志保存异常", e); |
| | | } else if (wrkMast.getIoType() == 103 && (wrkMast.getStaNo() == 3077 || wrkMast.getStaNo() == 3106)) { // 两箱出一箱,需桁架理货 |
| | | // 都要先去理货 |
| | | flag = 2; |
| | | // if (wrkDetls.size() == 1) { // 一卷贴标出库 |
| | | // flag = 4; |
| | | // } else { // 多卷直接出库 |
| | | // |
| | | // } |
| | | } |
| | | return flag; |
| | | } |
| | | |
| | | /** |
| | | * 自动备货处理 |
| | | */ |
| | | @Transactional |
| | | public void autoStockUpHandler(List<String> list,int columnNum) { |
| | | |
| | | // 根据包装组号获取所在库位 |
| | | List<LocDetl> locDetls = locDetlMapper.selectLocNoByGroupNo(list); |
| | | if (locDetls.isEmpty()) { |
| | | return; |
| | | } |
| | | // 相同则合并,一个库位两个包装组号 |
| | | Map<String,List<String>> map = new HashMap<>(); |
| | | for(LocDetl locDetl : locDetls) { |
| | | List<String> brand = map.get(locDetl.getLocNo()); |
| | | if (brand == null) { |
| | | map.put(locDetl.getLocNo(),new ArrayList<String>(){{add(locDetl.getBrand());}}); |
| | | } else { |
| | | brand.add(locDetl.getBrand()); |
| | | map.put(locDetl.getLocNo(),brand); |
| | | } |
| | | } |
| | | |
| | | // 遍历堆垛机并且判断是否存在任务 |
| | | for (int i = 1; i <= 6; i++) { |
| | | // 要备货的库位 |
| | | String sourceLocNo = null; |
| | | // 备货目标库位 |
| | | String staLocNo = null; |
| | | Integer wrkCount = wrkMastMapper.selectCount(new EntityWrapper<WrkMast>().eq("crn_no", i)); |
| | | if(wrkCount > 0) { |
| | | log.warn("{}号堆垛机已存在任务",i); |
| | | continue; |
| | | } |
| | | // 根据堆垛机号查询到对应的深库位和浅库位 深库位4*n-3和4*n 浅库位4*n-2和4*n-1 |
| | | int s1 = 4*i-3; |
| | | int s2 = 4*i; |
| | | int q1 = 4 * i - 2; |
| | | int q2 = 4 * i -1; |
| | | |
| | | // 根据堆垛机号获取一个浅库位 |
| | | for(String key : map.keySet()) { |
| | | int row = Integer.parseInt(key.substring(0, 2)); |
| | | if (row == q1 || row == q2) { |
| | | sourceLocNo = key; |
| | | break; |
| | | } |
| | | } |
| | | // 浅库位没有则找一个深库位 |
| | | if (sourceLocNo == null) { |
| | | for(String key : map.keySet()) { |
| | | int row = Integer.parseInt(key.substring(0, 2)); |
| | | if (row == s1 || row == s2) { |
| | | sourceLocNo = key; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | // 没有找到源库位 |
| | | if (sourceLocNo == null) { |
| | | log.warn("没有找到源库位,堆垛机:{}",i); |
| | | continue; |
| | | } |
| | | // 寻找一个备货的目标库位,先深后浅 |
| | | List<LocMast> locMasts1 = locMastMapper.selectList(new EntityWrapper<LocMast>().eq("loc_sts", "O").eq("crn_no", i).in("row1", s1, s2) |
| | | .le("bay1", columnNum)); |
| | | if (locMasts1.isEmpty()) { |
| | | // 深库位为空了,取浅库位 |
| | | List<LocMast> locMasts2 = locMastMapper.selectList(new EntityWrapper<LocMast>().eq("loc_sts", "O").eq("crn_no", i).in("row1", q1, q2) |
| | | .le("bay1", columnNum)); |
| | | if (!locMasts2.isEmpty()) { |
| | | staLocNo = locMasts2.get(0).getLocNo(); |
| | | } |
| | | } else { |
| | | staLocNo = locMasts1.get(0).getLocNo(); |
| | | } |
| | | |
| | | if(staLocNo == null) { |
| | | log.warn("{}号堆垛机备货区满了",i); |
| | | continue; |
| | | } |
| | | |
| | | // 备货的源库位,目标库位都获取到了,生成移库任务 |
| | | workService.locMove(sourceLocNo,staLocNo,29L); |
| | | |
| | | // 订单明细改成备货中,在任务完成时候改成备货完成,并判断整个订单是否完成 |
| | | orderDetlMapper.updateOrderDetlStatusByPackageNo(map.get(sourceLocNo), 1); |
| | | |
| | | // 移除已生成备货库位 |
| | | map.remove(sourceLocNo); |
| | | } |
| | | |
| | | } |
| | | |
| | | @Transactional |
| | | public void autoMoveLoc(List<OrderDetl> orderDetlList) { |
| | | |
| | | // 判断是否已经有执行的移库任务 |
| | | Integer count = wrkMastMapper.selectCount(new EntityWrapper<WrkMast>().in("io_type", 11, 12)); |
| | | if (count > 0) { |
| | | return; |
| | | } |
| | | |
| | | OrderDetl detl = null; // 要移库的明细 |
| | | String staLoc = null; // 移库目标库位 |
| | | |
| | | // 从待移库位列表中先浅后深获取一个待移库位 |
| | | Optional<OrderDetl> any = orderDetlList.stream().filter(orderDetl -> Utils.isShallowLoc(slaveProperties,orderDetl.getSpecs())).findAny(); |
| | | |
| | | if (any.isPresent()){ |
| | | detl = any.get(); |
| | | } |
| | | // 剩下的应该都是深库位,获取第一个 |
| | | if (detl == null) { |
| | | detl = orderDetlList.get(0); |
| | | // 对应浅库位有货,在堆垛机出库的时候会检测到,在那里生成移库任务 |
| | | } |
| | | |
| | | // 获取备货区配置 |
| | | Config config = configMapper.selectConfigByCode("auto_stock_up"); |
| | | if (config == null) { |
| | | return; |
| | | } |
| | | // 备货取是前几列 |
| | | int bay1 = Integer.parseInt(config.getValue()); |
| | | // 指定的目标库位 |
| | | String model = detl.getModel(); |
| | | |
| | | // 指定目标库位 |
| | | if (!Cools.isEmpty(model)) { |
| | | // 目标库位是深库位 |
| | | if (Utils.isDeepLoc(slaveProperties,model)) { |
| | | // 目标库位 |
| | | LocMast locMast2 = locMastMapper.selectById(model); |
| | | if (locMast2 == null || !locMast2.getLocSts().equals("O")) { |
| | | log.error("指定的目标库位【{}】状不为空", model); |
| | | return; |
| | | } |
| | | // 获取到对应浅库位 |
| | | String shallowLoc = Utils.getShallowLoc(slaveProperties, model); |
| | | LocMast locMast = locMastMapper.selectById(shallowLoc); |
| | | // 浅库位有货 |
| | | if (locMast.getLocSts().equals("F") || locMast.getLocSts().equals("D")) { |
| | | log.error("选择的深库位【{}】,但是浅库位【{}】有货", model, locMast.getLocNo()); |
| | | return; |
| | | } |
| | | // 避开备货区 |
| | | if (Utils.getBay(model) <= bay1) { |
| | | log.error("指定的目标库位【{}】在备货区,不能转移", model); |
| | | return; |
| | | } |
| | | } |
| | | // 深库位检测通过,或者是浅库位 |
| | | staLoc = model; |
| | | } else if ( detl.getBeBatch() != null) { // 指定目标巷道 |
| | | // 目标巷道 |
| | | Integer beBatch = detl.getBeBatch(); |
| | | // 从巷道里面先深后浅取一个空库位,不要占用备货区 |
| | | List<LocMast> locMasts = locMastMapper.selectList(new EntityWrapper<LocMast>().eq("crn_no", beBatch).eq("loc_sts", "O").gt("bay1", bay1)); |
| | | if (locMasts.isEmpty()) { |
| | | log.error("指定巷道【{}】没有能移库的空库位了",beBatch); |
| | | return; |
| | | } |
| | | // 先过滤出深库位 |
| | | Optional<LocMast> a = locMasts.stream().filter(locMast -> Utils.isDeepLoc(slaveProperties,locMast.getLocNo())).findAny(); |
| | | if (a.isPresent()){ |
| | | staLoc = a.get().getLocNo(); |
| | | // 获取到对应浅库位 |
| | | String shallowLoc = Utils.getShallowLoc(slaveProperties, staLoc); |
| | | LocMast locMast = locMastMapper.selectById(shallowLoc); |
| | | // 浅库位有货 |
| | | if (locMast.getLocSts().equals("F") || locMast.getLocSts().equals("D")) { |
| | | log.error("指定的目标巷道深库位【{}】,但是浅库位【{}】有货",staLoc,locMast.getLocNo()); |
| | | return; |
| | | } |
| | | } |
| | | // 深库位没有则取浅库位 |
| | | if (staLoc == null) { |
| | | staLoc = locMasts.get(0).getLocNo(); |
| | | } |
| | | } else { |
| | | log.error("目标库位或目标巷道有误:{}",detl); |
| | | return; |
| | | } |
| | | |
| | | // 生成跨巷道移库任务 |
| | | workService.autoLocMove(detl.getOrderNo(),detl.getSpecs(),staLoc,29L); |
| | | |
| | | // 更新单据明细移库状态为移库中 |
| | | detl.setDanger(1); |
| | | if (detl.getBeBatch() != null) { |
| | | detl.setModel(staLoc); // 补充目标库位 |
| | | } |
| | | orderDetlMapper.updateById(detl); |
| | | // 更新单据状态为2处理中 |
| | | orderMapper.updatePendingSettleByOrderNo(detl.getOrderNo(),2L); |
| | | } |
| | | |
| | | } |