| package com.zy.asrs.controller; | 
|   | 
| import com.baomidou.mybatisplus.mapper.EntityWrapper; | 
| import com.core.annotations.ManagerAuth; | 
| import com.core.common.*; | 
| import com.core.exception.CoolException; | 
| import com.zy.asrs.entity.*; | 
| import com.zy.asrs.entity.param.PakoutRequest; | 
| import com.zy.asrs.entity.param.StockOutParam; | 
| import com.zy.asrs.service.*; | 
| import com.zy.common.model.LocDetlDto; | 
| import com.zy.common.model.LocDto; | 
| import com.zy.common.model.enums.IoWorkType; | 
| import com.zy.common.web.BaseController; | 
| import org.springframework.beans.factory.annotation.Autowired; | 
| import org.springframework.web.bind.annotation.PostMapping; | 
| import org.springframework.web.bind.annotation.RequestBody; | 
| import org.springframework.web.bind.annotation.RequestParam; | 
| import org.springframework.web.bind.annotation.RestController; | 
|   | 
| import java.util.*; | 
| import java.util.stream.Collectors; | 
|   | 
| /** | 
|  * Created by vincent on 2022/3/26 | 
|  */ | 
|   | 
| @RestController | 
| public class OutController extends BaseController { | 
|   | 
|     @Autowired | 
|     private OrderService orderService; | 
|     @Autowired | 
|     private OrderDetlService orderDetlService; | 
|     @Autowired | 
|     private LocDetlService locDetlService; | 
|     @Autowired | 
|     private LocMastService locMastService; | 
|     @Autowired | 
|     private StaDescService staDescService; | 
|     @Autowired | 
|     private WorkService workService; | 
|     @Autowired | 
|     private BasDevpService basDevpService; | 
|     @Autowired | 
|     private DocTypeService docTypeService; | 
|     @Autowired | 
|     private SnowflakeIdWorker snowflakeIdWorker; | 
|     @Autowired | 
|     private MatService matService; | 
|   | 
|   | 
|     @PostMapping("/out/pakout/orderDetlIds/auth") | 
|     @ManagerAuth | 
|     public R pakoutOrderDetlIds(@RequestParam Long orderId) throws InterruptedException { | 
|         Thread.sleep(200); | 
|         return R.ok().add(orderDetlService.selectByOrderId(orderId).stream().map(OrderDetl::getId).distinct().collect(Collectors.toList())); | 
|     } | 
|   | 
|     @PostMapping("/getMesOrder/auth") | 
|     @ManagerAuth | 
|     public R getMesOrder() { | 
|         List<String> orderNoList = orderService.getOrderNosByDocType(25L); | 
|         return R.ok().add(orderNoList); | 
|     } | 
|   | 
|     @PostMapping("/out/pakout/preview/auth") | 
|     @ManagerAuth | 
|     public R pakoutPreview(@RequestBody List<Long> ids) { | 
|         if (Cools.isEmpty(ids)) { | 
|             return R.parse(BaseRes.PARAM); | 
|         } | 
|   | 
|         List<OrderDetl> orderDetls = orderDetlService.selectBatchIds(ids); | 
|         if (orderDetls.isEmpty()) { | 
|             return R.parse("请选择数据"); | 
|         } | 
|   | 
|         Order order = orderService.selectOne( | 
|                 new EntityWrapper<Order>().eq("order_no", orderDetls.get(0).getOrderNo()) | 
|         ); | 
|         if (order == null) { | 
|             return R.parse("订单数据为空"); | 
|         } | 
|   | 
|         Map<String, List<OrderDetl>> brandGroup; | 
|         if (order.getDocType() == 27) { | 
|             // 按包装组号分组处理 | 
|             brandGroup = orderDetls.stream() | 
|                     .collect(Collectors.groupingBy(o -> { | 
|                         String brand = o.getModel(); | 
|                         return brand != null ? brand : "跨巷道"; | 
|                     })); | 
|         } else { | 
|             // 按包装组号分组处理 | 
|             brandGroup = orderDetls.stream() | 
|                     .collect(Collectors.groupingBy(o -> { | 
|                         String brand = o.getBrand(); | 
|                         return brand != null ? brand : "跨巷道"; | 
|                     })); | 
|         } | 
|   | 
|   | 
|         List<LocDto> locDtos = new ArrayList<>(); | 
|   | 
|         // 每个包装组查一次库存 | 
|         for (Map.Entry<String, List<OrderDetl>> entry : brandGroup.entrySet()) { | 
|             String brand = entry.getKey(); | 
|             List<OrderDetl> brandOrderDetls = entry.getValue(); | 
|             List<LocDetl> locDetls; | 
|             if (order.getDocType() == 27) { | 
|                 locDetls = locDetlService.selectList( | 
|                         new EntityWrapper<LocDetl>().eq("model", brand) | 
|                 ); | 
|             } else { | 
|                 // 查这个包装组对应的所有库存 | 
|                 locDetls = locDetlService.selectList( | 
|                         new EntityWrapper<LocDetl>().eq("brand", brand) | 
|                 ); | 
|             } | 
|   | 
|             if (locDetls.isEmpty()) continue; | 
|   | 
|             // 获取出库口 | 
|             List<Integer> staNos = new ArrayList<>(); | 
|             if (order.getDocType() == 21) { | 
|                 staNos.add(3077); | 
|                 staNos.add(3106); | 
|             } else if (order.getDocType() == 22) { | 
|                 staNos.add(2041); | 
|             } else if (order.getDocType() == 23) { | 
|                 staNos.add(3092); | 
|                 staNos.add(3102); | 
|                 staNos.add(3095); | 
|             } | 
|   | 
|             // 去重 key,避免相同 loc+unit+model 重复显示 | 
|             Set<String> seen = new HashSet<>(); | 
|   | 
|             for (LocDetl locDetl : locDetls) { | 
|                 String key = locDetl.getLocNo() + "|" + locDetl.getUnit() + "|" + locDetl.getModel(); | 
|                 if (seen.contains(key)) continue; | 
|                 seen.add(key); | 
|   | 
|                 // 对应多个明细时,分配到第一个明细(或你可以拆分多个) | 
|                 OrderDetl firstDetl = brandOrderDetls.get(0); | 
|   | 
|                 LocDto locDto = new LocDto(); | 
|                 locDto.setLocNo(locDetl.getLocNo()); | 
|                 locDto.setUnit(locDetl.getUnit()); | 
|                 locDto.setModel(locDetl.getModel()); | 
|                 locDto.setThreeCode(locDetl.getThreeCode()); | 
|                 locDto.setBrand(locDetl.getBrand()); | 
|                 locDto.setOrderNo(firstDetl.getOrderNo()); | 
|                 locDto.setStaNos(staNos); | 
|                 locDto.setOrderDetlId(firstDetl.getId()); | 
|   | 
|                 locDtos.add(locDto); | 
|             } | 
|         } | 
|   | 
|         return R.ok().add(locDtos); | 
|     } | 
|   | 
|     @PostMapping("/out/refund/loc/preview/auth") | 
|     @ManagerAuth | 
|     public R refundLocPreview(@RequestBody List<Long> ids) { | 
|         if (Cools.isEmpty(ids)) { | 
|             return R.parse(BaseRes.PARAM); | 
|         } | 
|         List<LocDto> locDtos = new ArrayList<>(); | 
|         for (Long id : ids) { | 
|             Order order = orderService.selectById(id); | 
|             List<OrderDetl> orderDetls = orderDetlService.selectByOrderId(order.getId()); | 
|   | 
|             for (OrderDetl orderDetl : orderDetls) { | 
|                 LocDto locDto = new LocDto(orderDetl.getManu(), orderDetl.getMatnr(), orderDetl.getMaktx(), orderDetl.getModel(), orderDetl.getSpecs(), | 
|                         orderDetl.getBatch(), orderDetl.getBrand(), orderDetl.getBarcode(), orderDetl.getOrderNo(), orderDetl.getAnfme()); | 
|                 locDto.setOrderDetlId(orderDetl.getId()); | 
|                 locDto.setTkType(orderDetl.getTkType()); | 
|                 locDtos.add(locDto); | 
|             } | 
|         } | 
|   | 
|         return R.ok().add(locDtos); | 
|     } | 
|   | 
|     @PostMapping("/out/pakout/auth") | 
|     @ManagerAuth(memo = "订单出库") | 
|     public synchronized R pakout(@RequestBody PakoutRequest request) throws InterruptedException { | 
|         List<LocDto> locDtos = request.getTableCache(); | 
|         String optionValue = request.getOptionValue(); | 
|         if (Cools.isEmpty(locDtos)) { | 
|             return R.parse(BaseRes.PARAM); | 
|         } | 
|   | 
|         boolean lack = true; | 
|         for (LocDto locDto : locDtos) { | 
|             if (!locDto.isLack()) { | 
|                 lack = false; | 
|                 break; | 
|             } | 
|         } | 
|         if (lack) { | 
|             return R.error("库存不足"); | 
|         } | 
|   | 
|         Thread.sleep(1000L); | 
|   | 
|         List<StockOutParam> stockOutParams = new ArrayList<>(); | 
|         Map<Integer, StockOutParam> staNoMap = new HashMap<>(); | 
|         Set<String> processedKeys = new HashSet<>(); // 防止重复添加 brand+staNo | 
|   | 
|         for (LocDto locDto : locDtos) { | 
|             Integer staNo = locDto.getStaNo(); | 
|             String brand = locDto.getBrand(); | 
|             String key = staNo + "_" + brand; | 
|   | 
|             // 获取或创建 StockOutParam(按出库口合并) | 
|             StockOutParam stockOutParam = staNoMap.get(staNo); | 
|             if (stockOutParam == null) { | 
|                 stockOutParam = new StockOutParam(); | 
|                 stockOutParam.setOutSite(staNo); | 
|                 stockOutParam.setOrderNo(locDto.getOrderNo()); | 
|                 stockOutParam.setLocDetls(new ArrayList<>()); | 
|                 stockOutParams.add(stockOutParam); | 
|                 staNoMap.put(staNo, stockOutParam); | 
|             } | 
|   | 
|             // 避免重复添加相同brand的数据 | 
|             if (processedKeys.contains(key)) continue; | 
|             processedKeys.add(key); | 
|   | 
|             List<LocDetl> locDetls1 = locDetlService.selectList( | 
|                     new EntityWrapper<LocDetl>().eq("brand", brand)); | 
|             for (LocDetl locDetl : locDetls1) { | 
|                 StockOutParam.LocDetl detl = new StockOutParam.LocDetl(); | 
|                 detl.setLocNo(locDetl.getLocNo()); | 
|                 detl.setBrand(locDetl.getBrand()); | 
|                 detl.setModel(locDetl.getModel()); | 
|                 detl.setCount(locDetl.getAnfme()); | 
|                 stockOutParam.getLocDetls().add(detl); | 
|             } | 
|         } | 
|   | 
|         // 执行出库逻辑 | 
|         for (StockOutParam stockOutParam : stockOutParams) { | 
|             BasDevp staNo = basDevpService.checkSiteStatus(stockOutParam.getOutSite()); | 
|   | 
|             List<LocDetlDto> locDetlDtos = new ArrayList<>(); | 
|             for (StockOutParam.LocDetl paramLocDetl : stockOutParam.getLocDetls()) { | 
|                 LocDetl one = locDetlService.selectOne(new EntityWrapper<LocDetl>() | 
|                         .eq("loc_no", paramLocDetl.getLocNo()) | 
|                         .eq("brand", paramLocDetl.getBrand()) | 
|                         .eq("model", paramLocDetl.getModel())); | 
|   | 
|                 if (one != null) { | 
|                     // 判断是否为盘点单(docType == 23),如果不是则校验合格性 | 
|                     Order order = orderService.selectByNo(stockOutParam.getOrderNo()); | 
|                     if (order.getDocType() != 23) { | 
|                         if (order.getDocType() == 26 || order.getDocType() == 27) { | 
|                             if ("合格".equals(one.getThreeCode())) { | 
|                                 throw new CoolException(one.getModel() + "卷是合格: " + one.getThreeCode()); | 
|                             } | 
|                         } else { | 
|                             // 3077 3106 只有合格能出 | 
|                             if((stockOutParam.getOutSite() == 3077 || stockOutParam.getOutSite() == 3106) && !"合格".equals(one.getThreeCode())) { | 
|                                 throw new CoolException(one.getModel() + "卷不合格:" + one.getThreeCode()); | 
|                             } | 
|                             // 2041 只有待判能出 | 
|                             if(stockOutParam.getOutSite() == 2041 && null != one.getThreeCode()) { | 
|                                 throw new CoolException(one.getModel() + "卷不为待判:" + one.getThreeCode()); | 
|                             } | 
|                         } | 
|                     } | 
|   | 
|                     locDetlDtos.add(new LocDetlDto(one, paramLocDetl.getCount(), stockOutParam.getOrderNo())); | 
|                 } | 
|   | 
|             } | 
|   | 
|             if (!locDetlDtos.isEmpty()) { | 
|                 LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>() | 
|                         .eq("loc_no", locDetlDtos.get(0).getLocDetl().getLocNo())); | 
|                 if ("F".equals(locMast.getLocSts()) || "D".equals(locMast.getLocSts())) { | 
|                     Order order = orderService.selectByNo(stockOutParam.getOrderNo()); | 
|                     IoWorkType ioWorkType = (order.getDocType() != null && order.getDocType() == 23) | 
|                             ? IoWorkType.CHECK_OUT : null; | 
|                     if (order.getDocType() != null) { | 
|                         if (order.getDocType() == 26 || order.getDocType() == 27) { | 
|                             ioWorkType = IoWorkType.ALL_OUT; | 
|                         } | 
|                     } | 
|                     if (order.getDocType() == 27) { | 
|                         workService.stockOut2(staNo, locDetlDtos, | 
|                                 ioWorkType, | 
|                                 getUserId(), optionValue); | 
|                     }else { | 
|                         workService.stockOut(staNo, locDetlDtos, | 
|                                 ioWorkType, | 
|                                 getUserId(), optionValue); | 
|                     } | 
|                 } else { | 
|                     throw new CoolException("所选库位状态不为F/D,库位号:" + | 
|                             locMast.getLocNo() + ",当前状态:" + | 
|                             locMast.getLocSts() + "-" + locMast.getLocSts$()); | 
|                 } | 
|             } else { | 
|                 throw new CoolException("库存不存在"); | 
|             } | 
|         } | 
|   | 
|         return R.ok(); | 
|     } | 
|   | 
|   | 
|     @PostMapping("/out/refund/loc/auth") | 
|     @ManagerAuth(memo = "订单出库") | 
|     public synchronized R refundLoc(@RequestBody List<LocDto> locDtos) throws InterruptedException { | 
|         Long userId = getUserId(); | 
|         DocType docType = docTypeService.selectOrAdd("退货入库单", Boolean.TRUE); | 
|         Date now = new Date(); | 
|         long nowOrderNo = System.currentTimeMillis(); | 
|         Order order = new Order( | 
|                 String.valueOf(snowflakeIdWorker.nextId()),    // 编号[非空] | 
|                 "TK" + nowOrderNo,    // 订单编号 | 
|                 DateUtils.convert(now),    // 单据日期 | 
|                 docType.getDocId(),    // 单据类型 | 
|                 null,    // 项目编号 | 
|                 null,    // | 
|                 null,    // 调拨项目编号 | 
|                 null,    // 初始票据号 | 
|                 null,    // 票据号 | 
|                 null,    // 客户编号 | 
|                 null,    // 客户 | 
|                 null,    // 联系方式 | 
|                 null,    // 操作人员 | 
|                 null,    // 合计金额 | 
|                 null,    // 优惠率 | 
|                 null,    // 优惠金额 | 
|                 null,    // 销售或采购费用合计 | 
|                 null,    // 实付金额 | 
|                 null,    // 付款类型 | 
|                 null,    // 业务员 | 
|                 null,    // 结算天数 | 
|                 null,    // 邮费支付类型 | 
|                 null,    // 邮费 | 
|                 null,    // 付款时间 | 
|                 null,    // 发货时间 | 
|                 null,    // 物流名称 | 
|                 null,    // 物流单号 | 
| //                    2L,    // 订单状态 | 
|                 1L,    // 订单状态 | 
|                 1,    // 状态 | 
|                 userId,    // 添加人员 | 
|                 now,    // 添加时间 | 
|                 userId,    // 修改人员 | 
|                 now,    // 修改时间 | 
|                 null    // 备注 | 
|         ); | 
|         if (!orderService.insert(order)) { | 
|             throw new CoolException("保存订单主档失败"); | 
|         } | 
|         // 单据明细档 | 
|         int i = 0; | 
|         List<LocDto> locDtosList = new ArrayList<>(); | 
|         List<String> batchList = new ArrayList<>(); | 
|         for (LocDto locDto : locDtos) { | 
|             if (!batchList.contains(locDto.getBatch())) { | 
|                 batchList.add(locDto.getBatch()); | 
|                 locDtosList.add(locDto); | 
|             } | 
|         } | 
|         for (LocDto locDto : locDtosList) { | 
|             i++; | 
|             Mat mat = matService.selectByMatnr(locDto.getMatnr()); | 
|             if (Cools.isEmpty(mat)) { | 
|                 throw new CoolException(locDto.getMatnr() + "物料编码检索失败,请先添加商品"); | 
|             } | 
|             OrderDetl orderDetl = new OrderDetl(); | 
|             orderDetl.sync(mat); | 
|             orderDetl.setSuppCode(String.valueOf(i));  // 行号 | 
|             orderDetl.setManu(locDto.getLocNo());  //库位号 | 
|             orderDetl.setBatch(locDto.getBatch()); //木箱编码 | 
|             orderDetl.setAnfme(locDto.getAnfme());//出库数量 | 
|             orderDetl.setModel(locDto.getModel());//批次 | 
|             orderDetl.setSpecs(locDto.getSpecs());//规格 | 
|             orderDetl.setBrand(locDto.getBrand());//木箱类型 | 
|             orderDetl.setBarcode(locDto.getZpallet());//木箱类型 | 
| //                orderDetl.setWorkQty(locDetl.getAnfme()); | 
|             orderDetl.setWorkQty(0.0); | 
|             orderDetl.setOrderId(order.getId()); | 
|             orderDetl.setOrderNo(order.getOrderNo()); | 
|             orderDetl.setCreateBy(userId); | 
|             orderDetl.setCreateTime(now); | 
|             orderDetl.setUpdateBy(userId); | 
|             orderDetl.setUpdateTime(now); | 
|             orderDetl.setStatus(1); | 
|             orderDetl.setQty(0.0D); | 
|             if (!orderDetlService.insert(orderDetl)) { | 
|                 throw new CoolException("生成单据明细失败,请联系管理员"); | 
|             } | 
|   | 
|             OrderDetl orderDetl1 = orderDetlService.selectById(locDto.getOrderDetlId()); | 
|             orderDetl1.setTkType(1); | 
|             orderDetlService.updateById(orderDetl1); | 
|   | 
|         } | 
|   | 
|         return R.ok(); | 
|     } | 
|   | 
| } |