#region << 版 本 注 释 >> /*---------------------------------------------------------------- * 命名空间:WIDESEA_TaskInfoService * 创建者:胡童庆 * 创建时间:2024/8/2 16:13:36 * 版本:V1.0.0 * 描述: * * ---------------------------------------------------------------- * 修改人: * 修改时间: * 版本:V1.0.1 * 修改说明: * *----------------------------------------------------------------*/ #endregion << 版 本 注 释 >> using AutoMapper; using Microsoft.AspNetCore.Mvc.ApiExplorer; using Newtonsoft.Json; using SqlSugar; using System.Reflection.Emit; using System.Threading.Tasks; using WIDESEA_Common.CommonEnum; using WIDESEA_Common.LocationEnum; using WIDESEA_Common.OrderEnum; using WIDESEA_Common.StockEnum; using WIDESEA_Common.TaskEnum; using WIDESEA_Common.WareHouseEnum; using WIDESEA_Core; using WIDESEA_Core.BaseRepository; using WIDESEA_Core.BaseServices; using WIDESEA_Core.Enums; using WIDESEA_Core.Helper; using WIDESEA_DTO.Inbound; using WIDESEA_DTO.MES; using WIDESEA_DTO.Stock; using WIDESEA_DTO.Task; using WIDESEA_External.ERPService; using WIDESEA_External.Model; using WIDESEA_IBasicRepository; using WIDESEA_IBasicService; using WIDESEA_IInboundRepository; using WIDESEA_IInboundService; using WIDESEA_IOutboundRepository; using WIDESEA_IOutboundService; using WIDESEA_IRecordService; using WIDESEA_IStockRepository; using WIDESEA_IStockService; using WIDESEA_ITaskInfoRepository; using WIDESEA_ITaskInfoService; using WIDESEA_Model.Models; using WIDESEA_TaskInfoRepository; namespace WIDESEA_TaskInfoService { public partial class TaskService : ServiceBase, ITaskService { private readonly IMapper _mapper; private readonly IUnitOfWorkManage _unitOfWorkManage; private readonly IStockRepository _stockRepository; private readonly IBasicService _basicService; private readonly IRecordService _recordService; private readonly IOutboundService _outboundService; private readonly IStockService _stockService; private readonly IBasicRepository _basicRepository; private readonly IApiInfoRepository _apiInfoRepository; private readonly IInvokeERPService _invokeERPService; private readonly IInboundRepository _inboundRepository; private readonly IInboundOrderService _inboundOrderService; private readonly IPalletTypeInfoRepository _palletTypeInfoRepository; public ITaskRepository Repository => BaseDal; private Dictionary _taskOrderBy = new() { {nameof(Dt_Task.Grade),OrderByType.Desc }, {nameof(Dt_Task.CreateDate),OrderByType.Asc}, }; public List TaskTypes => typeof(TaskTypeEnum).GetEnumIndexList(); public List TaskOutboundTypes => typeof(TaskTypeEnum).GetEnumIndexList(); public TaskService(ITaskRepository BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IStockRepository stockRepository, IBasicService basicService, IRecordService recordService, IOutboundService outboundService, IStockService stockService, IBasicRepository basicRepository, IApiInfoRepository apiInfoRepository, IInvokeERPService invokeERPService, IInboundRepository inboundRepository, IInboundOrderService inboundOrderService, IPalletTypeInfoRepository palletTypeInfoRepository) : base(BaseDal) { _mapper = mapper; _unitOfWorkManage = unitOfWorkManage; _stockRepository = stockRepository; _basicService = basicService; _recordService = recordService; _outboundService = outboundService; _stockService = stockService; _basicRepository = basicRepository; _apiInfoRepository = apiInfoRepository; _invokeERPService = invokeERPService; _inboundRepository = inboundRepository; _inboundOrderService = inboundOrderService; _palletTypeInfoRepository = palletTypeInfoRepository; } /// /// 任务信息推送至WCS /// /// public WebResponseContent PushTasksToWCS(List tasks, string agvDescription = "") { try { List taskDTOs = _mapper.Map>(tasks); taskDTOs.ForEach(x => { x.AGVArea = agvDescription; }); string url = AppSettings.Get("WCS"); if (string.IsNullOrEmpty(url)) { return WebResponseContent.Instance.Error($"未找到WCSApi地址,请检查配置文件"); } string response = HttpHelper.Post($"{url}/api/Task/ReceiveTask", taskDTOs.Serialize()); return JsonConvert.DeserializeObject(response) ?? WebResponseContent.Instance.Error("返回错误"); } catch (Exception ex) { return WebResponseContent.Instance.Error(ex.Message); } } /// /// 放货完成 /// /// /// public WebResponseContent PutFinish(string code) { try { string url = AppSettings.Get("WCS"); if (string.IsNullOrEmpty(url)) { return WebResponseContent.Instance.Error($"未找到WCSAApi地址,请检查配置文件"); } string response = HttpHelper.Post($"{url}/api/CTU_AGV/PutFinish?code=" + code); return JsonConvert.DeserializeObject(response) ?? WebResponseContent.Instance.Error("返回错误"); } catch (Exception ex) { return WebResponseContent.Instance.Error(ex.Message); } } public WebResponseContent AGVTasks(SaveModel saveModel) { try { var palletCode = saveModel.MainData["barcode"].ToString(); var stationCode = saveModel.MainData["address"].ToString(); var warehouseId = saveModel.MainData["warehouseId"].ObjToInt(); Dt_Warehouse warehouse = _basicRepository.WarehouseRepository.QueryFirst(x => x.WarehouseId == warehouseId); if (warehouse == null) { return WebResponseContent.Instance.Error("未找到库区"); } Dt_Task task = Repository.QueryFirst(x => x.PalletCode == palletCode && x.WarehouseId == warehouseId); if (task != null) { return WebResponseContent.Instance.Error($"该托盘已生成任务"); } if (Repository.QueryFirst(x => x.SourceAddress == stationCode && x.TaskStatus == TaskStatusEnum.New.ObjToInt()) != null && warehouse.WarehouseCode != WarehouseEnum.HA58.ToString()) { return WebResponseContent.Instance.Error($"该站点已有未执行的任务"); } Dt_StockInfo stockInfo = _stockRepository.StockInfoRepository.Db.Queryable().Where(x => x.PalletCode == palletCode).Includes(x => x.Details).First(); if (stockInfo == null) { return WebResponseContent.Instance.Error($"未找到组盘信息"); } if (stockInfo.StockStatus != StockStatusEmun.出库完成.ObjToInt()) { return WebResponseContent.Instance.Error($"该托盘状态不正确"); } if (warehouseId != stockInfo.WarehouseId) { return WebResponseContent.Instance.Error($"仓库不正确"); } Dt_Task newTask = new Dt_Task() { CurrentAddress = stationCode, Grade = 0, NextAddress ="", PalletCode = palletCode, Roadway = warehouse.Remark,//查询对应线边仓地址巷道号 SourceAddress = stationCode, TargetAddress = "", TaskType = TaskTypeEnum.OutAllocate.ObjToInt(), TaskStatus = TaskStatusEnum.New.ObjToInt(), WarehouseId = stockInfo.WarehouseId, PalletType = stockInfo.PalletType }; _unitOfWorkManage.BeginTran(); BaseDal.AddData(newTask); PushTasksToWCS(new List { newTask}); _unitOfWorkManage.CommitTran(); return WebResponseContent.Instance.OK(); } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error(ex.Message); } } /// /// 入库任务完成 /// /// 任务号 /// public WebResponseContent InboundTaskCompleted(int taskNum) { try { Dt_Task task = BaseDal.QueryFirst(x => x.TaskNum == taskNum); if (task == null) { return WebResponseContent.Instance.Error($"未找到该任务信息"); } Dt_StockInfo stockInfo = _stockRepository.StockInfoRepository.Db.Queryable().Where(x => x.PalletCode == task.PalletCode && x.WarehouseId == task.WarehouseId).Includes(x => x.Details).First(); if (stockInfo == null) { return WebResponseContent.Instance.Error($"未找到托盘对应的组盘信息"); } if (!string.IsNullOrEmpty(stockInfo.LocationCode)) { return WebResponseContent.Instance.Error($"该托盘已绑定货位"); } if (stockInfo.Details.Count == 0 && stockInfo.PalletType != PalletTypeEnum.Empty.ObjToInt()) { return WebResponseContent.Instance.Error($"未找到该托盘库存明细信息"); } #region 空托退库 if (task.TaskType == TaskTypeEnum.MesPalletReturn.ObjToInt()) { _unitOfWorkManage.BeginTran(); BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId > 0 ? OperateTypeEnum.人工完成 : OperateTypeEnum.自动完成); _stockService.StockInfoService.Repository.DeleteAndMoveIntoHty(stockInfo, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成); _stockService.StockInfoDetailService.Repository.DeleteAndMoveIntoHty(stockInfo.Details, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成); _unitOfWorkManage.CommitTran(); return WebResponseContent.Instance.OK(); } #endregion Dt_LocationInfo locationInfo = _basicService.LocationInfoService.Repository.QueryFirst(x => x.LocationCode == task.TargetAddress); if (locationInfo == null) { return WebResponseContent.Instance.Error($"未找到目标货位信息"); } if (locationInfo.LocationStatus == LocationStatusEnum.InStock.ObjToInt()) { return WebResponseContent.Instance.Error($"货位状态不正确"); } LocationStatusEnum lastStatus = (LocationStatusEnum)locationInfo.LocationStatus; locationInfo.LocationStatus = LocationStatusEnum.InStock.ObjToInt(); Dt_Warehouse warehouse = _basicRepository.WarehouseRepository.QueryFirst(x => x.WarehouseId == task.WarehouseId); stockInfo.LocationCode = locationInfo.LocationCode; #region 空箱入库/拣选回库/生产退料 if (task.TaskType == TaskTypeEnum.InEmpty.ObjToInt() || task.TaskType == TaskTypeEnum.InPick.ObjToInt() || (task.TaskType == TaskTypeEnum.ProductionReturn.ObjToInt() && warehouse.WarehouseCode == WarehouseEnum.HA64.ToString())) { stockInfo.StockStatus = StockStatusEmun.入库完成.ObjToInt(); task.TaskStatus = TaskStatusEnum.Finish.ObjToInt(); stockInfo.Details.ForEach(x => { x.Status = StockStatusEmun.入库完成.ObjToInt(); }); _unitOfWorkManage.BeginTran(); BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId > 0 ? OperateTypeEnum.人工完成 : OperateTypeEnum.自动完成); _basicService.LocationInfoService.UpdateLocationStatus(locationInfo, stockInfo.PalletType, LocationStatusEnum.InStock, stockInfo.WarehouseId); _stockRepository.StockInfoRepository.UpdateData(stockInfo); _stockRepository.StockInfoDetailRepository.UpdateData(stockInfo.Details); _recordService.LocationStatusChangeRecordSetvice.AddLocationStatusChangeRecord(locationInfo, lastStatus, LocationStatusEnum.InStock, LocationChangeType.InboundCompleted); _unitOfWorkManage.CommitTran(); return WebResponseContent.Instance.OK(); } #endregion Dt_InboundOrder? inboundOrder = _inboundRepository.InboundOrderRepository.Db.Queryable().Where(x => x.InboundOrderNo == stockInfo.Details.FirstOrDefault().OrderNo).Includes(x => x.Details).First(); Dt_InboundOrderDetail? inboundOrderDetail = null; Dt_ReturnOrder? returnOrder = null; //标准入库流程查找入库单据 if (inboundOrder != null && stockInfo.StockStatus == StockStatusEmun.入库确认.ObjToInt()) { //查询原完成的入库明细数量 int overCount = inboundOrder.Details.Where(x => x.OrderDetailStatus == OrderDetailStatusEnum.Over.ObjToInt()).ToList().Count; inboundOrderDetail = inboundOrder.Details.FirstOrDefault(x => x.RowNo == stockInfo.Details.FirstOrDefault()?.InboundOrderRowNo); foreach (var item in stockInfo.Details) { if (inboundOrderDetail == null) { continue; } inboundOrderDetail.OverInQuantity += item.StockQuantity; if (inboundOrderDetail.OverInQuantity == inboundOrderDetail.OrderQuantity) { inboundOrderDetail.OrderDetailStatus = OrderDetailStatusEnum.Over.ObjToInt(); overCount += 1; } else if (inboundOrderDetail.OrderDetailStatus == OrderDetailStatusEnum.New.ObjToInt()) { inboundOrderDetail.OrderDetailStatus = OrderDetailStatusEnum.Inbounding.ObjToInt(); } } if (inboundOrder.Details.Count == overCount) { inboundOrder.OrderStatus = InOrderStatusEnum.入库完成.ObjToInt(); //判断是否为退料入库单 if (inboundOrder.OrderType == InOrderTypeEnum.Return.ObjToInt()) { returnOrder = _inboundRepository.ReturnOrderRepository.Db.Queryable().Where(x => x.OrderNo == inboundOrder.UpperOrderNo).Includes(x => x.Details).First(); returnOrder.ReturnOrderStatus = ReturnOrderStatusEnum.Returned.ObjToInt(); foreach (var item in inboundOrder.Details) { Dt_ReturnOrderDetail returnOrderDetail = returnOrder.Details?.FirstOrDefault(x => x.MCode == item.MaterielCode); if (returnOrderDetail != null) { returnOrderDetail.OverReturnQty = item.OverInQuantity; returnOrderDetail.OrderDetailStatus = ReturnOrderStatusEnum.Returned.ObjToInt(); } } } } else if (inboundOrder.OrderStatus == InOrderStatusEnum.未开始.ObjToInt()) { inboundOrder.OrderStatus = InOrderStatusEnum.入库中.ObjToInt(); } } if ((stockInfo.StockStatus == StockStatusEmun.入库确认.ObjToInt() || stockInfo.StockStatus == StockStatusEmun.手动组盘入库确认.ObjToInt()) && warehouse.WarehouseCode == WarehouseEnum.HA64.ToString()) { foreach (var model in stockInfo.Details) { TestSynStock(new TestToolSynInfo() { ToolCode = model.BatchNo, MaterialName = model.MaterielName, Life = int.TryParse(model.Remark, out int val) ? val : 1000 }); } } //测试架入库库存状态 if (task.TaskType == TaskTypeEnum.Inbound.ObjToInt() && warehouse.WarehouseCode == WarehouseEnum.HA64.ToString() && stockInfo.StockStatus != StockStatusEmun.手动组盘入库确认.ObjToInt()) { stockInfo.StockStatus = StockStatusEmun.入库完成未建出库单.ObjToInt(); } else { stockInfo.StockStatus = StockStatusEmun.入库完成.ObjToInt(); } stockInfo.Details.ForEach(x => { x.Status = StockStatusEmun.入库完成.ObjToInt(); }); //更新任务状态 task.TaskStatus = TaskStatusEnum.Finish.ObjToInt(); _unitOfWorkManage.BeginTran(); BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId > 0 ? OperateTypeEnum.人工完成 : OperateTypeEnum.自动完成); _basicService.LocationInfoService.UpdateLocationStatus(locationInfo, stockInfo.PalletType, LocationStatusEnum.InStock, stockInfo.WarehouseId); _stockRepository.StockInfoRepository.UpdateData(stockInfo); _stockRepository.StockInfoDetailRepository.UpdateData(stockInfo.Details); _recordService.LocationStatusChangeRecordSetvice.AddLocationStatusChangeRecord(locationInfo, lastStatus, LocationStatusEnum.InStock, LocationChangeType.InboundCompleted); _recordService.StockQuantityChangeRecordService.AddStockChangeRecord(stockInfo, stockInfo.Details, stockInfo.Details.Sum(x => x.StockQuantity), stockInfo.Details.Sum(x => x.StockQuantity), StockChangeTypeEnum.Inbound, taskNum); if (inboundOrder != null) { _inboundRepository.InboundOrderRepository.UpdateData(inboundOrder); _inboundRepository.InboundOrderDetailRepository.UpdateData(inboundOrderDetail); } if (returnOrder != null) { _inboundRepository.ReturnOrderRepository.UpdateData(returnOrder); _inboundRepository.ReturnOrderDetailRepository.UpdateData(returnOrder.Details); } _unitOfWorkManage.CommitTran(); //存在入库单并状态为完成状态推送至ERP if (inboundOrder != null && inboundOrder.OrderStatus == InOrderStatusEnum.入库完成.ObjToInt() && inboundOrder.OrderType != InOrderTypeEnum.Allocat.ObjToInt()) { if (inboundOrder.OrderType == InOrderTypeEnum.Return.ObjToInt()) { _inboundOrderService.FeedbackReturnOrder(inboundOrder, returnOrder); } else { _inboundOrderService.FeedbackInboundOrder(inboundOrder); } } return WebResponseContent.Instance.OK(); } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error(ex.Message); } } /// /// 出库任务完成 /// /// 任务号 /// public WebResponseContent OutboundTaskCompleted(int taskNum) { try { Dt_Task task = BaseDal.QueryFirst(x => x.TaskNum == taskNum); if (task == null) { return WebResponseContent.Instance.Error($"未找到任务信息"); } Dt_StockInfo stockInfo = _stockService.StockInfoService.Repository.GetStockInfo(task.PalletCode); Dt_LocationInfo locationInfo = _basicService.LocationInfoService.Repository.QueryFirst(x => x.LocationCode == task.SourceAddress); if (stockInfo == null) { return WebResponseContent.Instance.Error($"未找到库存信息"); } if (locationInfo == null) { return WebResponseContent.Instance.Error($"未找到货位信息"); } Dt_Warehouse warehouse = _basicRepository.WarehouseRepository.QueryFirst(x => x.WarehouseId == task.WarehouseId); List outStockLockInfos = _outboundService.OutboundStockLockInfoService.Repository.QueryData(x => x.TaskNum == taskNum); List outboundOrderDetails = new List(); List mesOutboundOrders = new List(); if ((outStockLockInfos == null || outStockLockInfos.Count == 0) && warehouse.WarehouseCode != WarehouseEnum.HA64.ToString() && (task.TaskType != TaskTypeEnum.OutEmpty.ObjToInt())) { return WebResponseContent.Instance.Error($"未找到出库详情信息"); } else { foreach (var item in outStockLockInfos) { if (task.TaskType == TaskTypeEnum.MesOutbound.ObjToInt()) { Dt_MesOutboundOrder mesOutboundOrder = _outboundService.MesOutboundOrderService.Repository.QueryFirst(x => x.TaskNo == item.OrderNo); if (mesOutboundOrder != null) { mesOutboundOrder.OverOutQuantity = item.AssignQuantity; if (mesOutboundOrder.OverOutQuantity == mesOutboundOrder.OrderQuantity) { mesOutboundOrder.OrderStatus = OrderDetailStatusEnum.Over.ObjToInt(); } mesOutboundOrders.Add(mesOutboundOrder); } } else { Dt_OutboundOrderDetail outboundOrderDetail = _outboundService.OutboundOrderDetailService.Repository.QueryFirst(x => x.Id == item.OrderDetailId); if (outboundOrderDetail != null) { outboundOrderDetail.OverOutQuantity += item.AssignQuantity; if (outboundOrderDetail.OverOutQuantity == outboundOrderDetail.OrderQuantity) { outboundOrderDetail.OrderDetailStatus = OrderDetailStatusEnum.Over.ObjToInt(); } outboundOrderDetails.Add(outboundOrderDetail); } } item.Status = OutLockStockStatusEnum.出库完成.ObjToInt(); } } task.TaskStatus = TaskStatusEnum.Finish.ObjToInt(); _unitOfWorkManage.BeginTran(); if (task.TaskType == TaskTypeEnum.Outbound.ObjToInt() || task.TaskType == TaskTypeEnum.OutAllocate.ObjToInt() || task.TaskType == TaskTypeEnum.MesHandPickOutbound.ObjToInt() || task.TaskType == TaskTypeEnum.MesHandOutbound.ObjToInt()) { //处理出库详情 if (outboundOrderDetails.Count > 0) { _outboundService.OutboundOrderDetailService.Repository.UpdateData(outboundOrderDetails); } stockInfo.LocationCode = ""; stockInfo.StockStatus = StockStatusEmun.出库完成.ObjToInt(); _stockService.StockInfoService.Repository.UpdateData(stockInfo); } else if (task.TaskType == TaskTypeEnum.OutEmpty.ObjToInt()) { _basicService.LocationInfoService.UpdateLocationStatus(locationInfo, stockInfo.PalletType, LocationStatusEnum.Free, stockInfo.WarehouseId); _stockService.StockInfoService.Repository.DeleteAndMoveIntoHty(stockInfo, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成); } else if (task.TaskType == TaskTypeEnum.MesOutbound.ObjToInt()) { _outboundService.MesOutboundOrderService.Repository.UpdateData(mesOutboundOrders); _stockService.StockInfoService.Repository.DeleteAndMoveIntoHty(stockInfo, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成); _stockService.StockInfoDetailService.Repository.DeleteAndMoveIntoHty(stockInfo.Details, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成); } _outboundService.OutboundStockLockInfoService.Repository.UpdateData(outStockLockInfos); int beforeStatus = locationInfo.LocationStatus; locationInfo.LocationStatus = LocationStatusEnum.Free.ObjToInt(); _basicService.LocationInfoService.UpdateLocationStatus(locationInfo, stockInfo.PalletType, LocationStatusEnum.Free, stockInfo.WarehouseId); BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成); _recordService.LocationStatusChangeRecordSetvice.AddLocationStatusChangeRecord(locationInfo, (LocationStatusEnum)beforeStatus, LocationStatusEnum.Free, LocationChangeType.OutboundCompleted, stockInfo.Details.FirstOrDefault()?.OrderNo ?? "", task.TaskNum); _unitOfWorkManage.CommitTran(); if (warehouse.WarehouseCode != WarehouseEnum.HA64.ToString() && task.TaskType == TaskTypeEnum.Outbound.ObjToInt()) { _outboundService.OutboundOrderService.TestOutUpload(outboundOrderDetails.FirstOrDefault().OrderId, outStockLockInfos); } if (task.TaskType == TaskTypeEnum.MesOutbound.ObjToInt()) { MesMaterialLotaAceptModel model = GetMesMaterialLotaAceptModel(stockInfo, stockInfo.Details.FirstOrDefault(), mesOutboundOrders.FirstOrDefault().TaskNo, warehouse.WarehouseCode, stockInfo.Details.Where(x => x.MaterielCode == mesOutboundOrders.FirstOrDefault().MaterialCode).Sum(x => x.StockQuantity)); UploadMesMaterialLotaAcept(model); } return WebResponseContent.Instance.OK(); } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error(ex.Message); } } } }