BusinessServiceImpl.java 41 KB

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