BusinessServiceImpl.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. package com.ruoyi.ams.business;
  2. import com.alibaba.fastjson.JSON;
  3. import com.ruoyi.ams.common.Constant;
  4. import com.ruoyi.ams.config.domain.AsnSoStrategy;
  5. import com.ruoyi.ams.config.domain.dto.AgvCallDTO;
  6. import com.ruoyi.ams.config.domain.dto.InWarehouseDTO;
  7. import com.ruoyi.ams.config.domain.dto.LotattDTO;
  8. import com.ruoyi.ams.config.domain.dto.OutWarehouseDTO;
  9. import com.ruoyi.ams.config.domain.vo.FlowConfigHeaderVO;
  10. import com.ruoyi.ams.config.mapper.AsnSoStrategyMapper;
  11. import com.ruoyi.ams.config.service.IFlowConfigHeaderService;
  12. import com.ruoyi.ams.config.service.ILocationPriorityHeaderService;
  13. import com.ruoyi.ams.config.service.LocationAllocationStrategy;
  14. import com.ruoyi.ams.inv.mapper.InvLotLocIdMapper;
  15. import com.ruoyi.ams.inv.service.IInvLotLocIdService;
  16. import com.ruoyi.ams.task.domain.WcsTask;
  17. import com.ruoyi.ams.task.mapper.WcsTaskMapper;
  18. import com.ruoyi.base.domain.BaseLocationInfo;
  19. import com.ruoyi.base.domain.BaseSku;
  20. import com.ruoyi.base.domain.vo.BaseLocationLotattVO;
  21. import com.ruoyi.base.mapper.BaseLocationInfoMapper;
  22. import com.ruoyi.base.service.IBaseLocationInfoService;
  23. import com.ruoyi.base.service.IBaseSkuService;
  24. import com.ruoyi.common.core.domain.AjaxResult;
  25. import com.ruoyi.common.exception.ServiceException;
  26. import com.ruoyi.common.utils.StringUtils;
  27. import lombok.extern.slf4j.Slf4j;
  28. import org.springframework.beans.factory.annotation.Autowired;
  29. import org.springframework.stereotype.Service;
  30. import org.springframework.transaction.annotation.Transactional;
  31. import java.util.*;
  32. @Slf4j
  33. @Service
  34. public class BusinessServiceImpl implements IBusinessService {
  35. @Autowired
  36. private IBusinessService businessService;
  37. @Autowired
  38. private IBaseLocationInfoService baseLocationInfoService;
  39. @Autowired
  40. private LocationAllocationStrategy locationAllocationStrategy;
  41. @Autowired
  42. private InvLotLocIdMapper invLotLocIdMapper;
  43. @Autowired
  44. private IInvLotLocIdService invLotLocIdService;
  45. @Autowired
  46. private WcsTaskMapper wcsTaskMapper;
  47. @Autowired
  48. private AsnSoStrategyMapper asnSoStrategyMapper;
  49. @Autowired
  50. private BaseLocationInfoMapper baseLocationInfoMapper;
  51. @Autowired
  52. private IBaseSkuService baseSkuService;
  53. @Autowired
  54. private IFlowConfigHeaderService flowConfigHeaderService;
  55. @Transactional
  56. @Override
  57. public AjaxResult agvCall(List<AgvCallDTO> agvCallDTOList) {
  58. AgvCallDTO agvCallDTO = new AgvCallDTO();
  59. for (AgvCallDTO agvCall : agvCallDTOList) {
  60. agvCallDTO.setLocationFrom(agvCall.getLocationFrom());
  61. agvCallDTO.setLocationTo(agvCall.getLocationTo());
  62. agvCallDTO.setId(agvCall.getId());
  63. agvCallDTO.setWarehouseId(agvCall.getWarehouseId());
  64. agvCallDTO.setLotattDTO(agvCall.getLotattDTO());
  65. break;
  66. }
  67. BaseLocationInfo locationFrom = null;
  68. BaseLocationInfo locationTo = null;
  69. //查询所属流程
  70. FlowConfigHeaderVO flowConfigHeaderVO = flowConfigHeaderService.selectFlowConfigHeaderById(agvCallDTO.getId());
  71. AsnSoStrategy asnSoStrategy = asnSoStrategyMapper.selectAsnSoStrategy();
  72. if (flowConfigHeaderVO == null) {
  73. log.info("-----------指令查询不到对应的流程:" + JSON.toJSONString(agvCallDTOList));
  74. return AjaxResult.error("指令查询不到对应的流程");
  75. }
  76. String paramLocationFrom = agvCallDTO.getLocationFrom();
  77. String paramLocationTo = agvCallDTO.getLocationTo();
  78. if (StringUtils.isEmpty(paramLocationFrom)) {
  79. paramLocationFrom = flowConfigHeaderVO.getLocationFrom();
  80. }
  81. if(StringUtils.isEmpty(paramLocationTo)) {
  82. paramLocationTo = flowConfigHeaderVO.getLocationTo();
  83. }
  84. List<BaseLocationInfo> locationFromList = this.convertLocation(paramLocationFrom, agvCallDTO.getWarehouseId());
  85. List<BaseLocationInfo> locationToList = this.convertLocation(paramLocationTo, agvCallDTO.getWarehouseId());
  86. if (flowConfigHeaderVO.getFlowType().equals("ASN")) {
  87. locationFrom = this.zoneLocationAllocation(locationFromList, "locationFrom", "ASN", asnSoStrategy, agvCallDTO);
  88. locationTo = this.zoneLocationAllocation(locationToList, "locationTo", "ASN", asnSoStrategy, agvCallDTO);
  89. //2.初始化库存
  90. for (AgvCallDTO agvCall : agvCallDTOList) {
  91. invLotLocIdService.initInv(locationFrom.getId().toString(), agvCall.getSku(), Constant.CUSTOMER_ID, agvCall.getQty(), agvCall.getLotattDTO());
  92. }
  93. } else if (flowConfigHeaderVO.getFlowType().equals("SO")) {
  94. locationFrom = this.zoneLocationAllocation(locationFromList, "locationFrom", "SO", asnSoStrategy, agvCallDTO);
  95. locationTo = this.zoneLocationAllocation(locationToList, "locationTo", "SO", asnSoStrategy, agvCallDTO);
  96. } else if (flowConfigHeaderVO.getFlowType().equals("MV")) {
  97. locationFrom = this.zoneLocationAllocation(locationFromList, "locationFrom", "MV", asnSoStrategy, agvCallDTO);
  98. locationTo = this.zoneLocationAllocation(locationToList, "locationTo", "MV", asnSoStrategy, agvCallDTO);
  99. }
  100. String taskNo = System.currentTimeMillis() + "";
  101. WcsTask wcsTask = new WcsTask();
  102. wcsTask.setTaskNo(taskNo);
  103. wcsTask.setAreaFrom(locationFrom.getZoneId().toString());
  104. wcsTask.setLocationFrom(locationFrom.getId().toString());
  105. wcsTask.setAreaTo(locationTo.getZoneId() + "");
  106. wcsTask.setLocationTo(locationTo.getId().toString());
  107. wcsTask.setState(9L);
  108. wcsTask.setPriority(1L);
  109. wcsTask.setCreateDate(new Date());
  110. wcsTask.setBusinessType("01");
  111. wcsTask.setTaskType("");
  112. return businessService.addTask(wcsTask);
  113. }
  114. @Transactional
  115. @Override
  116. public BaseLocationInfo inLocationAllocation(InWarehouseDTO inWarehouseDTO) {
  117. /**
  118. * 根据sku查询可以存放的zone
  119. * 根据每个zone的配置去分配可以存放的库位
  120. *
  121. * force
  122. * optimization
  123. * ignore
  124. */
  125. if (!StringUtils.isEmpty(inWarehouseDTO.getLocationTo())) { //指定库位则直接返回库位
  126. BaseLocationInfo baseLocationInfo = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(inWarehouseDTO.getLocationTo(), inWarehouseDTO.getWarehouseId());
  127. return baseLocationInfo;
  128. } else {
  129. if (StringUtils.isEmpty(inWarehouseDTO.getLocationZoneTo()) && StringUtils.isEmpty(inWarehouseDTO.getLocationTo())) { //不指定目标库位和区域
  130. // 没有指定目标的根据sku进行匹配并进行分配
  131. // 如果可以混放的区域不匹配物料也可以选择,否则只选择可以存放的区域
  132. AsnSoStrategy asnSoStrategy = asnSoStrategyMapper.selectAsnSoStrategy();
  133. BaseSku baseSku = baseSkuService.selectBaseSkuByCustomerId(Constant.CUSTOMER_ID, inWarehouseDTO.getSku());
  134. //判断是否强制同物料靠近,
  135. LotattDTO lotattDTO = inWarehouseDTO.getLotattDTO();
  136. Map<String, String> lotattMap = new HashMap<>();
  137. if (asnSoStrategy.getAsnSameLotatt1Flag().equals("optimization")) {
  138. lotattMap.put(asnSoStrategy.getAsnSameLotatt1Value(), lotattDTO.getAttr(asnSoStrategy.getAsnSameLotatt1Value()));
  139. }
  140. if (asnSoStrategy.getAsnSameLotatt2Flag().equals("optimization")) {
  141. lotattMap.put(asnSoStrategy.getAsnSameLotatt2Value(), lotattDTO.getAttr(asnSoStrategy.getAsnSameLotatt2Value()));
  142. }
  143. List<BaseLocationInfo> locationInfoList = new ArrayList<>();
  144. if (asnSoStrategy.getAsnSameSku().equals("force")) {
  145. List<String> colNo = baseLocationInfoMapper.selectSameSkuColNo(baseSku.getSku(), null, lotattMap);
  146. for (String s : colNo) {
  147. List<BaseLocationInfo> locs = baseLocationInfoService.selectNeighborLocation(s, null);
  148. locationInfoList.addAll(locs);
  149. }
  150. if (colNo == null || colNo.size() == 0) {
  151. colNo = baseLocationInfoMapper.selectSameSkuTypeColNo(baseSku.getSkuType(), null);
  152. for (String s : colNo) {
  153. List<BaseLocationInfo> locs = baseLocationInfoService.selectNeighborLocation(s, null);
  154. locationInfoList.addAll(locs);
  155. }
  156. }
  157. // List<BaseLocationInfo> locs = baseLocationInfoMapper.selectLocationByColNos(colNo);
  158. } else if (asnSoStrategy.getAsnSameSku().equals("optimization") || asnSoStrategy.getAsnSameSkuType().equals("optimization")) {
  159. List<String> skuColNo = baseLocationInfoMapper.selectSameSkuColNo(baseSku.getSku(), null, lotattMap);
  160. List<String> skuTypeColNo = baseLocationInfoMapper.selectSameSkuColNo(baseSku.getSkuType(), null, lotattMap);
  161. List<String> cols = new ArrayList<>();
  162. cols.addAll(skuColNo);
  163. cols.addAll(skuTypeColNo);
  164. List<BaseLocationInfo> locs = baseLocationInfoMapper.selectLocationByColNos(cols);
  165. locationInfoList.addAll(locs);
  166. } else {
  167. locationInfoList = baseLocationInfoMapper.selectLocationBindSku(baseSku.getSkuType());
  168. }
  169. return locationAllocationStrategy.filterLockLocation(locationInfoList, inWarehouseDTO, asnSoStrategy);
  170. } else {
  171. // 指定区域的
  172. List<BaseLocationInfo> locationInfoList = baseLocationInfoService.selectSortedLocatinListByZoneId(Long.parseLong(inWarehouseDTO.getLocationZoneTo()), inWarehouseDTO.getWarehouseId());
  173. return locationAllocationStrategy.filterLockLocation(locationInfoList);
  174. }
  175. }
  176. }
  177. @Transactional
  178. @Override
  179. public BaseLocationInfo outInvAllocation(OutWarehouseDTO outWarehouseDTO) {
  180. /**
  181. * 指定位置出库
  182. */
  183. if (!StringUtils.isEmpty(outWarehouseDTO.getLocationFrom())) {
  184. BaseLocationInfo baseLocationInfo = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(outWarehouseDTO.getLocationFrom(), outWarehouseDTO.getWarehouseId());
  185. return baseLocationInfo;
  186. } else {
  187. //未指定明确位置出库
  188. List<Long> zoneIdList = new ArrayList<>();
  189. if (!StringUtils.isEmpty(outWarehouseDTO.getLocationZoneFrom())) {
  190. zoneIdList.add(Long.parseLong(outWarehouseDTO.getLocationZoneFrom()));
  191. } else {
  192. List<BaseLocationLotattVO> zoneList = invLotLocIdMapper.selectInvZoneBySkuLotatt(outWarehouseDTO.getSku(), outWarehouseDTO.getSkuType(), outWarehouseDTO.getLotattDTO());
  193. for (BaseLocationLotattVO vo : zoneList) {
  194. zoneIdList.add(vo.getZoneId());
  195. }
  196. }
  197. LotattDTO lotattDTO = outWarehouseDTO.getLotattDTO();
  198. List<BaseLocationLotattVO> locationInfoList = baseLocationInfoMapper.selectSortedLocationLotattListByZoneIdList(zoneIdList, outWarehouseDTO.getWarehouseId(), lotattDTO.getAttr());
  199. AsnSoStrategy asnSoStrategy = asnSoStrategyMapper.selectAsnSoStrategy();
  200. return locationAllocationStrategy.filterLockInv(locationInfoList, outWarehouseDTO, asnSoStrategy);
  201. }
  202. }
  203. @Override
  204. public BaseLocationInfo zoneLocationAllocation(List<BaseLocationInfo> locationInfoList, String locationType, String type, AsnSoStrategy asnSoStrategy, AgvCallDTO agvCallDTO) {
  205. BaseLocationInfo locationInfo = null;
  206. if (type.equals("ASN")) {
  207. //入库
  208. if (locationType.equals("locationFrom")) {
  209. for (BaseLocationInfo b : locationInfoList) {
  210. if (!b.getStockStatus().equals("00")) {
  211. continue;
  212. }
  213. locationInfo = b;
  214. break;
  215. }
  216. if (locationInfo == null) {
  217. throw new RuntimeException("没有可以分配的库位");
  218. }
  219. } else {
  220. if (locationInfoList != null && locationInfoList.size() > 0) {
  221. locationInfo = locationAllocationStrategy.filterLockLocation(locationInfoList);
  222. } else {
  223. InWarehouseDTO inWarehouseDTO = new InWarehouseDTO();
  224. inWarehouseDTO.setWarehouseId(agvCallDTO.getWarehouseId());
  225. inWarehouseDTO.setSku(agvCallDTO.getSku());
  226. inWarehouseDTO.setLocationTo(agvCallDTO.getLocationTo());
  227. inWarehouseDTO.setLocationFrom(agvCallDTO.getLocationFrom());
  228. inWarehouseDTO.setQty(agvCallDTO.getQty());
  229. inWarehouseDTO.setSupplier(agvCallDTO.getSupplier());
  230. inWarehouseDTO.setWeight(agvCallDTO.getWeight());
  231. inWarehouseDTO.setLotattDTO(agvCallDTO.getLotattDTO());
  232. locationInfo = inLocationAllocation(inWarehouseDTO);
  233. }
  234. if (locationInfo == null) {
  235. throw new RuntimeException("没有可以分配的库位");
  236. }
  237. return locationInfo;
  238. }
  239. } else if (type.equals("SO")) {
  240. //起始库位
  241. if (locationType.equals("locationFrom")) {
  242. //指定库位
  243. if (locationInfoList != null && locationInfoList.size() > 0) {
  244. List<Long> locationList = new ArrayList<>();
  245. for (BaseLocationInfo b : locationInfoList) {
  246. locationList.add(b.getId());
  247. }
  248. List<BaseLocationLotattVO> locationLotattVOList = baseLocationInfoMapper.selectSortedLocationLotattListByLocationIdList(locationList, agvCallDTO.getWarehouseId(), agvCallDTO.getLotattDTO().getAttr());
  249. OutWarehouseDTO outWarehouseDTO = new OutWarehouseDTO();
  250. outWarehouseDTO.setSku(agvCallDTO.getSku());
  251. outWarehouseDTO.setQty(agvCallDTO.getQty());
  252. outWarehouseDTO.setWeight(agvCallDTO.getWeight());
  253. outWarehouseDTO.setSupplier(agvCallDTO.getSupplier());
  254. outWarehouseDTO.setLotattDTO(agvCallDTO.getLotattDTO());
  255. outWarehouseDTO.setWarehouseId(agvCallDTO.getWarehouseId());
  256. locationInfo = locationAllocationStrategy.filterLockInv(locationLotattVOList, outWarehouseDTO, asnSoStrategy);
  257. } else {
  258. OutWarehouseDTO outWarehouseDTO = new OutWarehouseDTO();
  259. outWarehouseDTO.setSku(agvCallDTO.getSku());
  260. outWarehouseDTO.setQty(agvCallDTO.getQty());
  261. outWarehouseDTO.setWeight(agvCallDTO.getWeight());
  262. outWarehouseDTO.setSupplier(agvCallDTO.getSupplier());
  263. outWarehouseDTO.setLotattDTO(agvCallDTO.getLotattDTO());
  264. outWarehouseDTO.setWarehouseId(agvCallDTO.getWarehouseId());
  265. locationInfo = outInvAllocation(outWarehouseDTO);
  266. }
  267. if (locationInfo == null) {
  268. throw new RuntimeException("没有可分配的库存");
  269. }
  270. return locationInfo;
  271. } else { //目标库位
  272. for (BaseLocationInfo b : locationInfoList) {
  273. if (!b.getStockStatus().equals("00")) {
  274. continue;
  275. }
  276. locationInfo = b;
  277. break;
  278. }
  279. if (locationInfo == null) {
  280. throw new RuntimeException("没有可以分配的库位");
  281. }
  282. }
  283. } else {
  284. //移库
  285. for (BaseLocationInfo b : locationInfoList) {
  286. if (!b.getStockStatus().equals("00")) {
  287. continue;
  288. }
  289. locationInfo = b;
  290. break;
  291. }
  292. if (locationInfo == null) {
  293. throw new RuntimeException("没有可以分配的库位");
  294. }
  295. }
  296. return locationInfo;
  297. }
  298. @Override
  299. public List<BaseLocationInfo> convertLocation(String locationNoOrZoneId, Long warehouseId) {
  300. List<BaseLocationInfo> locationInfoList = new ArrayList<>();
  301. if (!StringUtils.isEmpty(locationNoOrZoneId)) {
  302. String[] arr = locationNoOrZoneId.split(",");
  303. for (String obj : arr) {
  304. boolean isLocation = baseLocationInfoService.checkIsLocation(obj, warehouseId);
  305. if (isLocation) {
  306. BaseLocationInfo info = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(obj, warehouseId);
  307. locationInfoList.add(info);
  308. } else {
  309. List<BaseLocationInfo> infoList = baseLocationInfoService.selectSortedLocatinListByZoneId(Long.parseLong(obj), warehouseId);
  310. locationInfoList.addAll(infoList);
  311. }
  312. }
  313. }
  314. return locationInfoList;
  315. }
  316. @Transactional
  317. @Override
  318. public AjaxResult addTask(WcsTask wcsTask) {
  319. //锁定库位
  320. if (!StringUtils.isEmpty(wcsTask.getLocationFrom())) {
  321. baseLocationInfoService.updateLocationStockStatus(Long.parseLong(wcsTask.getLocationFrom()), Constant.STOCK_STATUS.STOCK10.getValue());
  322. }
  323. if (!StringUtils.isEmpty(wcsTask.getLocationTo())) {
  324. baseLocationInfoService.updateLocationStockStatus(Long.parseLong(wcsTask.getLocationTo()), Constant.STOCK_STATUS.STOCK10.getValue());
  325. }
  326. Integer priority = 1;
  327. if (!wcsTask.getTaskType().equals("OB")) {
  328. if (wcsTask.getPriority() == 99) {
  329. int current = wcsTaskMapper.selectCurrentPriority();
  330. priority = current - 100;
  331. } else {
  332. int current = wcsTaskMapper.selectCurrentPriority();
  333. priority = current + 10;
  334. }
  335. } else {
  336. //倒库任务顺序由原任务中间插入不需要获取
  337. priority = wcsTask.getPriority().intValue();
  338. }
  339. wcsTask.setPriority((long) priority);
  340. int result = wcsTaskMapper.insertWcsTask(wcsTask);
  341. if (result > 0) {
  342. return AjaxResult.success("任务生成成功");
  343. } else {
  344. throw new ServiceException("任务生成失败");
  345. }
  346. }
  347. @Override
  348. public AjaxResult sendTask(WcsTask wcsTask) {
  349. return AjaxResult.success();
  350. }
  351. }