AgvCallProxyService.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. package com.ruoyi.ams.xuankuang.service;
  2. import cn.hutool.core.collection.CollectionUtil;
  3. import cn.hutool.core.lang.Assert;
  4. import cn.hutool.core.util.ObjectUtil;
  5. import com.baomidou.mybatisplus.core.toolkit.IdWorker;
  6. import com.ruoyi.ams.asn.domain.WmsDocAsnDetails;
  7. import com.ruoyi.ams.asn.domain.WmsDocAsnHeader;
  8. import com.ruoyi.ams.asn.service.IWmsDocAsnDetailsService;
  9. import com.ruoyi.ams.asn.service.IWmsDocAsnHeaderService;
  10. import com.ruoyi.ams.business.IBusinessService;
  11. import com.ruoyi.ams.config.domain.dto.AgvCallDTO;
  12. import com.ruoyi.ams.config.domain.dto.AgvCallItemDTO;
  13. import com.ruoyi.ams.config.domain.dto.LotattDTO;
  14. import com.ruoyi.ams.order.domain.WmsDocOrderDetails;
  15. import com.ruoyi.ams.order.domain.WmsDocOrderHeader;
  16. import com.ruoyi.ams.order.service.IWmsDocOrderDetailsService;
  17. import com.ruoyi.ams.order.service.IWmsDocOrderHeaderService;
  18. import com.ruoyi.ams.task.service.IWcsTaskService;
  19. import com.ruoyi.ams.xuankuang.domain.form.AgvInTaskForm;
  20. import com.ruoyi.ams.xuankuang.domain.form.OutTaskForm;
  21. import com.ruoyi.ams.xuankuang.domain.vo.WcsResponseVo;
  22. import com.ruoyi.base.constant.Constant;
  23. import com.ruoyi.base.domain.BaseLocationInfo;
  24. import com.ruoyi.base.domain.BaseSku;
  25. import com.ruoyi.base.domain.vo.BaseLocationLotattDTO;
  26. import com.ruoyi.base.service.IBaseLocationInfoService;
  27. import com.ruoyi.base.service.IBaseSkuService;
  28. import com.ruoyi.base.utils.IdSequenceUtils;
  29. import com.ruoyi.common.core.domain.AjaxResult;
  30. import com.ruoyi.common.utils.StringUtils;
  31. import com.ruoyi.system.service.ISysConfigService;
  32. import lombok.extern.slf4j.Slf4j;
  33. import org.springframework.beans.factory.annotation.Autowired;
  34. import org.springframework.stereotype.Service;
  35. import org.springframework.transaction.annotation.Transactional;
  36. import java.math.BigDecimal;
  37. import java.util.ArrayList;
  38. import java.util.List;
  39. /**
  40. * @author Jwk
  41. * @version 1.0
  42. * @date 2023/6/6 13:35
  43. */
  44. @Slf4j
  45. @Service
  46. public class AgvCallProxyService {
  47. @Autowired
  48. private IBusinessService iBusinessService;
  49. @Autowired
  50. BaseLocationInfoSubService baseLocationInfoSubService;
  51. @Autowired
  52. WmsDocAsnSubService wmsDocAsnSubService;
  53. @Autowired
  54. private IBaseSkuService iBaseSkuService;
  55. @Autowired
  56. private ISysConfigService sysConfigService;
  57. @Autowired
  58. private IdSequenceUtils idSequenceUtils;
  59. @Autowired
  60. private IWmsDocAsnHeaderService iWmsDocAsnHeaderService;
  61. @Autowired
  62. private IWmsDocAsnDetailsService iWmsDocAsnDetailsService;
  63. @Autowired
  64. private IWmsDocOrderHeaderService iWmsDocOrderHeaderService;
  65. @Autowired
  66. private IWmsDocOrderDetailsService iWmsDocOrderDetailsService;
  67. @Autowired
  68. private WmsDocOrderSubService wmsDocOrderSubService;
  69. @Autowired
  70. private WcsTaskSubService wcsTaskSubService;
  71. @Autowired
  72. private WmsToWcsApiService wmsToWcsApiService;
  73. @Autowired
  74. private IBaseLocationInfoService iBaseLocationInfoService;
  75. @Autowired
  76. private InvLotLocIdSubService invLotLocIdSubService;
  77. @Autowired
  78. private IWcsTaskService iWcsTaskService;
  79. /**
  80. * 主方法:桶装入库
  81. * @param palletNo 入库托盘号
  82. * @param materialType 物料类型 丁胺黑药类型:5
  83. * @param agvSourceLocationId agv的起始点位
  84. * @param quantity 数量
  85. */
  86. @Transactional(rollbackFor = RuntimeException.class)
  87. public void bucketIntoStorage(String palletNo, String materialType,
  88. String agvSourceLocationId, Double quantity) {
  89. //1.预备参数设置
  90. BaseSku baseSku = iBaseSkuService.selectBaseSkuByMaterialType(materialType);
  91. Assert.isTrue(ObjectUtil.isNotNull(baseSku) && StringUtils.isNotBlank(baseSku.getSku()), "the materialType is illegal");
  92. String asnNo = idSequenceUtils.generateId(Constant.ID_TYPE.ASNNO.getDesc());
  93. Assert.isTrue(ObjectUtil.isNotNull(quantity) && quantity > 0, "quantity is illegal");
  94. BigDecimal quantityDecimal = new BigDecimal(quantity);
  95. //2. 获取agv的库位,并创建agv的wcs任务
  96. String agvTargetLocationId = String.valueOf(getAgvLocationId("bucketLocationIdList"));
  97. String agvTaskNo = IdWorker.getIdStr();
  98. wcsTaskSubService.addWcsTask(agvTaskNo, agvSourceLocationId, agvTargetLocationId,
  99. asnNo, palletNo, Constant.TASK_STS.TASK_CREATE.getLongValue(), "agv入库任务下发");
  100. //3.入库单创建
  101. WmsDocAsnHeader wmsDocAsnHeader =
  102. iWmsDocAsnHeaderService.createAsnHeader(asnNo, Constant.ASN_TYP.TZ.getValue(), Constant.ASN_STS.STS00.getValue());
  103. WmsDocAsnDetails wmsDocAsnDetail =
  104. iWmsDocAsnDetailsService.createAsnDetail(asnNo, baseSku.getSku(), quantityDecimal);
  105. //4. 根据入库单进行agv的任务下发,通知wcs并生成wcs任务;agv的目标点则是wcs任务的起始点位
  106. String taskNo = IdWorker.getIdStr();
  107. WcsResponseVo wcsResponseVo = noticeBucketIntoLocTask(taskNo, agvTargetLocationId, asnNo, palletNo, materialType, quantity);
  108. if (!wcsResponseVo.isSuccess()) {
  109. wmsDocAsnHeader.setNotes(wcsResponseVo.getMessage());
  110. iWmsDocAsnHeaderService.updateWmsDocAsnHeader(wmsDocAsnHeader);
  111. wcsTaskSubService.callBack(taskNo, Constant.TASK_STS.TASK_CANCEL.getValue(), null);
  112. }
  113. wmsDocAsnHeader.setAsnStatus(Constant.ASN_STS.STS10.getValue());
  114. wmsDocAsnDetail.setLineStatus(Constant.ASN_STS.STS10.getValue());
  115. iWmsDocAsnDetailsService.updateWmsDocAsnDetails(wmsDocAsnDetail);
  116. iWmsDocAsnHeaderService.updateWmsDocAsnHeader(wmsDocAsnHeader);
  117. }
  118. /**
  119. * 主方法:桶装出库
  120. * @param materialType 物料类型,丁胺黑药默认传5
  121. * @param targetLocationId 出库的最终目标库位
  122. * @param quantity 数量 不能大于4
  123. */
  124. @Transactional(rollbackFor = RuntimeException.class)
  125. public void bucketOutOfStorage(String materialType, String targetLocationId, Double quantity) {
  126. //1.预备参数设置
  127. BaseSku baseSku = iBaseSkuService.selectBaseSkuByMaterialType(materialType);
  128. Assert.isTrue(ObjectUtil.isNotNull(baseSku) && StringUtils.isNotBlank(baseSku.getSku()), "the materialType is illegal");
  129. String orderNo = idSequenceUtils.generateId(Constant.ID_TYPE.ORDERNO.getDesc());
  130. Assert.isTrue(ObjectUtil.isNotNull(quantity) && quantity > 0, "quantity is illegal");
  131. BigDecimal quantityDecimal = new BigDecimal(quantity);
  132. //2. 获取agv的库位,并创建agv的wcs任务
  133. String agvSourceLocationId = String.valueOf(getAgvLocationId("bucketLocationIdList"));
  134. String agvTaskNo = IdWorker.getIdStr();
  135. wcsTaskSubService.addWcsOutTask(agvTaskNo, agvSourceLocationId, targetLocationId,
  136. orderNo, Constant.TASK_STS.TASK_CREATE.getLongValue(), "agv出库任务下发");
  137. //3.出库单创建
  138. WmsDocOrderHeader docOrderHeader =
  139. iWmsDocOrderHeaderService.createOrderHeader(orderNo, Constant.ORDER_TYP.TZ.getValue(), Constant.ORDER_STS.STS00.getValue());
  140. WmsDocOrderDetails docOrderDetail =
  141. iWmsDocOrderDetailsService.createOrderDetail(orderNo, baseSku.getSku(), quantityDecimal);
  142. //4. 根据出库单进行出库任务下发,通知wcs并生成wcs任务;改变订单的状态
  143. List<BaseLocationLotattDTO> baseLocationLotattList = wmsDocOrderSubService.addConfirmAllocationAuto(orderNo);
  144. List<BaseLocationLotattDTO> filteredBaseLocationLotattList = wmsDocOrderSubService.filterInv(baseLocationLotattList, orderNo);
  145. Assert.isTrue(CollectionUtil.isNotEmpty(filteredBaseLocationLotattList), "filteredBaseLocationLotattList is empty");
  146. //int errorCount = 0;
  147. for (BaseLocationInfo baseLocationInfo : filteredBaseLocationLotattList){
  148. //每个推荐的出库库存都创建一个wcs任务,agv的起始点则是wcs任务的目标点位
  149. String taskNo = idSequenceUtils.generateId(Constant.ID_TYPE.LOTNUMBER.getDesc());
  150. //通知wcs的桶装出库的任务
  151. WcsResponseVo wcsResponseVo = noticeBucketOutLocTask(taskNo, agvSourceLocationId, orderNo, materialType, quantity, baseLocationInfo);
  152. if (!wcsResponseVo.isSuccess()) {
  153. //errorCount++;
  154. docOrderHeader.setRemark(wcsResponseVo.getMessage());
  155. iWmsDocOrderHeaderService.updateWmsDocOrderHeader(docOrderHeader);
  156. }
  157. }
  158. //此处屏蔽的代码:代表只有在全部同步失败的情况下,不改变单头和明细的状态
  159. //if(errorCount == filteredBaseLocationLotattList.size()) return;
  160. docOrderHeader.setOrderStatus(Constant.ASN_STS.STS10.getValue());
  161. docOrderDetail.setLineStatus(Constant.ASN_STS.STS10.getValue());
  162. iWmsDocOrderDetailsService.updateWmsDocOrderDetails(docOrderDetail);
  163. iWmsDocOrderHeaderService.updateWmsDocOrderHeader(docOrderHeader);
  164. }
  165. /**
  166. * 主方法:桶装越库
  167. * @param palletNo 托盘号
  168. * @param materialType 物料类型 丁胺黑药类型5
  169. * @param sourceLocationId 起始库位
  170. * @param targetLocationId 目标库位
  171. * @param quantity 数量 不大于4
  172. */
  173. public void bucketCrossStorage(String palletNo, String materialType, String sourceLocationId, String targetLocationId, Double quantity) {
  174. //1.预备参数设置
  175. Assert.isTrue(ObjectUtil.isNotNull(quantity) && quantity > 0, "quantity is illegal");
  176. BaseSku baseSku = iBaseSkuService.selectBaseSkuByMaterialType(materialType);
  177. Assert.isTrue(ObjectUtil.isNotNull(baseSku) && StringUtils.isNotBlank(baseSku.getSku()), "the materialType is illegal");
  178. BigDecimal quantityDecimal = new BigDecimal(quantity);
  179. //2.入库单创建
  180. String asnNo = idSequenceUtils.generateId(Constant.ID_TYPE.ASNNO.getDesc());
  181. iWmsDocAsnHeaderService.createAsnHeader(asnNo, Constant.ASN_TYP.TZ.getValue(), Constant.ASN_STS.STS10.getValue());
  182. iWmsDocAsnDetailsService.createAsnDetail(asnNo, baseSku.getSku(), quantityDecimal);
  183. //3.出库单创建
  184. String orderNo = idSequenceUtils.generateId(Constant.ID_TYPE.ORDERNO.getDesc());
  185. iWmsDocOrderHeaderService.createOrderHeader(orderNo, Constant.ORDER_TYP.TZ.getValue(), Constant.ORDER_STS.STS10.getValue());
  186. iWmsDocOrderDetailsService.createOrderDetail(orderNo, baseSku.getSku(), quantityDecimal);
  187. //2. 获取agv的库位,并创建agv的wcs任务
  188. String agvTaskNo = IdWorker.getIdStr();
  189. wcsTaskSubService.addCrossWcsTask(agvTaskNo, sourceLocationId, targetLocationId,
  190. asnNo, palletNo, orderNo, Constant.TASK_STS.TASK_WAIT.getLongValue(), "agv越库任务下发");
  191. }
  192. /**
  193. * 桶装出库
  194. *
  195. * @param locationFrom
  196. * @param locationTo
  197. * @return
  198. */
  199. public AjaxResult barrelsOutOfStorage(String locationFrom, String locationTo, String palletNo, String wcsId) {
  200. AgvCallDTO agvCallDTO = new AgvCallDTO();
  201. agvCallDTO.setLocationFrom(locationFrom);
  202. agvCallDTO.setLocationTo(locationTo);
  203. List<AgvCallItemDTO> agvCallItemDTOList = new ArrayList<>();
  204. LotattDTO lotattDTO = new LotattDTO();
  205. lotattDTO.setLotatt07(palletNo);
  206. lotattDTO.setLotatt08(wcsId);
  207. AgvCallItemDTO agvCallItemDTO = new AgvCallItemDTO();
  208. agvCallItemDTO.setSku("C4H9O2PSSNH4"); // 丁铵黑药
  209. agvCallItemDTO.setLotattDTO(lotattDTO);
  210. agvCallItemDTOList.add(agvCallItemDTO);
  211. agvCallDTO.setAgvCallItemDTOList(agvCallItemDTOList);
  212. return iBusinessService.agvCall(Constant.FLOW_CONFIG_ID.ONE.getValue(), agvCallDTO);
  213. }
  214. private WcsResponseVo noticeBucketOutLocTask(String taskNo, String bucketCacheLocationId, String orderNo, String materialType, Double quantity, BaseLocationInfo baseLocationInfo) {
  215. BaseSku baseSku = iBaseSkuService.selectBaseSkuByMaterialType(materialType);
  216. Assert.isTrue(ObjectUtil.isNotNull(baseSku), "baseSku is null");
  217. //1.生成一个wcs任务
  218. String locationInfoId = String.valueOf(baseLocationInfo.getId());
  219. wcsTaskSubService.addWcsOutTask(taskNo, locationInfoId, bucketCacheLocationId, orderNo);
  220. //4.组装wcs任务请求参数并同步当前的wcs任务
  221. OutTaskForm outTaskForm = assemblyOutTaskForm(taskNo, orderNo, baseSku.getSkuType(), materialType, quantity, baseLocationInfo);
  222. return wmsToWcsApiService.wmsOutTask(outTaskForm);
  223. }
  224. private WcsResponseVo noticeBucketIntoLocTask(String taskNo, String bucketCacheLocationId, String asnNo, String palletNo, String materialType, Double quantity) {
  225. BaseSku baseSku = iBaseSkuService.selectBaseSkuByMaterialType(materialType);
  226. Assert.isTrue(ObjectUtil.isNotNull(baseSku), "baseSku is null");
  227. // 1.推荐目标库位
  228. BaseLocationInfo baseLocationInfo = baseLocationInfoSubService.recommendAReceiptLocation(baseSku.getSku());
  229. Assert.isTrue(ObjectUtil.isNotNull(baseLocationInfo), "baseLocationLotatt is null");
  230. // 2.桶装接驳位生成库存
  231. invLotLocIdSubService.initInv(bucketCacheLocationId, baseSku.getSku(), palletNo, asnNo, taskNo, quantity);
  232. // 3.生成任务
  233. wcsTaskSubService.addWcsTask(taskNo, bucketCacheLocationId
  234. , String.valueOf(baseLocationInfo.getId()), asnNo, palletNo, Constant.TASK_STS.TASK_PUBILSH.getLongValue(), "四向车入库任务");
  235. //4.同步当前的wcs任务
  236. AgvInTaskForm agvInTaskForm = assemblyAgvInTaskForm(taskNo, asnNo, materialType, quantity, palletNo, baseLocationInfo);
  237. return wmsToWcsApiService.wmsAgvInTask(agvInTaskForm);
  238. }
  239. private OutTaskForm assemblyOutTaskForm(String taskNo, String orderNo, String skuType, String materialType, Double quantity, BaseLocationInfo baseLocationInfo) {
  240. OutTaskForm outTaskForm = new OutTaskForm();
  241. outTaskForm.setDocNo(orderNo);
  242. outTaskForm.setTaskNo(taskNo);
  243. outTaskForm.setRow(Integer.valueOf(baseLocationInfo.getRowIndex()));
  244. outTaskForm.setCol(Integer.parseInt(baseLocationInfo.getRowNo()));
  245. outTaskForm.setFloor(Integer.parseInt(baseLocationInfo.getShiftNo()));
  246. outTaskForm.setPackageType(Integer.valueOf(skuType));
  247. outTaskForm.setMaterial(Integer.valueOf(materialType));
  248. outTaskForm.setTotal(quantity.intValue());
  249. return outTaskForm;
  250. }
  251. private AgvInTaskForm assemblyAgvInTaskForm(String taskNo, String asnNo, String materialType, Double quantity, String palletNo, BaseLocationInfo baseLocationInfo) {
  252. AgvInTaskForm agvInTaskForm = new AgvInTaskForm();
  253. agvInTaskForm.setTaskNo(taskNo);
  254. agvInTaskForm.setAgvId("1");
  255. agvInTaskForm.setMaterial(Integer.valueOf(materialType));
  256. agvInTaskForm.setDocNo(asnNo);
  257. agvInTaskForm.setNum(quantity.intValue());
  258. agvInTaskForm.setPalletId(palletNo);
  259. agvInTaskForm.setRow(Integer.valueOf(baseLocationInfo.getRowIndex()));
  260. agvInTaskForm.setCol(Integer.valueOf(baseLocationInfo.getRowNo()));
  261. agvInTaskForm.setFloor(Integer.valueOf(baseLocationInfo.getShiftNo()));
  262. return agvInTaskForm;
  263. }
  264. private Long getAgvLocationId(String subSceneCode) {
  265. List<Long> bucketLocationIdList = iWcsTaskService.getBucketLocationIdList(subSceneCode);
  266. Assert.isTrue(CollectionUtil.isNotEmpty(bucketLocationIdList), "bucketLocationIdList is empty");
  267. BaseLocationInfo agvTargetLocationInfo = iBaseLocationInfoService.selectBaseLocationInfoById(bucketLocationIdList.get(0));
  268. return ObjectUtil.isNotNull(agvTargetLocationInfo) ? agvTargetLocationInfo.getId() : Constant.DRUM_CONNECTORS;
  269. }
  270. }