BusinessServiceImpl.java 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858
  1. package com.ruoyi.ams.business;
  2. import com.alibaba.fastjson.JSON;
  3. import com.ruoyi.ams.agv.ndc.common.ByteUtil;
  4. import com.ruoyi.ams.agv.ndc.common.CRC16Util;
  5. import com.ruoyi.ams.agv.ndc.domain.AmsTask;
  6. import com.ruoyi.ams.agv.ndc.service.IAmsTaskService;
  7. import com.ruoyi.ams.box.service.IWmsBoxInfoService;
  8. import com.ruoyi.ams.config.domain.AsnSoStrategy;
  9. import com.ruoyi.ams.config.domain.dto.*;
  10. import com.ruoyi.ams.config.domain.vo.FlowConfigHeaderVO;
  11. import com.ruoyi.ams.config.mapper.AsnSoStrategyMapper;
  12. import com.ruoyi.ams.config.service.IFlowConfigHeaderService;
  13. import com.ruoyi.ams.config.service.LocationAllocationStrategy;
  14. import com.ruoyi.ams.inv.mapper.InvLotLocIdMapper;
  15. import com.ruoyi.ams.inv.service.IInvLotAttService;
  16. import com.ruoyi.ams.inv.service.IInvLotLocIdService;
  17. import com.ruoyi.ams.task.domain.WcsTask;
  18. import com.ruoyi.ams.task.dto.WcsTaskLocationDTO;
  19. import com.ruoyi.ams.task.mapper.WcsTaskMapper;
  20. import com.ruoyi.ams.task.service.IWcsTaskService;
  21. import com.ruoyi.base.constant.Constant;
  22. import com.ruoyi.base.domain.BaseLocationInfo;
  23. import com.ruoyi.base.domain.BaseLocationZone;
  24. import com.ruoyi.base.domain.BaseSku;
  25. import com.ruoyi.base.domain.dto.BaseLocationInfoSameColDTO;
  26. import com.ruoyi.base.domain.vo.BaseLocationLotattVO;
  27. import com.ruoyi.base.mapper.BaseLocationInfoMapper;
  28. import com.ruoyi.base.service.IBaseLocationInfoService;
  29. import com.ruoyi.base.service.IBaseSkuService;
  30. import com.ruoyi.common.core.domain.AjaxResult;
  31. import com.ruoyi.common.core.redis.RedisCache;
  32. import com.ruoyi.common.core.redis.RedisKey;
  33. import com.ruoyi.common.exception.ServiceException;
  34. import com.ruoyi.common.utils.StringUtils;
  35. import com.ruoyi.common.utils.uuid.SnowflakeIdWorker;
  36. import lombok.extern.slf4j.Slf4j;
  37. import org.springframework.beans.factory.annotation.Autowired;
  38. import org.springframework.stereotype.Service;
  39. import org.springframework.transaction.annotation.Transactional;
  40. import java.math.BigDecimal;
  41. import java.util.*;
  42. import java.util.stream.Collectors;
  43. @Slf4j
  44. @Service
  45. public class BusinessServiceImpl implements IBusinessService {
  46. @Autowired
  47. private IBusinessService businessService;
  48. @Autowired
  49. private IBaseLocationInfoService baseLocationInfoService;
  50. @Autowired
  51. private LocationAllocationStrategy locationAllocationStrategy;
  52. @Autowired
  53. private InvLotLocIdMapper invLotLocIdMapper;
  54. @Autowired
  55. private IInvLotLocIdService invLotLocIdService;
  56. @Autowired
  57. private IInvLotAttService iInvLotAttService;
  58. @Autowired
  59. private WcsTaskMapper wcsTaskMapper;
  60. @Autowired
  61. private AsnSoStrategyMapper asnSoStrategyMapper;
  62. @Autowired
  63. private BaseLocationInfoMapper baseLocationInfoMapper;
  64. @Autowired
  65. private IBaseSkuService baseSkuService;
  66. @Autowired
  67. private RedisCache redisCache;
  68. @Autowired
  69. private IWmsBoxInfoService wmsBoxInfoService;
  70. @Autowired
  71. private IWcsTaskService wcsTaskService;
  72. @Autowired
  73. private IAmsTaskService amsTaskService;
  74. @Autowired
  75. private IFlowConfigHeaderService flowConfigHeaderService;
  76. public static int geniKey(String taskNo) {
  77. int res = CRC16Util.calcCrc16(ByteUtil.string2byteArray(taskNo));
  78. if (res == 0) {
  79. BigDecimal t = new BigDecimal(taskNo);
  80. t = t.add(BigDecimal.ONE);
  81. return geniKey(t.toString());
  82. } else {
  83. return res;
  84. }
  85. }
  86. @Override
  87. public AjaxResult agvCall(Long flowId, AgvCallDTO agvCallDTO) {
  88. //查询所属流程
  89. FlowConfigHeaderVO flowConfigHeaderVO = flowConfigHeaderService.selectFlowConfigHeaderById(flowId);
  90. List<AgvCallDTO> agvCallDTOList = new ArrayList<>();
  91. agvCallDTO.setWarehouseId(Constant.WAREHOUSE_ID);
  92. agvCallDTOList.add(agvCallDTO);
  93. return businessService.agvCall(flowConfigHeaderVO, agvCallDTOList);
  94. }
  95. @Override
  96. public AjaxResult agvCall(FlowConfigHeaderVO flowConfigHeaderVO, AgvCallDTO agvCallDTO) {
  97. List<AgvCallDTO> agvCallDTOList = new ArrayList<>();
  98. List<AgvCallItemDTO> callItemDTOList = new ArrayList<>();
  99. AgvCallItemDTO callItemDTO = new AgvCallItemDTO();
  100. callItemDTO.setLotattDTO(new LotattDTO());
  101. callItemDTO.setExtParam(agvCallDTO.getExtParam());
  102. callItemDTOList.add(callItemDTO);
  103. agvCallDTO.setAgvCallItemDTOList(callItemDTOList);
  104. agvCallDTOList.add(agvCallDTO);
  105. return businessService.agvCall(flowConfigHeaderVO, agvCallDTOList);
  106. }
  107. @Transactional
  108. @Override
  109. public AjaxResult agvCall(FlowConfigHeaderVO flowConfigHeaderVO, List<AgvCallDTO> agvCallDTOList) {
  110. //唯一操作标识,用于redis标记。报错时根据该id进行删除
  111. Long token = SnowflakeIdWorker.generateId();
  112. try {
  113. //查询全局配置策略
  114. AsnSoStrategy asnSoStrategy = asnSoStrategyMapper.selectAsnSoStrategy();
  115. for (AgvCallDTO agvCallDTO : agvCallDTOList) {
  116. //如果是入库把起始库位相同的数据整合到一起生成库存记录
  117. BaseLocationInfo locationFrom = null;
  118. BaseLocationInfo locationTo = null;
  119. List<WcsTask> wcsTaskList = new ArrayList<>();
  120. String paramLocationFrom = agvCallDTO.getLocationFrom();
  121. String paramLocationTo = agvCallDTO.getLocationTo();
  122. List<String> zoneIdList = new ArrayList<>();
  123. if (StringUtils.isEmpty(paramLocationFrom)) {
  124. paramLocationFrom = flowConfigHeaderVO.getLocationFrom();
  125. }
  126. if (StringUtils.isEmpty(paramLocationTo)) {
  127. paramLocationTo = flowConfigHeaderVO.getLocationTo();
  128. }
  129. if (!StringUtils.isEmpty(flowConfigHeaderVO.getLocationFrom())) {
  130. zoneIdList = Arrays.stream(flowConfigHeaderVO.getLocationFrom().split(",")).collect(Collectors.toList());
  131. }
  132. if (flowConfigHeaderVO.getFlowType().equals("ASN")) {
  133. // 统计入库箱数
  134. List<AgvCallItemDTO> agvCallItemDTOList = agvCallDTO.getAgvCallItemDTOList();
  135. int boxNum = agvCallItemDTOList.size();
  136. // int boxNum = agvCallItemDTOList.stream()
  137. // .mapToInt(v -> v.getQty().intValue())
  138. // .reduce(Integer::sum).getAsInt();
  139. asnSoStrategy.setAsnHeightLimit(boxNum + "");
  140. log.info("统计箱数量:" + boxNum);
  141. List<BaseLocationInfo> locationFromList = this.convertLocation(paramLocationFrom, agvCallDTO.getWarehouseId(), null);
  142. List<BaseLocationInfo> locationToList = this.convertLocation(paramLocationTo, agvCallDTO.getWarehouseId(), "shift_no+ 0,shift_index");
  143. locationFrom = this.zoneLocationAllocation(locationFromList, "locationFrom", "ASN", asnSoStrategy, token);
  144. locationTo = this.zoneLocationAllocation(locationToList, "locationTo", "ASN", asnSoStrategy, token);
  145. wcsTaskList.addAll(this.genTask(locationFrom, locationTo, flowConfigHeaderVO, agvCallDTO, token));
  146. } else if (flowConfigHeaderVO.getFlowType().equals("SO")) {
  147. AgvCallItemDTO agvCall = agvCallDTO.getAgvCallItemDTOList().get(0);
  148. List<BaseLocationInfo> locationToList = this.convertLocation(paramLocationTo, agvCallDTO.getWarehouseId(), null);
  149. HashMap<String, String> hashMap = JSON.parseObject(JSON.toJSONString(agvCall.getLotattDTO()), HashMap.class);
  150. List<BaseLocationInfo> locationFromList = baseLocationInfoMapper.selectSortedLocationLotattListByZoneIdListOrderBy(zoneIdList
  151. , agvCallDTO.getWarehouseId(), hashMap, agvCall.getSku(), "inv.create_time");
  152. locationFrom = this.zoneLocationAllocation(locationFromList, "locationFrom", "SO", asnSoStrategy, token);
  153. locationTo = this.zoneLocationAllocation(locationToList, "locationTo", "SO", asnSoStrategy, token);
  154. wcsTaskList.addAll(this.genTask(locationFrom, locationTo, flowConfigHeaderVO, agvCallDTO, token));
  155. } else if (flowConfigHeaderVO.getFlowType().equals("MV")) {
  156. List<BaseLocationInfo> locationFromList = this.convertLocation(paramLocationFrom, agvCallDTO.getWarehouseId(), null);
  157. List<BaseLocationInfo> locationToList = this.convertLocation(paramLocationTo, agvCallDTO.getWarehouseId(), null);
  158. locationFrom = this.zoneLocationAllocation(locationFromList, "locationFrom", "MV", asnSoStrategy, token);
  159. locationTo = this.zoneLocationAllocation(locationToList, "locationTo", "MV", asnSoStrategy, token);
  160. // 初始化库存
  161. if (agvCallDTO.getAgvCallItemDTOList().size() > 0) {
  162. iInvLotAttService.deleteInvLotAttBylocationId(locationFrom.getId());
  163. invLotLocIdService.deleteInvLotLocIdById(locationFrom.getId());
  164. invLotLocIdService.initInv(locationFrom.getId().toString(), agvCallDTO);
  165. }
  166. wcsTaskList.addAll(this.genTask(locationFrom, locationTo, flowConfigHeaderVO, agvCallDTO, token));
  167. }
  168. }
  169. return AjaxResult.success("任务下发成功");
  170. } catch (Exception e) {
  171. redisCache.unlockCacheObject(token); // 异常捕获的话就不能释放锁
  172. throw new ServiceException(e.getMessage(), token);
  173. }
  174. }
  175. @Transactional
  176. @Override
  177. public BaseLocationInfo inLocationAllocation(InWarehouseDTO inWarehouseDTO, Long token) {
  178. /**
  179. * 根据sku查询可以存放的zone
  180. * 根据每个zone的配置去分配可以存放的库位
  181. *
  182. * force
  183. * optimization
  184. * ignore
  185. */
  186. if (!StringUtils.isEmpty(inWarehouseDTO.getLocationTo())) { //指定库位则直接返回库位
  187. BaseLocationInfo baseLocationInfo = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(inWarehouseDTO.getLocationTo(), inWarehouseDTO.getWarehouseId());
  188. return baseLocationInfo;
  189. } else {
  190. if (StringUtils.isEmpty(inWarehouseDTO.getLocationZoneTo()) && StringUtils.isEmpty(inWarehouseDTO.getLocationTo())) { //不指定目标库位和区域
  191. // 没有指定目标的根据sku进行匹配并进行分配
  192. // 如果可以混放的区域不匹配物料也可以选择,否则只选择可以存放的区域
  193. AsnSoStrategy asnSoStrategy = asnSoStrategyMapper.selectAsnSoStrategy();
  194. BaseSku baseSku = baseSkuService.selectBaseSkuByCustomerId(Constant.CUSTOMER_ID, inWarehouseDTO.getSku());
  195. //判断是否强制同物料靠近,
  196. LotattDTO lotattDTO = inWarehouseDTO.getLotattDTO();
  197. Map<String, String> lotattMap = new HashMap<>();
  198. if (asnSoStrategy.getAsnSameLotatt1Flag().equals("optimization")) {
  199. lotattMap.put(asnSoStrategy.getAsnSameLotatt1Value(), lotattDTO.getAttr(asnSoStrategy.getAsnSameLotatt1Value()));
  200. }
  201. if (asnSoStrategy.getAsnSameLotatt2Flag().equals("optimization")) {
  202. lotattMap.put(asnSoStrategy.getAsnSameLotatt2Value(), lotattDTO.getAttr(asnSoStrategy.getAsnSameLotatt2Value()));
  203. }
  204. List<BaseLocationInfo> locationInfoList = new ArrayList<>();
  205. if (asnSoStrategy.getAsnSameSku().equals("force")) {
  206. List<String> colNo = baseLocationInfoMapper.selectSameSkuColNo(baseSku.getSku(), null, lotattMap);
  207. for (String s : colNo) {
  208. List<BaseLocationInfo> locs = baseLocationInfoService.selectNeighborLocation(s, null);
  209. locationInfoList.addAll(locs);
  210. }
  211. if (colNo == null || colNo.size() == 0) {
  212. colNo = baseLocationInfoMapper.selectSameSkuTypeColNo(baseSku.getSkuType(), null);
  213. for (String s : colNo) {
  214. List<BaseLocationInfo> locs = baseLocationInfoService.selectNeighborLocation(s, null);
  215. locationInfoList.addAll(locs);
  216. }
  217. }
  218. // List<BaseLocationInfo> locs = baseLocationInfoMapper.selectLocationByColNos(colNo);
  219. } else if (asnSoStrategy.getAsnSameSku().equals("optimization") || asnSoStrategy.getAsnSameSkuType().equals("optimization")) {
  220. List<String> skuColNo = baseLocationInfoMapper.selectSameSkuColNo(baseSku.getSku(), null, lotattMap);
  221. List<String> skuTypeColNo = baseLocationInfoMapper.selectSameSkuColNo(baseSku.getSkuType(), null, lotattMap);
  222. List<String> cols = new ArrayList<>();
  223. cols.addAll(skuColNo);
  224. cols.addAll(skuTypeColNo);
  225. List<BaseLocationInfo> locs = baseLocationInfoMapper.selectLocationByColNos(cols);
  226. locationInfoList.addAll(locs);
  227. } else {
  228. locationInfoList = baseLocationInfoMapper.selectLocationBindSku(baseSku.getSkuType());
  229. }
  230. return locationAllocationStrategy.filterLockLocation(locationInfoList, inWarehouseDTO, asnSoStrategy, token);
  231. } else {
  232. // 指定区域的
  233. List<BaseLocationInfo> locationInfoList = baseLocationInfoService.selectSortedLocatinListByZoneId(Long.parseLong(inWarehouseDTO.getLocationZoneTo()), inWarehouseDTO.getWarehouseId(), null);
  234. return locationAllocationStrategy.filterLockLocation(locationInfoList, token);
  235. }
  236. }
  237. }
  238. @Transactional
  239. @Override
  240. public BaseLocationInfo outInvAllocation(OutWarehouseDTO outWarehouseDTO, Long token) {
  241. /**
  242. * 指定位置出库
  243. */
  244. if (!StringUtils.isEmpty(outWarehouseDTO.getLocationFrom())) {
  245. BaseLocationInfo baseLocationInfo = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(outWarehouseDTO.getLocationFrom(), outWarehouseDTO.getWarehouseId());
  246. return baseLocationInfo;
  247. } else {
  248. //未指定明确位置出库
  249. List<Long> zoneIdList = new ArrayList<>();
  250. if (!StringUtils.isEmpty(outWarehouseDTO.getLocationZoneFrom())) {
  251. zoneIdList.add(Long.parseLong(outWarehouseDTO.getLocationZoneFrom()));
  252. } else {
  253. List<BaseLocationLotattVO> zoneList = invLotLocIdMapper.selectInvZoneBySkuLotatt(outWarehouseDTO.getSku(), outWarehouseDTO.getSkuType(), outWarehouseDTO.getLotattDTO());
  254. for (BaseLocationLotattVO vo : zoneList) {
  255. zoneIdList.add(vo.getZoneId());
  256. }
  257. }
  258. LotattDTO lotattDTO = outWarehouseDTO.getLotattDTO();
  259. List<BaseLocationLotattVO> locationInfoList = baseLocationInfoMapper.selectSortedLocationLotattListByZoneIdList(zoneIdList, outWarehouseDTO.getWarehouseId(), lotattDTO.getAttr());
  260. AsnSoStrategy asnSoStrategy = asnSoStrategyMapper.selectAsnSoStrategy();
  261. return locationAllocationStrategy.filterLockInv(locationInfoList, outWarehouseDTO, asnSoStrategy, token);
  262. }
  263. }
  264. @Override
  265. public BaseLocationInfo zoneLocationAllocation(List<BaseLocationInfo> locationInfoList, String locationType
  266. , String type, AsnSoStrategy asnSoStrategy, Long token) {
  267. BaseLocationInfo locationInfo = null;
  268. if (type.equals("ASN")) {
  269. //入库
  270. if (locationType.equals("locationFrom")) {
  271. for (BaseLocationInfo b : locationInfoList) {
  272. if (!b.getStockStatus().equals("00")) {
  273. continue;
  274. }
  275. if (!redisCache.lockCacheObject(RedisKey.LOCK_LOCATION + b.getId(), b.getId().toString(), token)) {
  276. continue;
  277. }
  278. locationInfo = b;
  279. break;
  280. }
  281. if (locationInfo == null) {
  282. throw new ServiceException("入库起始库位没有可以分配的空库位", token);
  283. }
  284. } else {
  285. for (BaseLocationInfo b : locationInfoList) {
  286. if (!b.getStockStatus().equals("00") || !b.getIsEmpty().equals("Y") || redisCache.checkIsLock(RedisKey.LOCK_LOCATION + b.getId())) {
  287. continue;
  288. }
  289. // 第六层不能放数量超过2的货
  290. int boxNum = Integer.parseInt(asnSoStrategy.getAsnHeightLimit());
  291. if (b.getShiftNo().equals("6")) {
  292. if (boxNum > 2) continue;
  293. } else {
  294. // 其他层数放置箱子数量不能超过6
  295. if (boxNum > 6) {
  296. log.error("入库箱数量不能超过6!");
  297. continue;
  298. }
  299. }
  300. if (!redisCache.lockCacheObject(RedisKey.LOCK_LOCATION + b.getId(), b.getId().toString(), token)) {
  301. continue;
  302. }
  303. locationInfo = b;
  304. break;
  305. }
  306. if (locationInfo == null) {
  307. throw new ServiceException("入库目标点没有可以分配的库位", token);
  308. }
  309. }
  310. } else if (type.equals("SO")) {
  311. //起始库位
  312. if (locationType.equals("locationFrom")) {
  313. for (BaseLocationInfo b : locationInfoList) {
  314. if (!b.getStockStatus().equals("00") || !b.getIsEmpty().equals("N") || redisCache.checkIsLock(RedisKey.LOCK_LOCATION + b.getId())) {
  315. continue;
  316. }
  317. if (!redisCache.lockCacheObject(RedisKey.LOCK_LOCATION + b.getId(), b.getId().toString(), token)) {
  318. continue;
  319. }
  320. // 判断起始库位上的库存质检状态是否可以出库
  321. boolean con = invLotLocIdService.verifyInventoryCanOutbound(b.getId().toString());
  322. if (!con) {
  323. continue;
  324. }
  325. locationInfo = b;
  326. break;
  327. }
  328. if (locationInfo == null) {
  329. throw new ServiceException("出库起始点没有可以分配的库存!", token);
  330. }
  331. } else { //目标库位
  332. for (BaseLocationInfo b : locationInfoList) {
  333. if (!b.getStockStatus().equals("00") || !b.getIsEmpty().equals("Y") || redisCache.checkIsLock(RedisKey.LOCK_LOCATION + b.getId())) {
  334. continue;
  335. }
  336. if (!redisCache.lockCacheObject(RedisKey.LOCK_LOCATION + b.getId(), b.getId().toString(), token)) {
  337. continue;
  338. }
  339. locationInfo = b;
  340. break;
  341. }
  342. if (locationInfo == null) {
  343. throw new ServiceException("出库目标点没有可以分配的库位", token);
  344. }
  345. }
  346. } else { //移库
  347. if (locationType.equals("locationFrom")) {
  348. for (BaseLocationInfo b : locationInfoList) {
  349. if (!b.getStockStatus().equals("00") || redisCache.checkIsLock(RedisKey.LOCK_LOCATION + b.getId())) {
  350. continue;
  351. }
  352. if (!redisCache.lockCacheObject(RedisKey.LOCK_LOCATION + b.getId(), b.getId().toString(), token)) {
  353. continue;
  354. }
  355. locationInfo = b;
  356. break;
  357. }
  358. //进行判断
  359. if (locationInfo == null) {
  360. throw new ServiceException("移库起始点没有可以分配的库位", token);
  361. }
  362. } else {
  363. for (BaseLocationInfo b : locationInfoList) {
  364. if (!b.getStockStatus().equals("00") || !b.getIsEmpty().equals("Y") || redisCache.checkIsLock(RedisKey.LOCK_LOCATION + b.getId())) {
  365. continue;
  366. }
  367. if (!redisCache.lockCacheObject(RedisKey.LOCK_LOCATION + b.getId(), b.getId().toString(), token)) {
  368. continue;
  369. }
  370. locationInfo = b;
  371. break;
  372. }
  373. //进行判断
  374. if (locationInfo == null) {
  375. throw new ServiceException("移库目标点没有可以分配的库位", token);
  376. }
  377. }
  378. }
  379. return locationInfo;
  380. }
  381. @Override
  382. public List<BaseLocationInfo> convertLocation(String locationNoOrZoneId, Long warehouseId, String orderBy) {
  383. List<BaseLocationInfo> locationInfoList = new ArrayList<>();
  384. if (!StringUtils.isEmpty(locationNoOrZoneId)) {
  385. String[] arr = locationNoOrZoneId.split(",");
  386. for (String obj : arr) {
  387. boolean isLocation = baseLocationInfoService.checkIsLocation(obj, warehouseId);
  388. if (isLocation) {
  389. BaseLocationInfo info = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(obj, warehouseId);
  390. locationInfoList.add(info);
  391. } else {
  392. List<BaseLocationInfo> infoList = baseLocationInfoService.selectSortedLocatinListByZoneId(Long.parseLong(obj), warehouseId, orderBy);
  393. locationInfoList.addAll(infoList);
  394. }
  395. }
  396. }
  397. return locationInfoList;
  398. }
  399. @Override
  400. public List<WcsTask> genTask(BaseLocationInfo locationFrom, BaseLocationInfo locationTo, FlowConfigHeaderVO flowConfigHeaderVO, AgvCallDTO agvCallDTO, Long token) {
  401. if (flowConfigHeaderVO.getLocationFromStrategyFlag().equals("N")) {
  402. if (locationFrom == null) {
  403. throw new ServiceException("起始库位不能为空", token);
  404. }
  405. }
  406. if (flowConfigHeaderVO.getLocationToStrategyFlag().equals("N")) {
  407. if (locationTo == null) {
  408. throw new ServiceException("目标库位不能为空", token);
  409. }
  410. }
  411. List<WcsTask> wcsTaskList = new ArrayList<>();
  412. if (StringUtils.isEmpty(flowConfigHeaderVO.getRootFlow())) {
  413. String taskNo = System.currentTimeMillis() + "";
  414. WcsTask wcsTask = new WcsTask();
  415. wcsTask.setTaskNo(taskNo);
  416. if (locationFrom != null) {
  417. wcsTask.setAreaFrom(locationFrom.getZoneId().toString());
  418. wcsTask.setLocationFrom(locationFrom.getId().toString());
  419. }
  420. if (locationTo != null) {
  421. wcsTask.setAreaTo(locationTo.getZoneId() + "");
  422. wcsTask.setLocationTo(locationTo.getId().toString());
  423. }
  424. wcsTask.setState(9L);
  425. wcsTask.setPriority(1L);
  426. wcsTask.setShopId(Constant.WAREHOUSE_ID.toString());
  427. wcsTask.setCreateDate(new Date());
  428. wcsTask.setBusinessType("01");
  429. wcsTask.setTaskType(Constant.TASK_TYPE.FORWARD.getValue());
  430. wcsTask.setExt8(token.toString());
  431. wcsTask.setExt7(flowConfigHeaderVO.getId().toString());
  432. wcsTask.setExt6(StringUtils.isNotEmpty(agvCallDTO.getToArea()) ? agvCallDTO.getToArea() : "");
  433. // 三向车叉尺方向(货叉朝左1,朝右2,中位或其他0)
  434. // 如果起始点是仓储区,左1,右2,我们系统A是靠马路也就是叉尺的右边
  435. if (locationFrom.getZoneId() != null
  436. && Objects.equals(locationFrom.getZoneId(), Constant.ZONE_TYPE.STORAGE.getValue())) {
  437. wcsTask.setExt4(locationFrom.getRowNo().equals("A") ? "2" : "1");
  438. }
  439. // 如果起始点是接驳位,默认给1
  440. if (locationFrom.getZoneId() != null
  441. && Objects.equals(locationFrom.getZoneId(), Constant.ZONE_TYPE.TRANSIT.getValue())) {
  442. wcsTask.setExt4("1");
  443. }
  444. wcsTask.setExtParam(agvCallDTO.getExtParam());
  445. wcsTaskList.add(wcsTask);
  446. businessService.addTask(wcsTask);
  447. } else {
  448. /*//获取对应的流程
  449. List<FlowConfigHeader> headerVOList = flowConfigHeaderService.sortFlowConfigHeader(Long.parseLong(flowConfigHeaderVO.getRootFlow()));
  450. AsnSoStrategy asnSoStrategy = asnSoStrategyMapper.selectAsnSoStrategy();
  451. String taskNo = System.currentTimeMillis() + "";
  452. WcsTask wcsTask = new WcsTask();
  453. wcsTask.setTaskNo(taskNo);
  454. wcsTask.setAreaFrom(locationFrom.getZoneId().toString());
  455. wcsTask.setLocationFrom(locationFrom.getId().toString());
  456. wcsTask.setAreaTo(locationTo.getZoneId() + "");
  457. wcsTask.setLocationTo(locationTo.getId().toString());
  458. wcsTask.setState(9L);
  459. wcsTask.setPriority(1L);
  460. wcsTask.setCreateDate(new Date());
  461. wcsTask.setBusinessType("01");
  462. wcsTask.setTaskType("");
  463. wcsTaskList.add(wcsTask);
  464. String beforeTaskNo = taskNo;
  465. for (FlowConfigHeader flowConfigHeader : headerVOList) {
  466. if (StringUtils.isEmpty(flowConfigHeader.getRelFlow()) && flowConfigHeader.getRootFlow().equals(flowConfigHeader.getId().toString())) {
  467. continue;
  468. }
  469. List<BaseLocationInfo> locationFromList = this.convertLocation(flowConfigHeader.getLocationFrom(), 1L);
  470. List<BaseLocationInfo> locationToList = this.convertLocation(flowConfigHeader.getLocationTo(), 1L);
  471. locationFrom = this.zoneLocationAllocation(locationFromList, "locationFrom", "MV", null, null);
  472. locationTo = this.zoneLocationAllocation(locationToList, "locationTo", "MV", null, null);
  473. String currentNo = SnowflakeIdWorker.generateId().toString();
  474. WcsTask child = new WcsTask();
  475. child.setTaskNo(currentNo);
  476. child.setParentTask(taskNo);
  477. child.setBeforeTask(beforeTaskNo);
  478. child.setAreaFrom(locationFrom.getZoneId().toString());
  479. child.setLocationFrom(locationFrom.getId().toString());
  480. child.setAreaTo(locationTo.getZoneId() + "");
  481. child.setLocationTo(locationTo.getId().toString());
  482. child.setState(9L);
  483. child.setPriority(1L);
  484. child.setCreateDate(new Date());
  485. child.setBusinessType("01");
  486. child.setTaskType("");
  487. wcsTaskList.add(child);
  488. beforeTaskNo = currentNo;
  489. }*/
  490. }
  491. return wcsTaskList;
  492. }
  493. @Transactional
  494. @Override
  495. public AjaxResult addTask(WcsTask wcsTask) {
  496. //锁定库位
  497. if (!StringUtils.isEmpty(wcsTask.getLocationFrom())) {
  498. baseLocationInfoService.updateLocationStockStatus(Long.parseLong(wcsTask.getLocationFrom()), Constant.STOCK_STATUS.STOCK10.getValue());
  499. }
  500. if (!StringUtils.isEmpty(wcsTask.getLocationTo())) {
  501. baseLocationInfoService.updateLocationStockStatus(Long.parseLong(wcsTask.getLocationTo()), Constant.STOCK_STATUS.STOCK10.getValue());
  502. }
  503. Integer priority = 1;
  504. if (!wcsTask.getTaskType().equals("OB")) {
  505. if (wcsTask.getPriority() == 99) {
  506. int current = wcsTaskMapper.selectCurrentPriority();
  507. priority = current - 100;
  508. } else {
  509. int current = wcsTaskMapper.selectCurrentPriority();
  510. priority = current + 10;
  511. }
  512. } else {
  513. //倒库任务顺序由原任务中间插入不需要获取
  514. priority = wcsTask.getPriority().intValue();
  515. }
  516. wcsTask.setPriority((long) priority);
  517. int result = wcsTaskMapper.insertWcsTask(wcsTask);
  518. if (result > 0) {
  519. return AjaxResult.success("任务生成成功");
  520. } else {
  521. throw new ServiceException("任务生成失败");
  522. }
  523. }
  524. @Override
  525. public AjaxResult addTaskList(List<WcsTask> wcsTaskList) {
  526. for (WcsTask wcsTask : wcsTaskList) {
  527. //锁定库位
  528. if (!StringUtils.isEmpty(wcsTask.getLocationFrom())) {
  529. baseLocationInfoService.updateLocationStockStatus(Long.parseLong(wcsTask.getLocationFrom()), Constant.STOCK_STATUS.STOCK10.getValue());
  530. }
  531. if (!StringUtils.isEmpty(wcsTask.getLocationTo())) {
  532. baseLocationInfoService.updateLocationStockStatus(Long.parseLong(wcsTask.getLocationTo()), Constant.STOCK_STATUS.STOCK10.getValue());
  533. }
  534. Integer priority = 1;
  535. if (!wcsTask.getTaskType().equals("OB")) {
  536. if (wcsTask.getPriority() == 99) {
  537. int current = wcsTaskMapper.selectCurrentPriority();
  538. priority = current - 100;
  539. } else {
  540. int current = wcsTaskMapper.selectCurrentPriority();
  541. priority = current + 10;
  542. }
  543. } else {
  544. //倒库任务顺序由原任务中间插入不需要获取
  545. priority = wcsTask.getPriority().intValue();
  546. }
  547. wcsTask.setPriority((long) priority);
  548. int result = wcsTaskMapper.insertWcsTask(wcsTask);
  549. if (result > 0) {
  550. return AjaxResult.success("任务生成成功");
  551. } else {
  552. throw new ServiceException("任务生成失败");
  553. }
  554. }
  555. return AjaxResult.success("");
  556. }
  557. @Override
  558. public AjaxResult sendTask(WcsTask wcsTask) {
  559. BaseLocationInfo locFrom = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(wcsTask.getLocationFrom(), Constant.WAREHOUSE_ID);
  560. BaseLocationInfo locTo = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(wcsTask.getLocationTo(), Constant.WAREHOUSE_ID);
  561. AmsTask amsTask = new AmsTask();
  562. amsTask.setTaskNo(wcsTask.getTaskNo());
  563. if (wcsTask.getBusinessType() == null || wcsTask.getBusinessType().equals("")) {
  564. amsTask.setBusinessType(Constant.TASK_BUSINESS_TYPE.TASK_01.getValue());
  565. } else {
  566. amsTask.setBusinessType(wcsTask.getBusinessType());
  567. }
  568. amsTask.setIsDelete(0);
  569. amsTask.setAciAccept(0);
  570. amsTask.setIkey((long) geniKey(amsTask.getTaskNo()));
  571. amsTask.setPriority(wcsTask.getPriority().intValue());
  572. // 充电任务直接传参数
  573. if (wcsTask.getBusinessType().equals(Constant.TASK_BUSINESS_TYPE.TASK_POWER.getValue())) {
  574. amsTask.setStFrom(Integer.parseInt(wcsTask.getLocationFrom()));
  575. amsTask.setStTo(Integer.parseInt(wcsTask.getLocationTo()));
  576. amsTask.setDeviceName(wcsTask.getDeviceName());
  577. } else {
  578. amsTask.setStFrom(locFrom.getAgvStation().intValue());
  579. amsTask.setStTo(locTo.getAgvStation().intValue());
  580. }
  581. amsTask.setExt1(wcsTask.getExt1());
  582. amsTask.setExt2(wcsTask.getExt2());
  583. amsTask.setExt3(wcsTask.getExt3());
  584. amsTask.setExt4(wcsTask.getExt4());
  585. if (wcsTask.getBusinessType().equals("m")) {
  586. //m类消息特殊处理
  587. wcsTask.setState(2L);
  588. int result = wcsTaskService.updateWcsTask(wcsTask);
  589. if (result > 0) {
  590. //更新
  591. return AjaxResult.success("下发成功");
  592. } else {
  593. return AjaxResult.error("下发失败");
  594. }
  595. } else {
  596. int result = amsTaskService.insertAmsTask(amsTask);
  597. if (result > 0) {
  598. //更新
  599. return AjaxResult.success("下发成功");
  600. } else {
  601. return AjaxResult.error("下发失败");
  602. }
  603. }
  604. }
  605. @Override
  606. public AjaxResult sendTaskList(List<WcsTask> wcsTaskList) {
  607. return null;
  608. }
  609. @Transactional
  610. @Override
  611. public void autoSend() {
  612. List<WcsTask> wcsTaskList = wcsTaskService.selectWcsUnallocated(Constant.WAREHOUSE_ID);
  613. if (wcsTaskList != null && wcsTaskList.size() > 0) {
  614. for (WcsTask wcsTask : wcsTaskList) {
  615. //如果是充电任务直接下发
  616. if (wcsTask.getBusinessType().equals(Constant.TASK_BUSINESS_TYPE.TASK_POWER.getValue()) ||
  617. wcsTask.getBusinessType().equals(Constant.TASK_BUSINESS_TYPE.TASK_m.getValue())) {
  618. log.info("定时充电/盘点取消任务直接下发");
  619. sendTask(wcsTask);
  620. wcsTask.setState(2L);
  621. wcsTaskService.updateWcsTask(wcsTask);
  622. break;
  623. }
  624. //转发任务
  625. if (StringUtils.isNotEmpty(wcsTask.getTaskType())
  626. && wcsTask.getTaskType().equals(Constant.TASK_TYPE.FORWARD.getValue())) {
  627. sendTask(wcsTask);
  628. wcsTask.setState(10L);
  629. wcsTaskService.updateWcsTask(wcsTask);
  630. break;
  631. }
  632. try {
  633. //任务下发判断
  634. businessService.taskDispatchStack(wcsTask);
  635. Thread.sleep(500);
  636. } catch (Exception e) {
  637. e.printStackTrace();
  638. }
  639. }
  640. }
  641. }
  642. @Transactional
  643. @Override
  644. public void autoSendTranSit() {
  645. // List<BaseLocationInfo> baseLocationInfos = baseLocationInfoService.selectSortedLocatinListByZoneId(Constant.ZONE_TYPE.TRANSIT.getValue()
  646. // , Constant.WAREHOUSE_ID, null);
  647. // for (BaseLocationInfo baseLocationInfo : baseLocationInfos) {
  648. // // 判断是否有货并且空闲
  649. // if (baseLocationInfo.getStockStatus().equals(Constant.STOCK_STATUS.STOCK00.getValue())
  650. // && baseLocationInfo.getIsEmpty().equals(Constant.IS_YES.N.name())) {
  651. // if (baseLocationInfo.getUserdefine1().equals("ASN")) {
  652. // AgvCallDTO agvCallDTO = new AgvCallDTO();
  653. // agvCallDTO.setLocationFrom(baseLocationInfo.getLocationNo());
  654. // businessService.agvCall(Constant.TRAN_STO_FLOW_ID, agvCallDTO);
  655. // } else if (baseLocationInfo.getUserdefine1().equals("SO_HG")) {
  656. // AgvCallDTO agvCallDTO = new AgvCallDTO();
  657. // agvCallDTO.setLocationFrom(baseLocationInfo.getLocationNo());
  658. // businessService.agvCall(Constant.TRAN_OUT_FLOW_ID, agvCallDTO);
  659. // } else if (baseLocationInfo.getUserdefine1().equals("SO_BHG")) {
  660. // AgvCallDTO agvCallDTO = new AgvCallDTO();
  661. // agvCallDTO.setLocationFrom(baseLocationInfo.getLocationNo());
  662. // businessService.agvCall(Constant.TRAN_OUT_BHG_FLOW_ID, agvCallDTO);
  663. // }
  664. // }
  665. // }
  666. }
  667. @Transactional
  668. @Override
  669. public boolean taskDispatchStack(WcsTask wcsTask) {
  670. /* boolean isSplit = taskService.taskSplit(wcsTask);
  671. //判断是否拆分如果拆分了直接跳过
  672. if(isSplit){
  673. return false;
  674. }*/
  675. //最后要执行的任务
  676. WcsTask currentTask = new WcsTask();
  677. //来源库位
  678. BaseLocationInfo basLocationInfoFrom = null;
  679. //目标区域
  680. BaseLocationZone basLocationZoneTo = null;
  681. //起始库位
  682. basLocationInfoFrom = baseLocationInfoService.selectBaseLocationInfoById(Long.parseLong(wcsTask.getLocationFrom()));
  683. //目标库位
  684. BaseLocationInfo locationInfoTo = baseLocationInfoService.selectBaseLocationInfoById(Long.parseLong(wcsTask.getLocationTo()));
  685. //TODO 前置任务未完成不进行下发
  686. if (businessService.taskDispatchCheck(wcsTask) == false) {
  687. return false;
  688. }
  689. if (basLocationInfoFrom != null) {
  690. if (basLocationInfoFrom.getIsEmpty().equals("Y")) {
  691. wcsTask.setRemark("起始库位为空无法进行任务");
  692. wcsTaskService.updateWcsTask(wcsTask);
  693. return false;
  694. }
  695. //起始库位巷道检测(起始库位检测是否同巷道)
  696. if (!StringUtils.isEmpty(basLocationInfoFrom.getColNo())) {
  697. List<BaseLocationInfo> locationInfoList = baseLocationInfoMapper.laneCheck(basLocationInfoFrom.getColNo(), "LANE_FROM", Constant.WAREHOUSE_ID);
  698. if (locationInfoList != null && locationInfoList.size() > 0) {
  699. wcsTask.setRemark("起始库位同列或同巷道有车辆在任务中,等待其他任务完成");
  700. wcsTaskService.updateWcsTask(wcsTask);
  701. return false;
  702. }
  703. }
  704. }
  705. //起始库位是地堆需要判断是否有阻挡
  706. if (basLocationInfoFrom.getLocationType().equals("2")) {
  707. //判断队列中是否有阻挡在当前任务之前
  708. List<WcsTaskLocationDTO> locationDTOS = wcsTaskService.selectTaskByColNo(basLocationInfoFrom.getColNo(), basLocationInfoFrom.getColIndex(), basLocationInfoFrom.getZoneId(), null);
  709. if (locationDTOS.size() > 0) {
  710. wcsTask.setRemark("队列中有其他任务阻挡,让其他任务先执行");
  711. wcsTaskService.updateWcsTask(wcsTask);
  712. return false;
  713. }
  714. //判断出库库位前是否有阻挡
  715. List<BaseLocationInfo> beforeLoc = baseLocationInfoService.selectBeforeLocationByColNo(basLocationInfoFrom.getColNo(), basLocationInfoFrom.getColIndex());
  716. if (beforeLoc != null) {
  717. for (BaseLocationInfo b : beforeLoc) {
  718. //如果前面库位不为空,或者状态占用
  719. //TODO 去除已经在任务中的
  720. if (b.getIsEmpty().equals("N")) {
  721. wcsTask.setRemark("有阻挡物,任务无法执行");
  722. wcsTaskService.updateWcsTask(wcsTask);
  723. return false;
  724. }
  725. }
  726. }
  727. }
  728. currentTask = wcsTask;
  729. //目标库位如果是地堆需要判断是否有阻挡
  730. if (locationInfoTo != null && locationInfoTo.getLocationType().equals("2")) {
  731. List<BaseLocationInfo> beforeLoc = baseLocationInfoService.selectBeforeLocationByColNo(locationInfoTo.getColNo(), locationInfoTo.getColIndex());
  732. if (beforeLoc != null) {
  733. for (BaseLocationInfo b : beforeLoc) {
  734. //跳过起始库位
  735. if (b.getId().equals(locationInfoTo.getId())) {
  736. continue;
  737. }
  738. //如果前面库位不为空,或者状态占用
  739. //TODO 排除已经在任务中的
  740. if (b.getIsEmpty().equals("N")) {
  741. currentTask.setRemark("目标库位前方有阻挡1");
  742. currentTask.setUpdateDate(new Date());
  743. wcsTaskService.updateWcsTask(currentTask);
  744. return false;
  745. }
  746. }
  747. }
  748. List<WcsTaskLocationDTO> dtos = wcsTaskService.selectTaskByColNoAfter(locationInfoTo.getColNo(), locationInfoTo.getColIndex(), locationInfoTo.getZoneId(), null);
  749. if (dtos != null && dtos.size() > 0) {
  750. currentTask.setRemark("目标库位同列有未完成的任务");
  751. wcsTaskService.updateWcsTask(currentTask);
  752. return false;
  753. }
  754. }
  755. //查询是否有更里面的位置可以存放
  756. if (locationInfoTo != null) {
  757. if (locationInfoTo.getZoneId() != 10) {
  758. String locationtoTmp = "";
  759. List<BaseLocationInfoSameColDTO> b = baseLocationInfoService.selectSameColCanToLoc(locationInfoTo.getColNo(), locationInfoTo.getColIndex());
  760. for (BaseLocationInfoSameColDTO bt : b) {
  761. if (bt.getIsOb() == false) {
  762. locationtoTmp = bt.getId().toString();
  763. } else {
  764. break;
  765. }
  766. }
  767. if (!StringUtils.isEmpty(locationtoTmp)) {
  768. wcsTask.setLocationTo(locationtoTmp);
  769. wcsTaskService.updateWcsTask(wcsTask);
  770. //释放原库位
  771. locationInfoTo.setStockStatus("00");
  772. baseLocationInfoService.updateBaseLocationInfo(locationInfoTo);
  773. //占用新库位
  774. BaseLocationInfo newlocationInfoTo = baseLocationInfoService.selectBaseLocationInfoById(Long.parseLong(locationtoTmp));
  775. newlocationInfoTo.setStockStatus("10");
  776. baseLocationInfoService.updateBaseLocationInfo(newlocationInfoTo);
  777. }
  778. }
  779. }
  780. currentTask.setState(10L);
  781. currentTask.setRemark("");
  782. if (wcsTaskService.updateWcsTask(currentTask) > 0) {
  783. AjaxResult result = businessService.sendTask(currentTask);
  784. if ((int) result.get(AjaxResult.CODE_TAG) == 500) {
  785. throw new ServiceException("自动下发任务失败:" + result.get("msg"));
  786. }
  787. return true;
  788. } else {
  789. return false;
  790. }
  791. }
  792. @Override
  793. public boolean taskDispatchCheck(WcsTask wcsTask) {
  794. if (!StringUtils.isEmpty(wcsTask.getBeforeTask())) {
  795. List<WcsTask> taskFindBeforeRecord = wcsTaskMapper.selectBeforeTask(wcsTask.getBeforeTask());
  796. if (taskFindBeforeRecord != null && taskFindBeforeRecord.size() > 0) {
  797. //log.info("前置任务未完成主任务无法下发{}",wcsTask);
  798. wcsTask.setRemark("前置任务未完成主任务无法下发");
  799. wcsTaskService.updateWcsTask(wcsTask);
  800. return false;
  801. }
  802. }
  803. return true;
  804. }
  805. }