ProductBLL.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. using SqlSugar;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using WMS.Core._02Entity;
  7. using WMS.Core.AppBll;
  8. using WMS.Info;
  9. using WMS.Info.Models;
  10. using WMS.Util;
  11. namespace WMS.Core.APPBLL
  12. {
  13. public class ProductBLL : AppCoreBLL
  14. {
  15. public ResInfo StockOutPickSubimit(ProductStockOutRequest request)
  16. {
  17. using (var ctx = SysDbCore.GetDbCtx())
  18. {
  19. ctx.BeginTran();
  20. try
  21. {
  22. if (string.IsNullOrWhiteSpace(request?.TrayNo) || !request.BoxNos.Any() || !request.OrderLines.Any())
  23. throw SysExCore.ThrowFailException("参数不能为空");
  24. //根据托盘码获取出库单号
  25. var stockOutEntity = ctx.Queryable<BILL_STOCKOUT, BILL_STOCKOUTLINEDETAIL>((ord, detail) => new object[] { JoinType.Inner, ord.F_no == detail.F_pNo })
  26. .Where((ord, detail) => detail.F_trayNo == request.TrayNo && ord.F_orderStatus != (int)EOrderState.Executed).Select<BILL_STOCKOUT>().First();
  27. if(stockOutEntity==null)
  28. throw SysExCore.ThrowFailException("当前托盘已不存在需要出库信息,请同步销售工单后再进行拣选出库!");
  29. ctx.Updateable<BILL_STOCKOUTLINE>().SetColumns(it => new BILL_STOCKOUTLINE
  30. {
  31. F_editTime = DateTime.Now,
  32. F_editUserNo = LoginUser.UserNo,
  33. F_actualQty = request.OrderLines.Sum(s => s.F_actualQty)
  34. }).Where(w => w.F_matNo == request.OrderLines.FirstOrDefault().F_matNo && w.F_pNo == stockOutEntity.F_no).ExecuteCommand();
  35. var stockOutLineLst = ctx.Queryable<BILL_STOCKOUTLINE>().Where(w => w.F_pNo == stockOutEntity.F_no).ToList();
  36. if (!stockOutLineLst.Any(a => a.F_actualQty != a.F_planQty))
  37. {
  38. ctx.Updateable<BILL_STOCKOUT>().SetColumns(it => new BILL_STOCKOUT
  39. {
  40. F_editTime = DateTime.Now,
  41. F_editUserNo = LoginUser.UserNo,
  42. F_orderStatus = (int)EOrderState.Executed
  43. }).Where(w => w.F_no == stockOutEntity.F_no).ExecuteCommand();
  44. }
  45. List<BILL_INVENTORY> lstInv = new List<BILL_INVENTORY>();
  46. foreach (var box in request.BoxNos.Distinct())
  47. {
  48. var inv = ctx.Queryable<BILL_INVENTORY>().First(f => f.F_trayNo == request.TrayNo && f.F_boxNo == box && f.F_matNo == request.OrderLines.FirstOrDefault().F_matNo);
  49. var detail = ctx.Queryable<BILL_STOCKOUTLINEDETAIL>().Where(f => f.F_pNo == stockOutEntity.F_no && f.F_trayNo == request.TrayNo && f.F_boxNo == box).First();
  50. if (inv == null || detail == null)
  51. continue;
  52. inv.F_quantity = detail.F_quantity * -1;
  53. lstInv.Add(inv);
  54. }
  55. //更新库存
  56. UpdateInventory(lstInv, ctx);
  57. ctx.CommitTran();
  58. return SysExCore.GetResSucc("出库成功!");
  59. }
  60. catch (Exception ex)
  61. {
  62. ctx.RollbackTran();
  63. throw ex;
  64. }
  65. finally
  66. {
  67. ctx.Dispose();
  68. }
  69. }
  70. }
  71. public ResInfo Entry(ScanCodeRequest reqData)
  72. {
  73. using (var ctx = SysDbCore.GetDbCtx())
  74. {
  75. try
  76. {
  77. if (string.IsNullOrWhiteSpace(reqData?.LocationNo) || string.IsNullOrWhiteSpace(reqData.TrayNo))
  78. throw SysExCore.ThrowFailException("参数不能为空");
  79. ctx.BeginTran();
  80. //获取当前点位信息
  81. var location = GetPointInfo(reqData.LocationNo);
  82. if (location == null)
  83. throw SysExCore.ThrowFailException("请输入有效的位置码!");
  84. if (location.F_type != (int)EPointType.CPRKJXK && location.F_type != (int)EPointType.CPCKJXK)
  85. throw SysExCore.ThrowFailException("请扫描正确的成品入库拣选口!");
  86. if (location.F_type == (int)EPointType.YCK)//异常口处理逻辑
  87. {
  88. var curTask = ctx.Queryable<WMS_TASK>().Where(f => f.F_taskStatus < (int)ETaskStatus.TaskFinish && f.F_trayNo == reqData.TrayNo).First();
  89. if (curTask == null)
  90. throw SysExCore.ThrowFailException("当前异常任务找不到对应的入库任务!");
  91. ctx.Updateable<WMS_TASK>().SetColumns(it => new WMS_TASK()
  92. {
  93. F_editTime = DateTime.Now,
  94. F_editUserNo = LoginUser.UserNo,
  95. F_posidFrom = reqData.LocationNo,
  96. F_posidcur = reqData.LocationNo,
  97. F_taskStatus = (int)ETaskStatus.NotIssued,
  98. F_posidNext = "1036"
  99. }).Where(w => w.F_taskNo == curTask.F_taskNo).ExecuteCommand();
  100. ctx.CommitTran();
  101. return SysExCore.GetResSucc("异常口任务生成成功");
  102. }
  103. var trayLocation = new FxBaseLocationCore().GetLociotnByTrayNo(reqData.TrayNo);
  104. if (trayLocation != null && trayLocation.F_status != (int)EWareCellState.Empty)
  105. throw SysExCore.ThrowFailException("当前托盘号已存在货位数据");
  106. var entryOrder = new BILL_ENTRYORDER
  107. {
  108. F_no = SerialNumberProvider.Instance.OrderNumber("wms", "RK"),
  109. F_addTime = DateTime.Now,
  110. F_addUserNo = LoginUser.UserNo,
  111. F_editTime = DateTime.Now,
  112. F_locationNo = reqData.LocationNo,
  113. F_orderStatus = (int)EOrderState.New,
  114. F_orderType = (int)EEntryOrderType.EntryOrderTypeProduct,
  115. F_trayNo = reqData.TrayNo,
  116. F_isBonded = reqData.TrayNo.StartsWith("B"),
  117. F_warehouseNo = SysSetCore.GetSysSet().DefaultWarehouseNo
  118. };
  119. var task = new WMS_TASK
  120. {
  121. F_addTime = DateTime.Now,
  122. F_addUserNo = LoginUser.UserNo,
  123. F_editTime = DateTime.Now,
  124. F_trayNo = reqData.TrayNo,
  125. F_posidNext = GetFreePointInfoByType((int)EPointType.RKDFPHWDW).F_no,
  126. F_priority = (int)EPriority.NotUrgent,
  127. F_taskStatus = (int)ETaskStatus.NotIssued,
  128. F_taskType = (int)ETaskComType.InStock,
  129. F_orderType = (int)ETaskOrderType.EntryOrderTypeProduct,
  130. F_posidFrom = reqData.LocationNo,
  131. F_posidcur = reqData.LocationNo,
  132. F_EquipmentType = (int)EEquipmentType.Convey,
  133. F_isBonded = reqData.TrayNo.StartsWith("B"),
  134. };
  135. task.F_orderNo = entryOrder.F_no;
  136. if (location.F_type == (int)EPointType.CPCKJXK)
  137. {
  138. #region 出库拣选入库
  139. var invs = ctx.Queryable<BILL_INVENTORY>().Where(i => i.F_trayNo == reqData.TrayNo && i.F_quantity > 0).ToList();
  140. if (!invs.Any())
  141. throw SysExCore.ThrowFailException("当前托盘信息为空!");
  142. entryOrder.F_totalOrderLines = invs.Count();
  143. invs.ForEach(inv =>
  144. {
  145. ctx.Insertable(new BILL_ENTRYORDERLINEDETAIL
  146. {
  147. F_addTime = DateTime.Now,
  148. F_addUserNo = LoginUser.UserNo,
  149. F_quantity = inv.F_quantity,
  150. F_matNo = inv.F_matNo,
  151. F_matName = inv.F_matName,
  152. F_matType = (int)EMatType.Product,
  153. F_pNo = entryOrder.F_no,
  154. F_trayNo = inv.F_trayNo,
  155. F_batchNo = inv.F_batchNo,
  156. F_boxNo = inv.F_boxNo,
  157. }).ExecuteCommand();
  158. });
  159. #endregion
  160. }
  161. if (location.F_type == (int)EPointType.CPRKJXK)
  162. {
  163. #region 组盘拣选入库
  164. List<BILL_INVENTORY> lstInv = new List<BILL_INVENTORY>();
  165. var matInfos = ctx.Queryable<FX_wo_mstr, FX_wo_mstr_info>((wo, info) => new object[] { JoinType.Inner, wo.order_code == info.order_code })
  166. .Where((wo, info) => info.tray_no == reqData.TrayNo && wo.wo_status == 1).Select<FX_wo_mstr_info>().ToList();
  167. if (!matInfos.Any())
  168. throw SysExCore.ThrowFailException($"未获取到托盘号{reqData.TrayNo}组盘信息");
  169. matInfos.ForEach(orderLine =>
  170. {
  171. var mat = CacheFacade.GetMatInfo(orderLine.wo_part, EMatType.Product);
  172. ctx.Insertable(new BILL_ENTRYORDERLINEDETAIL
  173. {
  174. F_addTime = DateTime.Now,
  175. F_addUserNo = LoginUser.UserNo,
  176. F_quantity = orderLine.qty,
  177. F_matNo = orderLine.wo_part,
  178. F_matName = mat?.F_matName,
  179. F_matType = (int)EMatType.Product,
  180. F_pNo = entryOrder.F_no,
  181. F_boxNo = orderLine.box_code,
  182. F_trayNo = reqData.TrayNo
  183. }).ExecuteCommand();
  184. var matDetail = ctx.Queryable<FX_wo_mstr_info>().Where(c => c.order_code == orderLine.order_code && c.wo_part == orderLine.wo_part).ToList();
  185. foreach (var item in matDetail)
  186. {
  187. lstInv.Add(new BILL_INVENTORY
  188. {
  189. F_addTime = DateTime.Now,
  190. F_addUserNo = LoginUser.UserNo,
  191. F_editTime = DateTime.Now,
  192. F_matNo = item.wo_part,
  193. F_matType = (int)EMatType.Product,
  194. F_projectNo = mat.F_projectNo,
  195. F_quantity = item.qty,
  196. F_unit = mat?.F_unit,
  197. F_boxNo = item.box_code,
  198. F_matName = mat?.F_matName,
  199. F_trayNo = reqData.TrayNo,
  200. F_warehouseNo = SysSetCore.GetSysSet().DefaultWarehouseNo,
  201. F_isBonded = reqData.TrayNo.StartsWith("B"),
  202. });
  203. }
  204. });
  205. entryOrder.F_totalOrderLines = matInfos.Count;
  206. entryOrder.F_relatedOrderNo = string.Join(",", matInfos.Select(s => s.order_code));
  207. ctx.Updateable<FX_wo_mstr>().SetColumns(it => new FX_wo_mstr()
  208. {
  209. edit_Time = DateTime.Now,
  210. edit_user = LoginUser.UserNo,
  211. wo_status = 2
  212. }).Where(w => w.order_code == matInfos.First().order_code).ExecuteCommand();
  213. //更新库存
  214. UpdateInventory(lstInv, ctx);
  215. #endregion
  216. }
  217. ctx.Insertable(entryOrder).ExecuteCommand();
  218. ctx.Insertable(task).ExecuteReturnEntity();
  219. ctx.CommitTran();
  220. return SysExCore.GetResSucc("成品入库任务生成成功");
  221. }
  222. catch (Exception ex)
  223. {
  224. ctx.RollbackTran();
  225. throw ex;
  226. }
  227. }
  228. }
  229. /// <summary>
  230. /// 工单提交验证并获取出库明细
  231. /// </summary>
  232. /// <param name="reqData"></param>
  233. /// <returns></returns>
  234. public ResInfo WorkOrderSubmit(WorkOrderRequest reqData)
  235. {
  236. if (reqData?.workOrders.Count < 1)
  237. {
  238. SysExCore.ThrowFailException("请求工单数据不能为空");
  239. }
  240. using (var ctx = SysDbCore.GetDbCtx())
  241. {
  242. try
  243. {
  244. //验证工单
  245. StringBuilder sb = new StringBuilder();
  246. sb.Append(@" <dsWorkOrderReceipt>");
  247. foreach (var item in reqData.workOrders)
  248. {
  249. //if (ctx.Queryable<FX_wo_mstr>().Any(c => c.wo_lot == item.wo_lot))
  250. // throw SysExCore.ThrowFailException($"工单{item.wo_lot}已经验证过!");
  251. sb.Append("<workOrderReceipt>");
  252. sb.Append($"<woLot>{item.wo_lot}</woLot>");
  253. sb.Append($"<lotserialQty>{item.wo_qty_ord}</lotserialQty> ");
  254. sb.Append($"<lotserial>{item.lotserial}</lotserial>");
  255. sb.Append($"<location>{item.location}</location>");
  256. sb.Append(@"</workOrderReceipt>");
  257. }
  258. sb.Append(@" </dsWorkOrderReceipt>");
  259. var res = WebServiceCall.callWebService(SysSetCore.GetSysSet().FxWebServiceUrl, "processQdocMessage", sb.ToString());
  260. if (res.Contains("<ns1:result>error</ns1:result>"))
  261. throw SysExCore.ThrowFailException($"工单验证失败!{string.Join(",", new TransferBLL().WebSerciceResponse(res))}");
  262. //string whereStr = string.Join("','", reqData.workOrders.Select(s => s.wo_lot));
  263. reqData.workOrders.ForEach(order =>
  264. {
  265. if (ctx.Queryable<FX_wo_mstr>().Any(a => a.wo_lot == order.wo_lot))
  266. throw SysExCore.ThrowFailException($"工单{ order.wo_lot}已存在!");
  267. var fxmat = FxDbCore.GetData<FX_wo_mstr>($"select * from pub.wo_mstr where wo_domain = 'AFCN' and wo_site='SUZ' and wo_lot ='{order.wo_lot}' ");
  268. fxmat.ForEach(mat =>
  269. {
  270. mat.order_code = SerialNumberProvider.Instance.OrderNumber("wms", "ZP");
  271. mat.add_Time = DateTime.Now;
  272. mat.add_user = LoginUser.UserNo;
  273. mat.wo_qty_ord = order.wo_qty_ord;
  274. mat.wo_qty_comp = 0;
  275. mat.wo_loc = order.location;
  276. mat.wo_lotserial = order.lotserial;
  277. mat.edit_Time = DateTime.Now;
  278. mat.wo_lot = order.wo_lot;
  279. var woMat = ctx.Queryable<FX_wo_mstr>().Where(a => a.wo_lot == mat.wo_lot && a.wo_part == mat.wo_part).First();
  280. if (woMat != null)
  281. {
  282. ctx.Updateable<FX_wo_mstr>().SetColumns(it => new FX_wo_mstr
  283. {
  284. wo_qty_ord = woMat.wo_qty_ord + order.wo_qty_ord,
  285. wo_status = 0,
  286. edit_Time = DateTime.Now,
  287. edit_user = LoginUser.UserNo,
  288. }).Where(w => w.order_code == woMat.order_code && w.wo_lot == woMat.wo_lot && w.wo_part == woMat.wo_part).ExecuteCommand();
  289. }
  290. else
  291. {
  292. ctx.Insertable(fxmat).ExecuteCommand();
  293. }
  294. });
  295. });
  296. ctx.CommitTran();
  297. return SysExCore.GetResSucc("验证成功!");
  298. }
  299. catch (Exception ex)
  300. {
  301. ctx.RollbackTran();
  302. throw ex;
  303. }
  304. }
  305. }
  306. /// <summary>
  307. /// 已验证工单查询
  308. /// </summary>
  309. /// <param name="lotNo"></param>
  310. /// <returns></returns>
  311. public ResInfo WorkOrderQuery(string lotNo)
  312. {
  313. var woEntity = SysDbCore.GetDbCtx().Queryable<FX_wo_mstr>().Where(w => w.wo_lot == lotNo).ToList();
  314. return SysExCore.GetResSucc(data: woEntity);
  315. }
  316. /// <summary>
  317. /// 根据栈板或箱码获取物料明细
  318. /// </summary>
  319. /// <param name="code"></param>
  320. /// <returns></returns>
  321. public ResInfo CombByFxCode(string code)
  322. {
  323. return null;
  324. //FxWebReference.interfaceClass interfaceClass = new FxWebReference.interfaceClass();
  325. ////FxWebReference.interfaceClassPortTypeClient interfaceClass = new FxWebReference.interfaceClassPortTypeClient();
  326. //var param = new
  327. //{
  328. // uuid = Guid.NewGuid().ToString(),
  329. // condition = new
  330. // {
  331. // code = code
  332. // },
  333. // dataType = "getBoxOrPalletData"
  334. //};
  335. //var res = interfaceClass.GetDataFromMes(param.ToJson());
  336. //var respEntity = res.ToObject<ProductResponse>();
  337. //if (respEntity.result != "PASS")
  338. // throw SysExCore.ThrowFailException(respEntity.message);
  339. //if (respEntity.responseData?.is_success != true)
  340. // throw SysExCore.ThrowFailException(respEntity.responseData.message);
  341. //var wo = SysDbCore.GetDbCtx().Queryable<FX_wo_mstr>().Where(c => c.add_user == LoginUser.UserNo && c.wo_qty_comp < c.wo_qty_ord && c.wo_status < 1 && SqlFunc.ContainsArray(respEntity.responseData.data.Select(S => S.pt_part).ToList(), c.wo_part)).OrderBy(o => o.add_Time).First();
  342. //if (wo == null)
  343. // throw SysExCore.ThrowFailException("找到不该物料对应的已验证工单或该托盘数量大于工单计划数量");
  344. //List<MatInfo> matInfos = new List<MatInfo>();
  345. //respEntity.responseData.data.ForEach(item =>
  346. //{
  347. // var mat = CacheFacade.GetMatInfo(item.pt_part, EMatType.Product);
  348. // matInfos.Add(new MatInfo
  349. // {
  350. // order_code = wo.order_code,
  351. // boxCode = item.box_code,
  352. // matNo = item.pt_part,
  353. // quantity = item.qty,
  354. // productDate = item.pro_time,
  355. // matType = (int)EMatType.Product,
  356. // matName = mat.F_matName,
  357. // });
  358. //});
  359. //return SysExCore.GetResSucc(data: matInfos);
  360. }
  361. /// <summary>
  362. /// 组盘提交
  363. /// </summary>
  364. /// <param name="reqData"></param>
  365. /// <returns></returns>
  366. public ResInfo CombSubmit(PackTrayRequest reqData)
  367. {
  368. if (!reqData.Mats.Any())
  369. throw SysExCore.ThrowFailException("组盘信息不能为空");
  370. var trayLocation = new FxBaseLocationCore().GetLociotnByTrayNo(reqData.TrayNo);
  371. if (trayLocation != null && trayLocation.F_status != (int)EWareCellState.Empty)
  372. throw SysExCore.ThrowFailException("当前托盘号已存在货位数据");
  373. using (var ctx = SysDbCore.GetDbCtx())
  374. {
  375. try
  376. {
  377. ctx.BeginTran();
  378. List<FX_wo_mstr_info> mstr_Infos = new List<FX_wo_mstr_info>();
  379. reqData.Mats.ForEach(mat =>
  380. {
  381. mstr_Infos.Add(new FX_wo_mstr_info
  382. {
  383. pro_time = mat.productDate,
  384. box_code = mat.boxCode,
  385. qty = mat.quantity,
  386. tray_no = reqData.TrayNo,
  387. order_code = mat.order_code,
  388. wo_part = mat.matNo,
  389. wo_part_name = mat.matName,
  390. });
  391. var woMat = ctx.Queryable<FX_wo_mstr>().OrderBy(o => o.add_Time).First(c => c.order_code == mat.order_code && c.wo_part == mat.matNo &&
  392. c.wo_status < 2 && c.wo_qty_ord > c.wo_qty_comp && (c.wo_qty_ord - c.wo_qty_comp) > mat.quantity);
  393. if(woMat==null)
  394. throw SysExCore.ThrowFailException($"未匹配到有效验证的工单!");
  395. if ((woMat.wo_qty_comp + mat.quantity) > woMat.wo_qty_ord)
  396. throw SysExCore.ThrowFailException($"绑盘数量不能大于工单{woMat.wo_lot}需求数量!");
  397. woMat.wo_qty_comp += mat.quantity;
  398. ctx.Updateable<FX_wo_mstr>().SetColumns(it => new FX_wo_mstr()
  399. {
  400. wo_qty_comp = woMat.wo_qty_comp
  401. }).Where(it => it.wo_lot == woMat.wo_lot && it.wo_part == woMat.wo_part).ExecuteCommand();
  402. if (ctx.Queryable<FX_wo_mstr>().Any(a => a.wo_qty_comp == a.wo_qty_ord && a.order_code == woMat.order_code && a.wo_lot == woMat.wo_lot && a.wo_part == woMat.wo_part))
  403. {
  404. ctx.Updateable<FX_wo_mstr>().SetColumns(it => new FX_wo_mstr
  405. {
  406. wo_status = 1,
  407. edit_user = LoginUser.UserNo,
  408. edit_Time = DateTime.Now
  409. }).Where(w => w.order_code == woMat.order_code && w.wo_lot == woMat.wo_lot && w.wo_part == woMat.wo_part).ExecuteCommand();
  410. }
  411. });
  412. var retCount = ctx.Insertable(mstr_Infos).ExecuteCommand();
  413. if (retCount < 1)
  414. throw SysExCore.ThrowFailException("提交失败");
  415. ctx.CommitTran();
  416. }
  417. catch (Exception)
  418. {
  419. ctx.RollbackTran();
  420. throw;
  421. }
  422. return SysExCore.GetResSucc("提交成功");
  423. }
  424. }
  425. /// <summary>
  426. /// 根据托盘和箱码获取拣选出库明细
  427. /// </summary>
  428. /// <param name="reqData"></param>
  429. /// <returns></returns>
  430. public ResInfo GetStockOutLineDetail(StockOutScanBoxCodeRequest request)
  431. {
  432. if (string.IsNullOrWhiteSpace(request.BoxCode) || string.IsNullOrWhiteSpace(request.TrayNo))
  433. throw SysExCore.ThrowFailException("托盘码或箱码都不能为空");
  434. var stockOutLines = SysDbCore.GetDbCtx().Queryable<BILL_STOCKOUTLINE, BILL_STOCKOUTLINEDETAIL>((line, detail) => new object[] { JoinType.Inner, line.F_pNo == detail.F_pNo && line.F_matNo == detail.F_matNo })
  435. .Where((line, detail) => detail.F_trayNo == request.TrayNo && detail.F_boxNo == request.BoxCode).Select<BILL_STOCKOUTLINE>().ToList();
  436. return SysExCore.GetResSucc(data: stockOutLines);
  437. }
  438. }
  439. }