using Rhea.Common; using Microsoft.AspNetCore.Http; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading; using System.Threading.Tasks; using Tiger.Model; using Tiger.Model.Sharetronic.Shelf; using Tiger.Business.WMS.Sharetronic.Shelf; using Tiger.IBusiness; namespace Tiger.Business.WMS.Transaction { /// /// 盘点调度事务 /// public class WmsCount : WMSTransactionBase, IWmsCount { public IWmsCount Init(string id, string userCode, string apiHost, string orgCode) { TransID = id; UserCode = userCode; ApiHost = apiHost; OrgCode = orgCode; Logger.Console.Info($"Start {this.GetType().Name} Transaction[ID: {TransID}]"); return this; } #region Propertys & Variables public string UserCode { get; set; } public long UserId { get; set; } public string OrgCode { get; set; } public Inventory CurInv { get; set; } public WMS_COUNT count { get; set; } public List Shelfs { get; set; } public List locations { get; set; } public List mdtls { get; set; } public List ldtls { get; set; } public List sumlist { get; set; } #endregion #region Functions /// /// 盘点单列表 /// /// /// /// /// /// public ApiAction> GetCountHeaders(int pageIndex, int pageSize, string orgcode, string billcode) { var action = new ApiAction>(); try { var query = Biz.Db.Queryable().Where(x => (x.STATUS < WMS_COUNT.STATUSs.Paused.GetValue()) && x.AUTH_ORG == orgcode) .WhereIF(!billcode.IsNullOrEmpty(), x => x.COUNT_NO.Contains(billcode)) .OrderByDescending(x => x.UPDATE_TIME) .OrderBy(x => x.CREATE_TIME) .ToPage(pageIndex, pageSize); action.Data = query; } catch (Exception ex) { action.CatchExceptionWithLog(ex, $"盘点单获取列表异常"); } return action; } /// /// 盘点单选择事件 /// /// /// public async Task> SelectOrder(CountEntity input) { var action = new ApiAction(); try { count = await Biz.Db.Queryable().ByAuth(input.AuthOption).Where(x => x.COUNT_NO == input.CountNo) .Includes(q => q.MDtlsWithGhost, d => d.Warehouse) .Includes(q => q.MDtlsWithGhost, d => d.Region) .Includes(q => q.MDtlsWithGhost, d => d.Shelf) .Includes(q => q.MDtlsWithGhost, d => d.Location) .IncludesAllFirstLayer().FirstAsync(); mdtls = count.MDtls; ldtls = count.LDtls; sumlist = count.SumList; locations = count.MDtls.Where(x => x.STATUS == WMS_COUNT_MDTL.STATUSs.WaitCount.GetValue()).Select(x => x.Location).Distinct().ToList(); Shelfs = count.MDtls.Where(q => q.SHELF_ID != null && q.STATUS==0).Select(x => x.Shelf).Distinct().ToList(); action.Data = new CountEntityReturn() { CountNo = input.CountNo, Shelfs = Shelfs.Select(q => new ShelfDropDown { SHELF_CODE = q.SHELF_CODE, SHELF_NAME = q.SHELF_NAME }).ToList(), Warehouse = count.MDtls.Select(x => x.Warehouse).First(), COUNT_TYPE = count.COUNT_TYPE }; action.LocaleMsg = Biz.L($"选择盘点单[{input.CountNo}]成功"); //action = await LightAll(new() { AuthOption = input.AuthOption, ReqType = CurReqType, Color = LedColor.Blue }); } catch (Exception ex) { action.CatchExceptionWithLog(ex, $"盘点单选择异常"); } return action; } /// /// 盘点单推荐所有物料亮灯 /// /// /// public async Task> LightAll(CountLightEntity light) { var action = new ApiAction(); try { var _shelf = Shelfs.Where(q => q.SHELF_CODE == light.ShelfCode).FirstOrDefault(); var list = locations.Where(q => q.SHELF_ID == _shelf.ID).ToList(); if (list.Any()) { await Share.Shelf.LightMulti(TransID, light.Color, list); action.Data = new CountOutput() { CountNo = count.COUNT_NO, }; Logger.Interface.Info($"亮灯成功,亮灯颜色[{light.Color.GetDesc()}],亮灯位置[{string.Join(",", list.Select(t => t.LOCATION_CODE))}]"); action.LocaleMsg = Biz.L("亮灯成功,亮灯颜色[{0}]", light.Color.GetDesc()); } else { action.LocaleMsg = Biz.L($"无需亮灯,盘点的物料不在智能货架上"); } } catch (Exception ex) { action.CatchExceptionWithLog(ex, $"亮灯异常"); } return action; } /// /// 盘点单明细 /// /// public async Task>> CountSumDtl(BasePageInput input) { var action = new ApiAction>(); try { var query = Biz.Db.Queryable().ByAuth(input.AuthOption) .WhereIF(!input.Code.IsNullOrEmpty(), x => x.ITEM_CODE.Contains(input.Code)) .Where(t => t.COUNT_NO == count.COUNT_NO) .OrderByDescending(x => x.UPDATE_TIME.ToString("yyyy-MM-dd")) .OrderBy(x => x.CREATE_TIME) .ToPage(input.pageIndex, input.pageSize); action.Data = await Task.FromResult(query); } catch (Exception ex) { action.CatchExceptionWithLog(ex, $"获取盘点单明细异常"); } return action; } ///// ///// 发料明细提示信息 ///// ///// //public async Task GetItemTips(string itemcode) //{ // var action = new ApiAction(); // try // { // action.Data = $"物料{itemcode}:已下架[{(double)req.Dtls.Where(x => x.ITEM_CODE == itemcode).Sum(x => x.OUTQTY)}],共{(double)req.Dtls.Where(x => x.ITEM_CODE == itemcode).Sum(x => x.PRQTY)} {Suggests.FirstOrDefault()?.Item?.UNIT}"; // } // catch (Exception ex) // { // action.CatchExceptionWithLog(ex, $"获取发料明细提示信息异常"); // } // return action; //} /// /// 扫描物料调度下架 /// /// /// public async Task> ScanItem(BaseInput input) { var action = new ApiAction(); try { if (input.SN.IsNullOrEmpty()) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("条码不能为空"); return action; } //解析条码 Result result = WMS_ITEM_Biz.WmsItem.Get(input.SN, input.AuthOption, true); if (!result.IsSuccessed) { action.IsSuccessed = false; action.LocaleMsg = result.LocaleMsg; return action; } CurInv = result.Data; //验证条码是否正确 if (!CurInv.isNormalStatus || CurInv.Status != WMS_ITEM.STATUSs.InStore) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.WmsCount.ScanItem.StatusException", string.Join(',', CurInv.StatusList.Select(x => x.GetDesc()))); return action; } //储位验证 if (CurInv.Location.IsNullOrEmpty()) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.WmsCount.ScanItem.LocationIsNull", CurInv.CurPkg.SN, CurInv.CurPkg.LOCATION_ID); return action; } //物料验证 if (CurInv.ItemInfo.IsNullOrEmpty() || !mdtls.Where(t => t.ITEM_CODE == CurInv.ItemInfo?.ITEM_CODE).Any()) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.WmsCount.ScanItem.NotFound", CurInv.ItemInfo.ITEM_CODE.IsNullOrEmpty(CurInv.Barcode.ItemCode)); return action; } //var aa = mdtls.Where(t => t.SN == CurInv.CurPkg.SN).First(); //V076420231110000003 //更新条码盘点明细状态 var mItem = mdtls.Where(q=> CurInv.Items.Any(a=>q.SN==a.SN)).ToList() ?? new List() { new() { COUNT_NO = count.COUNT_NO, SN = CurInv.SN, QTY = CurInv.CurPkg.QTY, ITEM_CODE = CurInv.ItemInfo.ITEM_CODE, UNIT = CurInv.ItemInfo.UNIT, PROD_DATE = CurInv.Items[0].PROD_DATE, FIRST_IN_DATE = CurInv.Items[0].FIRST_IN_DATE, SUPP_CODE = CurInv.CurPkg.SUPP_CODE, SUPP_LOTNO = CurInv.CurPkg.SUPP_LOTNO, WH_ID = CurInv.CurPkg.WH_ID, REGION_ID = CurInv.CurPkg.REGION_ID, SHELF_ID = CurInv.CurPkg.SHELF_ID, LOCATION_ID = CurInv.CurPkg.LOCATION_ID, ERP_WH = CurInv.CurPkg.ERP_WH, RESULT = WMS_COUNT_MDTL.RESULTs.NewFound.GetValue(), } }; //如果是新发现的条码就添加到列表中 foreach (var item in mItem) { if (item.RESULT == WMS_COUNT_MDTL.RESULTs.NewFound.GetValue()) { mdtls.Add(item); } if (item.STATUS == WMS_COUNT_MDTL.STATUSs.Counted.GetValue()) { //灭灯 var _action = await DownLight(input); if (!_action.IsSuccessed) { return _action; } action.IsSuccessed = false; action.LocaleMsg = Biz.L($"该条码已经盘点过,请扫描其他未盘点的条码!"); return action; } item.ACTION = WMS_COUNT_MDTL.ACTIONs.NoAdjust.GetValue(); item.STATUS = WMS_COUNT_MDTL.STATUSs.Counted.GetValue(); item.REVIEWER = UserCode; item.REVIEW_DATE = DateTime.Now; item.ACT_QTY = CurInv.CurPkg.QTY; item.RESULT = item.RESULT == WMS_COUNT_MDTL.RESULTs.NewFound.GetValue() ? WMS_COUNT_MDTL.RESULTs.NewFound.GetValue() : WMS_COUNT_MDTL.RESULTs.Founded.GetValue(); //var lItem = ldtls.Where(t => t.LOCATION_ID == CurInv.CurPkg.LOCATION_ID).FirstOrDefault(); ////如果是新发现的条码,其原储位又没有在盘点储位列表中 //bool isNewFound = false; //if (lItem == null && item.RESULT == WMS_COUNT_MDTL.RESULTs.NewFound.GetValue()) //{ // lItem = new() // { // COUNT_NO = count.COUNT_NO, // ITEM_CODE = CurInv.ItemInfo.ITEM_CODE, // UNIT = CurInv.ItemInfo.UNIT, // WH_ID = CurInv.CurPkg.WH_ID, // REGION_ID = CurInv.CurPkg.REGION_ID, // SHELF_ID = CurInv.CurPkg.SHELF_ID, // LOCATION_ID = CurInv.CurPkg.LOCATION_ID, // ERP_WH = CurInv.CurPkg.ERP_WH, // QTY = CurInv.CurPkg.QTY, // SN_QTY = 1, // ACT_SN_QTY = 1, // ACT_QTY = CurInv.CurPkg.QTY, // STATUS = WMS_COUNT_LDTL.STATUSs.Counted.GetValue(), // RESULT = lItem.QTY == lItem.ACT_QTY ? WMS_COUNT_LDTL.RESULTs.Balance.GetValue() : (lItem.QTY > lItem.ACT_QTY ? WMS_COUNT_LDTL.RESULTs.Losses.GetValue() : WMS_COUNT_LDTL.RESULTs.Profit.GetValue()) // }; // isNewFound = true; //} var sumItem = sumlist.Where(t => t.ITEM_CODE == CurInv.ItemInfo.ITEM_CODE).FirstOrDefault(); count.STATUS = count.STATUS == WMS_COUNT.STATUSs.New.GetValue() ? WMS_COUNT.STATUSs.Counting.GetValue() : count.STATUS; //如果扫描列表状态都是已盘点,则结束并更新盘点单状态 if (mdtls.Count == mdtls.Where(t => t.STATUS == WMS_COUNT_MDTL.STATUSs.Counted.GetValue()).Count()) { count.STATUS = WMS_COUNT.STATUSs.Closed.GetValue(); } locations = mdtls.Where(x => x.STATUS == WMS_COUNT_MDTL.STATUSs.WaitCount.GetValue()).Select(x => x.Location).Distinct().ToList(); //灭灯 var Action = await DownLight(input); if (!Action.IsSuccessed) { item.STATUS = WMS_COUNT_MDTL.STATUSs.WaitCount.GetValue(); return Action; } //保存数据库 var db = Business.Biz.Db; var dbTran = db.UseTran(() => { db.Storageable(mItem, UserCode).ExecuteCommand(); //if (isNewFound) //{ // ldtls.Add(lItem); // db.Insertable(lItem, UserCode).ExecuteCommand(); //} //else //{ // db.Updateable().SetColumns(t => new WMS_COUNT_LDTL // { // STATUS = WMS_COUNT_LDTL.STATUSs.Counted.GetValue(), // ACT_QTY = t.ACT_QTY + CurInv.CurPkg.QTY, // ACT_SN_QTY = t.ACT_SN_QTY + 1, // UPDATE_USER = UserCode, // UPDATE_TIME = DateTime.Now, // RESULT = Convert.ToInt32(SqlFunc.IF(t.QTY == t.ACT_QTY + CurInv.CurPkg.QTY).Return(WMS_COUNT_LDTL.RESULTs.Balance.GetValue()).ElseIF(t.QTY > t.ACT_QTY + CurInv.CurPkg.QTY).Return(WMS_COUNT_LDTL.RESULTs.Losses.GetValue()).End(WMS_COUNT_LDTL.RESULTs.Profit.GetValue())) // }).Where(q => q.ID == lItem.ID).ExecuteCommand(); //} if (sumItem != null) { db.Updateable().SetColumns(t => new WMS_COUNT_SUM { ACT_QTY = t.ACT_QTY + CurInv.CurPkg.QTY, ACT_SN_QTY = t.ACT_SN_QTY + 1, UPDATE_USER = UserCode, UPDATE_TIME = DateTime.Now, RESULT = Convert.ToInt32(SqlFunc.IF(t.QTY == t.ACT_QTY + CurInv.CurPkg.QTY).Return(WMS_COUNT_SUM.RESULTs.Balance.GetValue()).ElseIF(t.QTY > t.ACT_QTY + CurInv.CurPkg.QTY).Return(WMS_COUNT_SUM.RESULTs.Losses.GetValue()).End(WMS_COUNT_SUM.RESULTs.Profit.GetValue())) }).Where(q => q.ID == sumItem.ID).ExecuteCommand(); } db.Updateable(count, UserCode).UpdateColumns(t => new { t.UPDATE_TIME, t.UPDATE_USER, t.STATUS }).ExecuteCommand(); }); if (!dbTran.IsSuccess) { Logger.Default.Fatal(dbTran.ErrorException, "Database transaction save exception"); this.Close(!dbTran.IsSuccess); throw dbTran.ErrorException; } } if (count.STATUS == WMS_COUNT.STATUSs.Closed.GetValue()) { CloseLight(new CountLightEntity() { ShelfCode = "" }); } action.LocaleMsg = Biz.L($"条码[{CurInv.CurPkg.SN}]核实成功,单号:[{count.COUNT_NO}],状态:{count.STATUS.GetEnumDesc()}"); //var shelfs = Biz.Db.Queryable().Where(q =>q.COUNT_NO==count.COUNT_NO && q.SHELF_ID != null && q.STATUS == 0).Select(x => x.Shelf).Distinct().ToList(); var shelfs = mdtls.Where(q => q.SHELF_ID != null && q.STATUS == 0).Select(x => x.Shelf).Distinct().ToList(); action.Data = new CountOutput() { SN = CurInv.CurPkg.SN, ItemCode = CurInv.ItemInfo.ITEM_CODE, ItemName = CurInv.ItemInfo.ITEM_VER, ItemDesc = CurInv.ItemInfo.ITEM_NAME, Qty = CurInv.CurPkg.QTY, regionCode = CurInv.Region.REGION_CODE, locationCode = CurInv.Location?.LOCATION_CODE, Unit = CurInv.CurPkg.UNIT, Shelfs= shelfs.Select(q => new ShelfDropDown { SHELF_CODE = q.SHELF_CODE, SHELF_NAME = q.SHELF_NAME }).ToList(), Status = $"已盘点数:[{mdtls.Where(t => t.STATUS == WMS_COUNT_MDTL.STATUSs.Counted.GetValue()).Count()}]/总数:[{mdtls.Count}]" }; } catch (Exception ex) { action.CatchExceptionWithLog(ex, $"扫描物料[{input.SN}]复核异常"); } return action; } /// /// 选普通货架带出储位 /// /// /// public async Task> ChangeShelf(BaseInput input) { var action = new ApiAction(); try { //检查是否是智能货架 var whUnit = await Biz.Db.Queryable().Where(t => t.SHELF_CODE.ToUpper() == input.SN.ToUpper() && t.AUTH_ORG == OrgCode).IncludesAllFirstLayer().FirstAsync(); if (whUnit != null && whUnit.SHELF_TYPE == WMS_SHELF.SHELF_TYPEs.Smart.GetValue()) { var shelfs = mdtls.Where(q => q.SHELF_ID != null && q.STATUS == 0).Select(x => x.Shelf).Distinct().ToList(); action.Data = new CountOutput() { locationCode = "", Shelfs = shelfs.Select(q => new ShelfDropDown { SHELF_CODE = q.SHELF_CODE, SHELF_NAME = q.SHELF_NAME }).ToList(), }; } else { //查询出所有储位 var locations = mdtls.Where(q=>q.Shelf.SHELF_CODE==input.SN && q.STATUS==0).Select(q=>q.Location.LOCATION_CODE).Distinct().ToList(); string joined = String.Join(",", locations); var shelfs = mdtls.Where(q => q.SHELF_ID != null && q.STATUS == 0).Select(x => x.Shelf).Distinct().ToList(); action.Data = new CountOutput() { locationCode = joined, Shelfs = shelfs.Select(q => new ShelfDropDown { SHELF_CODE = q.SHELF_CODE, SHELF_NAME = q.SHELF_NAME }).ToList(), }; } } catch (Exception ex) { action.CatchExceptionWithLog(ex, $"选择货架[{input.SN}]复核异常"); } return action; } /// /// 灭灯 /// /// /// private async Task> DownLight(BaseInput input) { var action = new ApiAction(); try { if (CurInv.Shelf.SHELF_TYPE == WMS_SHELF.SHELF_TYPEs.Smart.GetValue()) { ShelfApiResult shelfApiResult = await Share.Shelf.PutOn(TransID, CurInv.Shelf, CurInv.Items[0]); if (!shelfApiResult.IsSuccess) { action.IsSuccessed = false; action.LocaleMsg = Biz.L(shelfApiResult.GetData()); return action; } var reaultShelf = shelfApiResult.GetData(); var nLocation = reaultShelf.GetLocation(); if (nLocation == null) { action.IsSuccessed = false; action.LocaleMsg = Biz.L($"系统不存在储位,请先维护货架信息"); return action; } if (nLocation.LOCATION_CODE != CurInv.Location.LOCATION_CODE) { action.IsSuccessed = false; action.LocaleMsg = Biz.L($"货架返回的储位跟条码所在的储位不一样"); return action; } } //灭灯 if (CurInv.Shelf.SHELF_TYPE == WMS_SHELF.SHELF_TYPEs.Smart.GetValue() || CurInv.Shelf.SHELF_TYPE == WMS_SHELF.SHELF_TYPEs.QRCode.GetValue()) { await Share.Shelf.DownSingle(TransID, CurInv.Location); } } catch (Exception ex) { action.CatchExceptionWithLog(ex, $"扫描物料[{input.SN}]复核异常"); } return action; } /// /// 灭灯 /// /// public async Task CloseLight(CountLightEntity light) { var action = new ApiAction(); try { var _shelf = Shelfs.Where(q => q.SHELF_CODE == light.ShelfCode).FirstOrDefault(); var list = light.ShelfCode.IsNullOrEmpty() ? mdtls.Select(x => x.Location).Distinct().ToList() : locations.Where(q => q.SHELF_ID == _shelf.ID).ToList(); if (list.Any()) { //灭灯 await Share.Shelf.DownMulti(TransID, list); action.Data = new CountOutput() { CountNo = count.COUNT_NO, }; action.LocaleMsg = Biz.L("灭灯成功"); } else { action.LocaleMsg = Biz.L($"无需灭灯"); } } catch (Exception ex) { action.CatchExceptionWithLog(ex, $"灭灯异常"); } return action; } /// /// 添加一个ApiAction的历史记录 /// /// public override void AddHistory(Microsoft.AspNetCore.Http.HttpRequest request, ApiAction action) { var his = action.History(); his.TraceDic.Add("mdtls", mdtls); his.TraceDic.Add("ldtls", ldtls); his.TraceDic.Add("count", count); his.TraceDic.Add("sumlist", sumlist); ActionHistoryList.Add($"{request.HttpContext.TraceIdentifier} at {action.Timestamp:yyyy/MM/dd HH:mm:ss.fff}: {request.Path}", his); LastActionTime = DateTime.Now; } #endregion /// /// 关闭 /// /// /// public override bool Close(bool needSaveHistoryLog = false) { //检查盘点单是否关闭 Biz.Db.Ado.UseStoredProcedure().ExecuteCommand("pkg_count_status", new SugarParameter("CountNo", count.COUNT_NO)); //needSaveHistoryLog = true; CloseLight(new CountLightEntity() { ShelfCode = "" }).Wait(); //保存操作日志 this.IsFinished = true; return IsFinished ? base.Close(needSaveHistoryLog) : IsFinished; } }//endClass }