AgvCallProxyService.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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.inv.service.IInvLotLocIdService;
  15. import com.ruoyi.ams.order.domain.WmsDocOrderDetails;
  16. import com.ruoyi.ams.order.domain.WmsDocOrderHeader;
  17. import com.ruoyi.ams.order.service.IWmsDocOrderDetailsService;
  18. import com.ruoyi.ams.order.service.IWmsDocOrderHeaderService;
  19. import com.ruoyi.ams.task.service.IWcsTaskService;
  20. import com.ruoyi.ams.xuankuang.domain.form.AgvInTaskForm;
  21. import com.ruoyi.ams.xuankuang.domain.form.OutTaskForm;
  22. import com.ruoyi.ams.xuankuang.domain.vo.WcsResponseVo;
  23. import com.ruoyi.base.constant.Constant;
  24. import com.ruoyi.base.domain.BaseLocationInfo;
  25. import com.ruoyi.base.domain.BaseSku;
  26. import com.ruoyi.base.domain.vo.BaseLocationLotattDTO;
  27. import com.ruoyi.base.service.IBaseLocationInfoService;
  28. import com.ruoyi.base.service.IBaseSkuService;
  29. import com.ruoyi.base.utils.IdSequenceUtils;
  30. import com.ruoyi.common.core.domain.AjaxResult;
  31. import com.ruoyi.common.utils.StringUtils;
  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 IdSequenceUtils idSequenceUtils;
  57. @Autowired
  58. private IWmsDocAsnHeaderService iWmsDocAsnHeaderService;
  59. @Autowired
  60. private IWmsDocAsnDetailsService iWmsDocAsnDetailsService;
  61. @Autowired
  62. private IWmsDocOrderHeaderService iWmsDocOrderHeaderService;
  63. @Autowired
  64. private IWmsDocOrderDetailsService iWmsDocOrderDetailsService;
  65. @Autowired
  66. private WmsDocOrderSubService wmsDocOrderSubService;
  67. @Autowired
  68. private WcsTaskSubService wcsTaskSubService;
  69. @Autowired
  70. private WmsToWcsApiService wmsToWcsApiService;
  71. @Autowired
  72. private IBaseLocationInfoService iBaseLocationInfoService;
  73. @Autowired
  74. private InvLotLocIdSubService invLotLocIdSubService;
  75. @Autowired
  76. private IWcsTaskService iWcsTaskService;
  77. @Autowired
  78. private IInvLotLocIdService invLotLocIdService;
  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.selectSkuByMaterialType(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. addWcsTask(agvTaskNo, agvSourceLocationId, agvTargetLocationId,
  99. asnNo, palletNo, Constant.TASK_STS.TASK_CREATE.getLongValue(), "AGV入库任务下发", Constant.TaskType.AGV.getDesc());
  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.selectSkuByMaterialType(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. addWcsOutTask(agvTaskNo, agvSourceLocationId, targetLocationId,
  136. orderNo, Constant.TASK_STS.TASK_CREATE.getLongValue(), "AGV出库任务下发", Constant.TaskType.AGV.getDesc());
  137. //3.出库单创建
  138. WmsDocOrderHeader docOrderHeader =
  139. iWmsDocOrderHeaderService.createOrderHeader(orderNo, Constant.ORDER_TYP.TZ.getValue(), Constant.ORDER_STS.STS00.getValue(), baseSku.getSku());
  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. //通知wcs的桶装出库的任务
  150. WcsResponseVo wcsResponseVo = noticeBucketOutLocTask(IdWorker.getIdStr(), agvSourceLocationId, orderNo, materialType, quantity, baseLocationInfo);
  151. if (!wcsResponseVo.isSuccess()) {
  152. //errorCount++;
  153. docOrderHeader.setRemark(wcsResponseVo.getMessage());
  154. iWmsDocOrderHeaderService.updateWmsDocOrderHeader(docOrderHeader);
  155. }
  156. }
  157. //此处屏蔽的代码:代表只有在全部同步失败的情况下,不改变单头和明细的状态
  158. //if(errorCount == filteredBaseLocationLotattList.size()) return;
  159. docOrderHeader.setOrderStatus(Constant.ASN_STS.STS10.getValue());
  160. docOrderDetail.setLineStatus(Constant.ASN_STS.STS10.getValue());
  161. iWmsDocOrderDetailsService.updateWmsDocOrderDetails(docOrderDetail);
  162. iWmsDocOrderHeaderService.updateWmsDocOrderHeader(docOrderHeader);
  163. }
  164. /**
  165. * 主方法:桶装越库
  166. * @param palletNo 托盘号
  167. * @param materialType 物料类型 丁胺黑药类型5
  168. * @param sourceLocationId 起始库位
  169. * @param targetLocationId 目标库位
  170. * @param quantity 数量 不大于4
  171. */
  172. public void bucketCrossStorage(String palletNo, String materialType, String sourceLocationId, String targetLocationId, Double quantity) {
  173. //1.预备参数设置
  174. Assert.isTrue(ObjectUtil.isNotNull(quantity) && quantity > 0, "quantity is illegal");
  175. BaseSku baseSku = iBaseSkuService.selectBaseSkuByMaterialType(materialType);
  176. Assert.isTrue(ObjectUtil.isNotNull(baseSku) && StringUtils.isNotBlank(baseSku.getSku()), "the materialType is illegal");
  177. BigDecimal quantityDecimal = new BigDecimal(quantity);
  178. //2.入库单创建
  179. String asnNo = idSequenceUtils.generateId(Constant.ID_TYPE.ASNNO.getDesc());
  180. iWmsDocAsnHeaderService.createAsnHeader(asnNo, Constant.ASN_TYP.TZ.getValue(), Constant.ASN_STS.STS40.getValue());
  181. iWmsDocAsnDetailsService.createAsnDetail(asnNo, baseSku.getSku(), quantityDecimal);
  182. //3.出库单创建
  183. String orderNo = idSequenceUtils.generateId(Constant.ID_TYPE.ORDERNO.getDesc());
  184. iWmsDocOrderHeaderService.createOrderHeader(orderNo, Constant.ORDER_TYP.TZ.getValue(), Constant.ORDER_STS.STS40.getValue(), baseSku.getSku());
  185. iWmsDocOrderDetailsService.createOrderDetail(orderNo, baseSku.getSku(), quantityDecimal);
  186. //2. 获取agv的库位,并创建agv的wcs任务
  187. String agvTaskNo = IdWorker.getIdStr();
  188. wcsTaskSubService.addCrossWcsTask(agvTaskNo, sourceLocationId, targetLocationId,
  189. asnNo, palletNo, orderNo, Constant.TASK_STS.TASK_WAIT.getLongValue(), "agv越库任务下发");
  190. }
  191. /**
  192. * 桶装出库
  193. *
  194. * @param locationFrom
  195. * @param locationTo
  196. * @return
  197. */
  198. public AjaxResult barrelsOutOfStorage(String locationFrom, String locationTo, String palletNo, String wcsId) {
  199. AgvCallDTO agvCallDTO = new AgvCallDTO();
  200. agvCallDTO.setLocationFrom(locationFrom);
  201. agvCallDTO.setLocationTo(locationTo);
  202. List<AgvCallItemDTO> agvCallItemDTOList = new ArrayList<>();
  203. LotattDTO lotattDTO = new LotattDTO();
  204. lotattDTO.setLotatt07(palletNo);
  205. lotattDTO.setLotatt08(wcsId);
  206. AgvCallItemDTO agvCallItemDTO = new AgvCallItemDTO();
  207. agvCallItemDTO.setSku("C4H9O2PSSNH4"); // 丁铵黑药
  208. agvCallItemDTO.setLotattDTO(lotattDTO);
  209. agvCallItemDTOList.add(agvCallItemDTO);
  210. agvCallDTO.setAgvCallItemDTOList(agvCallItemDTOList);
  211. return iBusinessService.agvCall(Constant.FLOW_CONFIG_ID.ONE.getValue(), agvCallDTO);
  212. }
  213. private WcsResponseVo noticeBucketOutLocTask(String taskNo, String bucketCacheLocationId, String orderNo, String materialType, Double quantity, BaseLocationInfo baseLocationInfo) {
  214. BaseSku baseSku = iBaseSkuService.selectSkuByMaterialType(materialType);
  215. Assert.isTrue(ObjectUtil.isNotNull(baseSku) && StringUtils.isNotBlank(baseSku.getSku()) , "baseSku is null");
  216. //1.生成一个wcs任务
  217. String locationInfoId = String.valueOf(baseLocationInfo.getId());
  218. addWcsOutTask(taskNo, locationInfoId, bucketCacheLocationId, orderNo, 10L, "桶装料出库任务", Constant.TaskType.RGV.getDesc());
  219. //修改出库出库存的traceId TODO
  220. invLotLocIdService.operateTraceIdByLocationId(locationInfoId, taskNo);
  221. //4.组装wcs任务请求参数并同步当前的wcs任务
  222. OutTaskForm outTaskForm = assemblyOutTaskForm(taskNo, orderNo, baseSku.getSkuType(), materialType, quantity, baseLocationInfo);
  223. return wmsToWcsApiService.wmsOutTask(outTaskForm);
  224. }
  225. private AjaxResult addWcsTask(String taskNo, String locationFrom, String locationTo
  226. , String asnNo, String palletNo, Long state, String remake, String taskType) {
  227. return wcsTaskSubService.addWcsTask(taskNo, locationFrom, locationTo, asnNo, palletNo, StringUtils.EMPTY, state, remake, taskType);
  228. }
  229. private AjaxResult addWcsOutTask(String taskNo, String locationFrom, String locationTo,
  230. String orderNo, Long status, String remark, String taskType) {
  231. return wcsTaskSubService.addWcsOutTask(taskNo, locationFrom, locationTo
  232. , orderNo, StringUtils.EMPTY, StringUtils.EMPTY, status, remark, taskType);
  233. }
  234. private WcsResponseVo noticeBucketIntoLocTask(String taskNo, String bucketCacheLocationId, String asnNo, String palletNo, String materialType, Double quantity) {
  235. BaseSku baseSku = iBaseSkuService.selectBaseSkuByMaterialType(materialType);
  236. Assert.isTrue(ObjectUtil.isNotNull(baseSku), "baseSku is null");
  237. // 1.推荐目标库位
  238. BaseLocationInfo baseLocationInfo = baseLocationInfoSubService.recommendAReceiptLocation(baseSku.getSku());
  239. Assert.isTrue(ObjectUtil.isNotNull(baseLocationInfo), "baseLocationLotatt is null");
  240. // 2.桶装接驳位生成库存
  241. invLotLocIdSubService.initInv(bucketCacheLocationId, baseSku.getSku(), palletNo, asnNo, taskNo, quantity);
  242. // 3.生成任务
  243. addWcsTask(taskNo, bucketCacheLocationId
  244. , String.valueOf(baseLocationInfo.getId()), asnNo, palletNo,
  245. Constant.TASK_STS.TASK_PUBILSH.getLongValue(), "桶装料入库任务",
  246. Constant.TaskType.RGV.getDesc());
  247. //4.同步当前的wcs任务
  248. AgvInTaskForm agvInTaskForm = assemblyAgvInTaskForm(taskNo, asnNo, materialType, quantity, palletNo, baseLocationInfo);
  249. return wmsToWcsApiService.wmsAgvInTask(agvInTaskForm);
  250. }
  251. private OutTaskForm assemblyOutTaskForm(String taskNo, String orderNo, String skuType, String materialType, Double quantity, BaseLocationInfo baseLocationInfo) {
  252. OutTaskForm outTaskForm = new OutTaskForm();
  253. outTaskForm.setDocNo(orderNo);
  254. outTaskForm.setTaskNo(taskNo);
  255. outTaskForm.setRow(Integer.valueOf(baseLocationInfo.getRowIndex()));
  256. outTaskForm.setCol(Integer.parseInt(baseLocationInfo.getRowNo()));
  257. outTaskForm.setFloor(Integer.parseInt(baseLocationInfo.getShiftNo()));
  258. outTaskForm.setPackageType(Integer.valueOf(skuType));
  259. outTaskForm.setMaterial(Integer.valueOf(materialType));
  260. outTaskForm.setTotal(quantity.intValue());
  261. return outTaskForm;
  262. }
  263. private AgvInTaskForm assemblyAgvInTaskForm(String taskNo, String asnNo, String materialType, Double quantity, String palletNo, BaseLocationInfo baseLocationInfo) {
  264. AgvInTaskForm agvInTaskForm = new AgvInTaskForm();
  265. agvInTaskForm.setTaskNo(taskNo);
  266. agvInTaskForm.setAgvId("1");
  267. agvInTaskForm.setMaterial(Integer.valueOf(materialType));
  268. agvInTaskForm.setDocNo(asnNo);
  269. agvInTaskForm.setNum(quantity.intValue());
  270. agvInTaskForm.setPalletId(palletNo);
  271. agvInTaskForm.setRow(Integer.valueOf(baseLocationInfo.getRowIndex()));
  272. agvInTaskForm.setCol(Integer.valueOf(baseLocationInfo.getRowNo()));
  273. agvInTaskForm.setFloor(Integer.valueOf(baseLocationInfo.getShiftNo()));
  274. return agvInTaskForm;
  275. }
  276. private Long getAgvLocationId(String subSceneCode) {
  277. List<Long> bucketLocationIdList = iWcsTaskService.getBucketLocationIdList(subSceneCode);
  278. Assert.isTrue(CollectionUtil.isNotEmpty(bucketLocationIdList), "bucketLocationIdList is empty");
  279. BaseLocationInfo agvTargetLocationInfo = iBaseLocationInfoService.selectBaseLocationInfoById(bucketLocationIdList.get(0));
  280. return ObjectUtil.isNotNull(agvTargetLocationInfo) ? agvTargetLocationInfo.getId() : Constant.DRUM_CONNECTORS;
  281. }
  282. }