BusinessServiceImpl.java 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  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. List<BaseLocationInfo> locationFromList = this.convertLocation(paramLocationFrom, agvCallDTO.getWarehouseId(), null);
  134. List<BaseLocationInfo> locationToList = this.convertLocation(paramLocationTo, agvCallDTO.getWarehouseId(), "shift_no+ 0,shift_index");
  135. locationFrom = this.zoneLocationAllocation(locationFromList, "locationFrom", "ASN", asnSoStrategy, token);
  136. locationTo = this.zoneLocationAllocation(locationToList, "locationTo", "ASN", asnSoStrategy, token);
  137. // 初始化库存
  138. if (agvCallDTO.getAgvCallItemDTOList().size() > 0) {
  139. iInvLotAttService.deleteInvLotAttBylocationId(locationFrom.getId());
  140. invLotLocIdService.deleteInvLotLocIdById(locationFrom.getId());
  141. invLotLocIdService.initInv(locationFrom.getId().toString(), agvCallDTO);
  142. }
  143. wcsTaskList.addAll(this.genTask(locationFrom, locationTo, flowConfigHeaderVO, agvCallDTO, token));
  144. } else if (flowConfigHeaderVO.getFlowType().equals("SO")) {
  145. AgvCallItemDTO agvCall = agvCallDTO.getAgvCallItemDTOList().get(0);
  146. List<BaseLocationInfo> locationToList = this.convertLocation(paramLocationTo, agvCallDTO.getWarehouseId(), null);
  147. HashMap<String, String> hashMap = JSON.parseObject(JSON.toJSONString(agvCall.getLotattDTO()), HashMap.class);
  148. List<BaseLocationInfo> locationFromList = baseLocationInfoMapper.selectSortedLocationLotattListByZoneIdListOrderBy(zoneIdList
  149. , agvCallDTO.getWarehouseId(), hashMap, agvCall.getSku(), "inv.create_time");
  150. locationFrom = this.zoneLocationAllocation(locationFromList, "locationFrom", "SO", asnSoStrategy, token);
  151. locationTo = this.zoneLocationAllocation(locationToList, "locationTo", "SO", asnSoStrategy, token);
  152. wcsTaskList.addAll(this.genTask(locationFrom, locationTo, flowConfigHeaderVO, agvCallDTO, token));
  153. } else if (flowConfigHeaderVO.getFlowType().equals("MV")) {
  154. List<BaseLocationInfo> locationFromList = this.convertLocation(paramLocationFrom, agvCallDTO.getWarehouseId(), null);
  155. List<BaseLocationInfo> locationToList = this.convertLocation(paramLocationTo, agvCallDTO.getWarehouseId(), null);
  156. locationFrom = this.zoneLocationAllocation(locationFromList, "locationFrom", "MV", asnSoStrategy, token);
  157. locationTo = this.zoneLocationAllocation(locationToList, "locationTo", "MV", asnSoStrategy, token);
  158. // 初始化库存
  159. if (agvCallDTO.getAgvCallItemDTOList().size() > 0) {
  160. iInvLotAttService.deleteInvLotAttBylocationId(locationFrom.getId());
  161. invLotLocIdService.deleteInvLotLocIdById(locationFrom.getId());
  162. invLotLocIdService.initInv(locationFrom.getId().toString(), agvCallDTO);
  163. }
  164. wcsTaskList.addAll(this.genTask(locationFrom, locationTo, flowConfigHeaderVO, agvCallDTO, token));
  165. }
  166. }
  167. return AjaxResult.success("任务下发成功");
  168. } catch (Exception e) {
  169. redisCache.unlockCacheObject(token); // 异常捕获的话就不能释放锁
  170. throw new ServiceException(e.getMessage(), token);
  171. }
  172. }
  173. @Transactional
  174. @Override
  175. public BaseLocationInfo inLocationAllocation(InWarehouseDTO inWarehouseDTO, Long token) {
  176. /**
  177. * 根据sku查询可以存放的zone
  178. * 根据每个zone的配置去分配可以存放的库位
  179. *
  180. * force
  181. * optimization
  182. * ignore
  183. */
  184. if (!StringUtils.isEmpty(inWarehouseDTO.getLocationTo())) { //指定库位则直接返回库位
  185. BaseLocationInfo baseLocationInfo = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(inWarehouseDTO.getLocationTo(), inWarehouseDTO.getWarehouseId());
  186. return baseLocationInfo;
  187. } else {
  188. if (StringUtils.isEmpty(inWarehouseDTO.getLocationZoneTo()) && StringUtils.isEmpty(inWarehouseDTO.getLocationTo())) { //不指定目标库位和区域
  189. // 没有指定目标的根据sku进行匹配并进行分配
  190. // 如果可以混放的区域不匹配物料也可以选择,否则只选择可以存放的区域
  191. AsnSoStrategy asnSoStrategy = asnSoStrategyMapper.selectAsnSoStrategy();
  192. BaseSku baseSku = baseSkuService.selectBaseSkuByCustomerId(Constant.CUSTOMER_ID, inWarehouseDTO.getSku());
  193. //判断是否强制同物料靠近,
  194. LotattDTO lotattDTO = inWarehouseDTO.getLotattDTO();
  195. Map<String, String> lotattMap = new HashMap<>();
  196. if (asnSoStrategy.getAsnSameLotatt1Flag().equals("optimization")) {
  197. lotattMap.put(asnSoStrategy.getAsnSameLotatt1Value(), lotattDTO.getAttr(asnSoStrategy.getAsnSameLotatt1Value()));
  198. }
  199. if (asnSoStrategy.getAsnSameLotatt2Flag().equals("optimization")) {
  200. lotattMap.put(asnSoStrategy.getAsnSameLotatt2Value(), lotattDTO.getAttr(asnSoStrategy.getAsnSameLotatt2Value()));
  201. }
  202. List<BaseLocationInfo> locationInfoList = new ArrayList<>();
  203. if (asnSoStrategy.getAsnSameSku().equals("force")) {
  204. List<String> colNo = baseLocationInfoMapper.selectSameSkuColNo(baseSku.getSku(), null, lotattMap);
  205. for (String s : colNo) {
  206. List<BaseLocationInfo> locs = baseLocationInfoService.selectNeighborLocation(s, null);
  207. locationInfoList.addAll(locs);
  208. }
  209. if (colNo == null || colNo.size() == 0) {
  210. colNo = baseLocationInfoMapper.selectSameSkuTypeColNo(baseSku.getSkuType(), null);
  211. for (String s : colNo) {
  212. List<BaseLocationInfo> locs = baseLocationInfoService.selectNeighborLocation(s, null);
  213. locationInfoList.addAll(locs);
  214. }
  215. }
  216. // List<BaseLocationInfo> locs = baseLocationInfoMapper.selectLocationByColNos(colNo);
  217. } else if (asnSoStrategy.getAsnSameSku().equals("optimization") || asnSoStrategy.getAsnSameSkuType().equals("optimization")) {
  218. List<String> skuColNo = baseLocationInfoMapper.selectSameSkuColNo(baseSku.getSku(), null, lotattMap);
  219. List<String> skuTypeColNo = baseLocationInfoMapper.selectSameSkuColNo(baseSku.getSkuType(), null, lotattMap);
  220. List<String> cols = new ArrayList<>();
  221. cols.addAll(skuColNo);
  222. cols.addAll(skuTypeColNo);
  223. List<BaseLocationInfo> locs = baseLocationInfoMapper.selectLocationByColNos(cols);
  224. locationInfoList.addAll(locs);
  225. } else {
  226. locationInfoList = baseLocationInfoMapper.selectLocationBindSku(baseSku.getSkuType());
  227. }
  228. return locationAllocationStrategy.filterLockLocation(locationInfoList, inWarehouseDTO, asnSoStrategy, token);
  229. } else {
  230. // 指定区域的
  231. List<BaseLocationInfo> locationInfoList = baseLocationInfoService.selectSortedLocatinListByZoneId(Long.parseLong(inWarehouseDTO.getLocationZoneTo()), inWarehouseDTO.getWarehouseId(), null);
  232. return locationAllocationStrategy.filterLockLocation(locationInfoList, token);
  233. }
  234. }
  235. }
  236. @Transactional
  237. @Override
  238. public BaseLocationInfo outInvAllocation(OutWarehouseDTO outWarehouseDTO, Long token) {
  239. /**
  240. * 指定位置出库
  241. */
  242. if (!StringUtils.isEmpty(outWarehouseDTO.getLocationFrom())) {
  243. BaseLocationInfo baseLocationInfo = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(outWarehouseDTO.getLocationFrom(), outWarehouseDTO.getWarehouseId());
  244. return baseLocationInfo;
  245. } else {
  246. //未指定明确位置出库
  247. List<Long> zoneIdList = new ArrayList<>();
  248. if (!StringUtils.isEmpty(outWarehouseDTO.getLocationZoneFrom())) {
  249. zoneIdList.add(Long.parseLong(outWarehouseDTO.getLocationZoneFrom()));
  250. } else {
  251. List<BaseLocationLotattVO> zoneList = invLotLocIdMapper.selectInvZoneBySkuLotatt(outWarehouseDTO.getSku(), outWarehouseDTO.getSkuType(), outWarehouseDTO.getLotattDTO());
  252. for (BaseLocationLotattVO vo : zoneList) {
  253. zoneIdList.add(vo.getZoneId());
  254. }
  255. }
  256. LotattDTO lotattDTO = outWarehouseDTO.getLotattDTO();
  257. List<BaseLocationLotattVO> locationInfoList = baseLocationInfoMapper.selectSortedLocationLotattListByZoneIdList(zoneIdList, outWarehouseDTO.getWarehouseId(), lotattDTO.getAttr());
  258. AsnSoStrategy asnSoStrategy = asnSoStrategyMapper.selectAsnSoStrategy();
  259. return locationAllocationStrategy.filterLockInv(locationInfoList, outWarehouseDTO, asnSoStrategy, token);
  260. }
  261. }
  262. @Override
  263. public BaseLocationInfo zoneLocationAllocation(List<BaseLocationInfo> locationInfoList, String locationType
  264. , String type, AsnSoStrategy asnSoStrategy, Long token) {
  265. BaseLocationInfo locationInfo = null;
  266. if (type.equals("ASN")) {
  267. //入库
  268. if (locationType.equals("locationFrom")) {
  269. for (BaseLocationInfo b : locationInfoList) {
  270. if (!b.getStockStatus().equals("00")) {
  271. continue;
  272. }
  273. if (!redisCache.lockCacheObject(RedisKey.LOCK_LOCATION + b.getId(), b.getId().toString(), token)) {
  274. continue;
  275. }
  276. locationInfo = b;
  277. break;
  278. }
  279. if (locationInfo == null) {
  280. throw new ServiceException("入库起始库位没有可以分配的空库位", token);
  281. }
  282. } else {
  283. for (BaseLocationInfo b : locationInfoList) {
  284. if (!b.getStockStatus().equals("00") || !b.getIsEmpty().equals("Y") || redisCache.checkIsLock(RedisKey.LOCK_LOCATION + b.getId())) {
  285. continue;
  286. }
  287. if (!redisCache.lockCacheObject(RedisKey.LOCK_LOCATION + b.getId(), b.getId().toString(), token)) {
  288. continue;
  289. }
  290. locationInfo = b;
  291. break;
  292. }
  293. if (locationInfo == null) {
  294. throw new ServiceException("入库目标点没有可以分配的库位", token);
  295. }
  296. }
  297. } else if (type.equals("SO")) {
  298. //起始库位
  299. if (locationType.equals("locationFrom")) {
  300. for (BaseLocationInfo b : locationInfoList) {
  301. if (!b.getStockStatus().equals("00") || !b.getIsEmpty().equals("N") || redisCache.checkIsLock(RedisKey.LOCK_LOCATION + b.getId())) {
  302. continue;
  303. }
  304. if (!redisCache.lockCacheObject(RedisKey.LOCK_LOCATION + b.getId(), b.getId().toString(), token)) {
  305. continue;
  306. }
  307. // 判断起始库位上的库存质检状态是否可以出库
  308. boolean con = invLotLocIdService.verifyInventoryCanOutbound(b.getId().toString());
  309. if (!con) {
  310. continue;
  311. }
  312. locationInfo = b;
  313. break;
  314. }
  315. if (locationInfo == null) {
  316. throw new ServiceException("出库起始点没有可以分配的库存!", token);
  317. }
  318. } else { //目标库位
  319. for (BaseLocationInfo b : locationInfoList) {
  320. if (!b.getStockStatus().equals("00") || !b.getIsEmpty().equals("Y") || redisCache.checkIsLock(RedisKey.LOCK_LOCATION + b.getId())) {
  321. continue;
  322. }
  323. if (!redisCache.lockCacheObject(RedisKey.LOCK_LOCATION + b.getId(), b.getId().toString(), token)) {
  324. continue;
  325. }
  326. locationInfo = b;
  327. break;
  328. }
  329. if (locationInfo == null) {
  330. throw new ServiceException("出库目标点没有可以分配的库位", token);
  331. }
  332. }
  333. } else { //移库
  334. if (locationType.equals("locationFrom")) {
  335. for (BaseLocationInfo b : locationInfoList) {
  336. if (!b.getStockStatus().equals("00") || redisCache.checkIsLock(RedisKey.LOCK_LOCATION + b.getId())) {
  337. continue;
  338. }
  339. if (!redisCache.lockCacheObject(RedisKey.LOCK_LOCATION + b.getId(), b.getId().toString(), token)) {
  340. continue;
  341. }
  342. locationInfo = b;
  343. break;
  344. }
  345. //进行判断
  346. if (locationInfo == null) {
  347. throw new ServiceException("搬运起始点没有可以分配的库位", token);
  348. }
  349. } else {
  350. for (BaseLocationInfo b : locationInfoList) {
  351. if (!b.getStockStatus().equals("00") || !b.getIsEmpty().equals("Y") || redisCache.checkIsLock(RedisKey.LOCK_LOCATION + b.getId())) {
  352. continue;
  353. }
  354. if (!redisCache.lockCacheObject(RedisKey.LOCK_LOCATION + b.getId(), b.getId().toString(), token)) {
  355. continue;
  356. }
  357. locationInfo = b;
  358. break;
  359. }
  360. //进行判断
  361. if (locationInfo == null) {
  362. throw new ServiceException("搬运目标点没有可以分配的库位", token);
  363. }
  364. }
  365. }
  366. return locationInfo;
  367. }
  368. @Override
  369. public List<BaseLocationInfo> convertLocation(String locationNoOrZoneId, Long warehouseId, String orderBy) {
  370. List<BaseLocationInfo> locationInfoList = new ArrayList<>();
  371. if (!StringUtils.isEmpty(locationNoOrZoneId)) {
  372. String[] arr = locationNoOrZoneId.split(",");
  373. for (String obj : arr) {
  374. boolean isLocation = baseLocationInfoService.checkIsLocation(obj, warehouseId);
  375. if (isLocation) {
  376. BaseLocationInfo info = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(obj, warehouseId);
  377. locationInfoList.add(info);
  378. } else {
  379. List<BaseLocationInfo> infoList = baseLocationInfoService.selectSortedLocatinListByZoneId(Long.parseLong(obj), warehouseId, orderBy);
  380. locationInfoList.addAll(infoList);
  381. }
  382. }
  383. }
  384. return locationInfoList;
  385. }
  386. @Override
  387. public List<WcsTask> genTask(BaseLocationInfo locationFrom, BaseLocationInfo locationTo, FlowConfigHeaderVO flowConfigHeaderVO, AgvCallDTO agvCallDTO, Long token) {
  388. if (flowConfigHeaderVO.getLocationFromStrategyFlag().equals("N")) {
  389. if (locationFrom == null) {
  390. throw new ServiceException("起始库位不能为空", token);
  391. }
  392. }
  393. if (flowConfigHeaderVO.getLocationToStrategyFlag().equals("N")) {
  394. if (locationTo == null) {
  395. throw new ServiceException("目标库位不能为空", token);
  396. }
  397. }
  398. List<WcsTask> wcsTaskList = new ArrayList<>();
  399. if (StringUtils.isEmpty(flowConfigHeaderVO.getRootFlow())) {
  400. String taskNo = System.currentTimeMillis() + "";
  401. WcsTask wcsTask = new WcsTask();
  402. wcsTask.setTaskNo(taskNo);
  403. if (locationFrom != null) {
  404. wcsTask.setAreaFrom(locationFrom.getZoneId().toString());
  405. wcsTask.setLocationFrom(locationFrom.getId().toString());
  406. }
  407. if (locationTo != null) {
  408. wcsTask.setAreaTo(locationTo.getZoneId() + "");
  409. wcsTask.setLocationTo(locationTo.getId().toString());
  410. }
  411. wcsTask.setState(9L);
  412. wcsTask.setPriority(1L);
  413. wcsTask.setShopId(Constant.WAREHOUSE_ID.toString());
  414. wcsTask.setCreateDate(new Date());
  415. wcsTask.setCreateUser(agvCallDTO.getCreateUser());
  416. wcsTask.setBusinessType("01");
  417. wcsTask.setTaskType(Constant.TASK_TYPE.FORWARD.getValue());
  418. wcsTask.setExt8(token.toString());
  419. wcsTask.setExt7(flowConfigHeaderVO.getId().toString());
  420. wcsTask.setExt6(StringUtils.isNotEmpty(agvCallDTO.getToArea()) ? agvCallDTO.getToArea() : "");
  421. wcsTask.setExtParam(agvCallDTO.getExtParam());
  422. wcsTaskList.add(wcsTask);
  423. businessService.addTask(wcsTask);
  424. } else {
  425. /*//获取对应的流程
  426. List<FlowConfigHeader> headerVOList = flowConfigHeaderService.sortFlowConfigHeader(Long.parseLong(flowConfigHeaderVO.getRootFlow()));
  427. AsnSoStrategy asnSoStrategy = asnSoStrategyMapper.selectAsnSoStrategy();
  428. String taskNo = System.currentTimeMillis() + "";
  429. WcsTask wcsTask = new WcsTask();
  430. wcsTask.setTaskNo(taskNo);
  431. wcsTask.setAreaFrom(locationFrom.getZoneId().toString());
  432. wcsTask.setLocationFrom(locationFrom.getId().toString());
  433. wcsTask.setAreaTo(locationTo.getZoneId() + "");
  434. wcsTask.setLocationTo(locationTo.getId().toString());
  435. wcsTask.setState(9L);
  436. wcsTask.setPriority(1L);
  437. wcsTask.setCreateDate(new Date());
  438. wcsTask.setBusinessType("01");
  439. wcsTask.setTaskType("");
  440. wcsTaskList.add(wcsTask);
  441. String beforeTaskNo = taskNo;
  442. for (FlowConfigHeader flowConfigHeader : headerVOList) {
  443. if (StringUtils.isEmpty(flowConfigHeader.getRelFlow()) && flowConfigHeader.getRootFlow().equals(flowConfigHeader.getId().toString())) {
  444. continue;
  445. }
  446. List<BaseLocationInfo> locationFromList = this.convertLocation(flowConfigHeader.getLocationFrom(), 1L);
  447. List<BaseLocationInfo> locationToList = this.convertLocation(flowConfigHeader.getLocationTo(), 1L);
  448. locationFrom = this.zoneLocationAllocation(locationFromList, "locationFrom", "MV", null, null);
  449. locationTo = this.zoneLocationAllocation(locationToList, "locationTo", "MV", null, null);
  450. String currentNo = SnowflakeIdWorker.generateId().toString();
  451. WcsTask child = new WcsTask();
  452. child.setTaskNo(currentNo);
  453. child.setParentTask(taskNo);
  454. child.setBeforeTask(beforeTaskNo);
  455. child.setAreaFrom(locationFrom.getZoneId().toString());
  456. child.setLocationFrom(locationFrom.getId().toString());
  457. child.setAreaTo(locationTo.getZoneId() + "");
  458. child.setLocationTo(locationTo.getId().toString());
  459. child.setState(9L);
  460. child.setPriority(1L);
  461. child.setCreateDate(new Date());
  462. child.setBusinessType("01");
  463. child.setTaskType("");
  464. wcsTaskList.add(child);
  465. beforeTaskNo = currentNo;
  466. }*/
  467. }
  468. return wcsTaskList;
  469. }
  470. @Transactional
  471. @Override
  472. public AjaxResult addTask(WcsTask wcsTask) {
  473. //锁定库位
  474. if (!StringUtils.isEmpty(wcsTask.getLocationFrom())) {
  475. baseLocationInfoService.updateLocationStockStatus(Long.parseLong(wcsTask.getLocationFrom()), Constant.STOCK_STATUS.STOCK10.getValue());
  476. }
  477. if (!StringUtils.isEmpty(wcsTask.getLocationTo())) {
  478. baseLocationInfoService.updateLocationStockStatus(Long.parseLong(wcsTask.getLocationTo()), Constant.STOCK_STATUS.STOCK10.getValue());
  479. }
  480. Integer priority = 1;
  481. if (!wcsTask.getTaskType().equals("OB")) {
  482. if (wcsTask.getPriority() == 99) {
  483. int current = wcsTaskMapper.selectCurrentPriority();
  484. priority = current - 100;
  485. } else {
  486. int current = wcsTaskMapper.selectCurrentPriority();
  487. priority = current + 10;
  488. }
  489. } else {
  490. //倒库任务顺序由原任务中间插入不需要获取
  491. priority = wcsTask.getPriority().intValue();
  492. }
  493. wcsTask.setPriority((long) priority);
  494. int result = wcsTaskMapper.insertWcsTask(wcsTask);
  495. if (result > 0) {
  496. return AjaxResult.success("任务生成成功");
  497. } else {
  498. throw new ServiceException("任务生成失败");
  499. }
  500. }
  501. @Override
  502. public AjaxResult addTaskList(List<WcsTask> wcsTaskList) {
  503. for (WcsTask wcsTask : wcsTaskList) {
  504. //锁定库位
  505. if (!StringUtils.isEmpty(wcsTask.getLocationFrom())) {
  506. baseLocationInfoService.updateLocationStockStatus(Long.parseLong(wcsTask.getLocationFrom()), Constant.STOCK_STATUS.STOCK10.getValue());
  507. }
  508. if (!StringUtils.isEmpty(wcsTask.getLocationTo())) {
  509. baseLocationInfoService.updateLocationStockStatus(Long.parseLong(wcsTask.getLocationTo()), Constant.STOCK_STATUS.STOCK10.getValue());
  510. }
  511. Integer priority = 1;
  512. if (!wcsTask.getTaskType().equals("OB")) {
  513. if (wcsTask.getPriority() == 99) {
  514. int current = wcsTaskMapper.selectCurrentPriority();
  515. priority = current - 100;
  516. } else {
  517. int current = wcsTaskMapper.selectCurrentPriority();
  518. priority = current + 10;
  519. }
  520. } else {
  521. //倒库任务顺序由原任务中间插入不需要获取
  522. priority = wcsTask.getPriority().intValue();
  523. }
  524. wcsTask.setPriority((long) priority);
  525. int result = wcsTaskMapper.insertWcsTask(wcsTask);
  526. if (result > 0) {
  527. return AjaxResult.success("任务生成成功");
  528. } else {
  529. throw new ServiceException("任务生成失败");
  530. }
  531. }
  532. return AjaxResult.success("");
  533. }
  534. @Override
  535. public AjaxResult sendTask(WcsTask wcsTask) {
  536. BaseLocationInfo locFrom = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(wcsTask.getLocationFrom(), Constant.WAREHOUSE_ID);
  537. BaseLocationInfo locTo = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(wcsTask.getLocationTo(), Constant.WAREHOUSE_ID);
  538. AmsTask amsTask = new AmsTask();
  539. amsTask.setTaskNo(wcsTask.getTaskNo());
  540. if (wcsTask.getBusinessType() == null || wcsTask.getBusinessType().equals("")) {
  541. amsTask.setBusinessType(Constant.TASK_BUSINESS_TYPE.TASK_01.getValue());
  542. } else {
  543. amsTask.setBusinessType(wcsTask.getBusinessType());
  544. }
  545. amsTask.setIsDelete(0);
  546. amsTask.setAciAccept(0);
  547. amsTask.setIkey((long) geniKey(amsTask.getTaskNo()));
  548. amsTask.setPriority(wcsTask.getPriority().intValue());
  549. amsTask.setStFrom(locFrom.getAgvStation().intValue());
  550. amsTask.setStTo(locTo.getAgvStation().intValue());
  551. amsTask.setExt1(wcsTask.getExt1());
  552. amsTask.setExt2(wcsTask.getExt2());
  553. amsTask.setExt3(wcsTask.getExt3());
  554. if (wcsTask.getBusinessType().equals("m")) {
  555. //m类消息特殊处理
  556. wcsTask.setState(2L);
  557. int result = wcsTaskService.updateWcsTask(wcsTask);
  558. if (result > 0) {
  559. //更新
  560. return AjaxResult.success("下发成功");
  561. } else {
  562. return AjaxResult.error("下发失败");
  563. }
  564. } else {
  565. int result = amsTaskService.insertAmsTask(amsTask);
  566. if (result > 0) {
  567. //更新
  568. return AjaxResult.success("下发成功");
  569. } else {
  570. return AjaxResult.error("下发失败");
  571. }
  572. }
  573. }
  574. @Override
  575. public AjaxResult sendTaskList(List<WcsTask> wcsTaskList) {
  576. return null;
  577. }
  578. @Transactional
  579. @Override
  580. public void autoSend() {
  581. List<WcsTask> wcsTaskList = wcsTaskService.selectWcsUnallocated(Constant.WAREHOUSE_ID);
  582. if (wcsTaskList != null && wcsTaskList.size() > 0) {
  583. for (WcsTask wcsTask : wcsTaskList) {
  584. //如果是充电任务直接下发
  585. if (wcsTask.getBusinessType().equals(Constant.TASK_BUSINESS_TYPE.TASK_POWER.getValue()) ||
  586. wcsTask.getBusinessType().equals(Constant.TASK_BUSINESS_TYPE.TASK_m.getValue())) {
  587. log.info("定时充电/盘点取消任务直接下发");
  588. sendTask(wcsTask);
  589. wcsTask.setState(2L);
  590. wcsTaskService.updateWcsTask(wcsTask);
  591. break;
  592. }
  593. //转发任务
  594. if (StringUtils.isNotEmpty(wcsTask.getTaskType())
  595. && wcsTask.getTaskType().equals(Constant.TASK_TYPE.FORWARD.getValue())) {
  596. sendTask(wcsTask);
  597. wcsTask.setState(10L);
  598. wcsTaskService.updateWcsTask(wcsTask);
  599. break;
  600. }
  601. try {
  602. //任务下发判断
  603. businessService.taskDispatchStack(wcsTask);
  604. Thread.sleep(500);
  605. } catch (Exception e) {
  606. e.printStackTrace();
  607. }
  608. }
  609. }
  610. }
  611. @Transactional
  612. @Override
  613. public void autoSendTranSit() {
  614. List<BaseLocationInfo> baseLocationInfos = baseLocationInfoService.selectSortedLocatinListByZoneId(Constant.ZONE_TYPE.TRANSIT.getValue()
  615. , Constant.WAREHOUSE_ID, null);
  616. for (BaseLocationInfo baseLocationInfo : baseLocationInfos) {
  617. // 判断是否有货并且空闲
  618. // if (baseLocationInfo.getStockStatus().equals(Constant.STOCK_STATUS.STOCK00.getValue())
  619. // && baseLocationInfo.getIsEmpty().equals(Constant.IS_YES.N.name())) {
  620. // if (baseLocationInfo.getUserdefine1().equals("ASN")) {
  621. // AgvCallDTO agvCallDTO = new AgvCallDTO();
  622. // agvCallDTO.setLocationFrom(baseLocationInfo.getLocationNo());
  623. // businessService.agvCall(Constant.TRAN_STO_FLOW_ID, agvCallDTO);
  624. // } else if (baseLocationInfo.getUserdefine1().equals("SO_HG")) {
  625. // AgvCallDTO agvCallDTO = new AgvCallDTO();
  626. // agvCallDTO.setLocationFrom(baseLocationInfo.getLocationNo());
  627. // businessService.agvCall(Constant.TRAN_OUT_FLOW_ID, agvCallDTO);
  628. // } else if (baseLocationInfo.getUserdefine1().equals("SO_BHG")) {
  629. // AgvCallDTO agvCallDTO = new AgvCallDTO();
  630. // agvCallDTO.setLocationFrom(baseLocationInfo.getLocationNo());
  631. // businessService.agvCall(Constant.TRAN_OUT_BHG_FLOW_ID, agvCallDTO);
  632. // }
  633. // }
  634. }
  635. }
  636. @Transactional
  637. @Override
  638. public boolean taskDispatchStack(WcsTask wcsTask) {
  639. /* boolean isSplit = taskService.taskSplit(wcsTask);
  640. //判断是否拆分如果拆分了直接跳过
  641. if(isSplit){
  642. return false;
  643. }*/
  644. //最后要执行的任务
  645. WcsTask currentTask = new WcsTask();
  646. //来源库位
  647. BaseLocationInfo basLocationInfoFrom = null;
  648. //目标区域
  649. BaseLocationZone basLocationZoneTo = null;
  650. //起始库位
  651. basLocationInfoFrom = baseLocationInfoService.selectBaseLocationInfoById(Long.parseLong(wcsTask.getLocationFrom()));
  652. //目标库位
  653. BaseLocationInfo locationInfoTo = baseLocationInfoService.selectBaseLocationInfoById(Long.parseLong(wcsTask.getLocationTo()));
  654. //TODO 前置任务未完成不进行下发
  655. if (businessService.taskDispatchCheck(wcsTask) == false) {
  656. return false;
  657. }
  658. if (basLocationInfoFrom != null) {
  659. if (basLocationInfoFrom.getIsEmpty().equals("Y")) {
  660. wcsTask.setRemark("起始库位为空无法进行任务");
  661. wcsTaskService.updateWcsTask(wcsTask);
  662. return false;
  663. }
  664. //起始库位巷道检测(起始库位检测是否同巷道)
  665. if (!StringUtils.isEmpty(basLocationInfoFrom.getColNo())) {
  666. List<BaseLocationInfo> locationInfoList = baseLocationInfoMapper.laneCheck(basLocationInfoFrom.getColNo(), "LANE_FROM", Constant.WAREHOUSE_ID);
  667. if (locationInfoList != null && locationInfoList.size() > 0) {
  668. wcsTask.setRemark("起始库位同列或同巷道有车辆在任务中,等待其他任务完成");
  669. wcsTaskService.updateWcsTask(wcsTask);
  670. return false;
  671. }
  672. }
  673. }
  674. //起始库位是地堆需要判断是否有阻挡
  675. if (basLocationInfoFrom.getLocationType().equals("2")) {
  676. //判断队列中是否有阻挡在当前任务之前
  677. List<WcsTaskLocationDTO> locationDTOS = wcsTaskService.selectTaskByColNo(basLocationInfoFrom.getColNo(), basLocationInfoFrom.getColIndex(), basLocationInfoFrom.getZoneId(), null);
  678. if (locationDTOS.size() > 0) {
  679. wcsTask.setRemark("队列中有其他任务阻挡,让其他任务先执行");
  680. wcsTaskService.updateWcsTask(wcsTask);
  681. return false;
  682. }
  683. //判断出库库位前是否有阻挡
  684. List<BaseLocationInfo> beforeLoc = baseLocationInfoService.selectBeforeLocationByColNo(basLocationInfoFrom.getColNo(), basLocationInfoFrom.getColIndex());
  685. if (beforeLoc != null) {
  686. for (BaseLocationInfo b : beforeLoc) {
  687. //如果前面库位不为空,或者状态占用
  688. //TODO 去除已经在任务中的
  689. if (b.getIsEmpty().equals("N")) {
  690. wcsTask.setRemark("有阻挡物,任务无法执行");
  691. wcsTaskService.updateWcsTask(wcsTask);
  692. return false;
  693. }
  694. }
  695. }
  696. }
  697. currentTask = wcsTask;
  698. //目标库位如果是地堆需要判断是否有阻挡
  699. if (locationInfoTo != null && locationInfoTo.getLocationType().equals("2")) {
  700. List<BaseLocationInfo> beforeLoc = baseLocationInfoService.selectBeforeLocationByColNo(locationInfoTo.getColNo(), locationInfoTo.getColIndex());
  701. if (beforeLoc != null) {
  702. for (BaseLocationInfo b : beforeLoc) {
  703. //跳过起始库位
  704. if (b.getId().equals(locationInfoTo.getId())) {
  705. continue;
  706. }
  707. //如果前面库位不为空,或者状态占用
  708. //TODO 排除已经在任务中的
  709. if (b.getIsEmpty().equals("N")) {
  710. currentTask.setRemark("目标库位前方有阻挡1");
  711. currentTask.setUpdateDate(new Date());
  712. wcsTaskService.updateWcsTask(currentTask);
  713. return false;
  714. }
  715. }
  716. }
  717. List<WcsTaskLocationDTO> dtos = wcsTaskService.selectTaskByColNoAfter(locationInfoTo.getColNo(), locationInfoTo.getColIndex(), locationInfoTo.getZoneId(), null);
  718. if (dtos != null && dtos.size() > 0) {
  719. currentTask.setRemark("目标库位同列有未完成的任务");
  720. wcsTaskService.updateWcsTask(currentTask);
  721. return false;
  722. }
  723. }
  724. //查询是否有更里面的位置可以存放
  725. if (locationInfoTo != null) {
  726. if (locationInfoTo.getZoneId() != 10) {
  727. String locationtoTmp = "";
  728. List<BaseLocationInfoSameColDTO> b = baseLocationInfoService.selectSameColCanToLoc(locationInfoTo.getColNo(), locationInfoTo.getColIndex());
  729. for (BaseLocationInfoSameColDTO bt : b) {
  730. if (bt.getIsOb() == false) {
  731. locationtoTmp = bt.getId().toString();
  732. } else {
  733. break;
  734. }
  735. }
  736. if (!StringUtils.isEmpty(locationtoTmp)) {
  737. wcsTask.setLocationTo(locationtoTmp);
  738. wcsTaskService.updateWcsTask(wcsTask);
  739. //释放原库位
  740. locationInfoTo.setStockStatus("00");
  741. baseLocationInfoService.updateBaseLocationInfo(locationInfoTo);
  742. //占用新库位
  743. BaseLocationInfo newlocationInfoTo = baseLocationInfoService.selectBaseLocationInfoById(Long.parseLong(locationtoTmp));
  744. newlocationInfoTo.setStockStatus("10");
  745. baseLocationInfoService.updateBaseLocationInfo(newlocationInfoTo);
  746. }
  747. }
  748. }
  749. currentTask.setState(10L);
  750. currentTask.setRemark("");
  751. if (wcsTaskService.updateWcsTask(currentTask) > 0) {
  752. AjaxResult result = businessService.sendTask(currentTask);
  753. if ((int) result.get(AjaxResult.CODE_TAG) == 500) {
  754. throw new ServiceException("自动下发任务失败:" + result.get("msg"));
  755. }
  756. return true;
  757. } else {
  758. return false;
  759. }
  760. }
  761. @Override
  762. public boolean taskDispatchCheck(WcsTask wcsTask) {
  763. if (!StringUtils.isEmpty(wcsTask.getBeforeTask())) {
  764. List<WcsTask> taskFindBeforeRecord = wcsTaskMapper.selectBeforeTask(wcsTask.getBeforeTask());
  765. if (taskFindBeforeRecord != null && taskFindBeforeRecord.size() > 0) {
  766. //log.info("前置任务未完成主任务无法下发{}",wcsTask);
  767. wcsTask.setRemark("前置任务未完成主任务无法下发");
  768. wcsTaskService.updateWcsTask(wcsTask);
  769. return false;
  770. }
  771. }
  772. return true;
  773. }
  774. }