| | |
| | | using log4net.Core; |
| | | |
| | | using Mapster; |
| | | using Masuit.Tools; |
| | | using Masuit.Tools.Models; |
| | | using Microsoft.EntityFrameworkCore; |
| | | using System.Linq; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_DTO.MOM; |
| | | using WIDESEA_DTO.WMS; |
| | | using WIDESEA_IStorageBasicRepository; |
| | | using WIDESEA_IServices; |
| | | using WIDESEA_IStoragIntegrationServices; |
| | | using WIDESEA_Model.Models; |
| | | using WIDESEA_StorageBasicRepository; |
| | | using WIDESEA_StorageTaskRepository; |
| | | using WIDESEA_StoragIntegrationServices; |
| | | using WIDESEAWCS_BasicInfoRepository; |
| | | |
| | | namespace WIDESEA_StorageOutTaskServices; |
| | |
| | | { |
| | | private readonly LogFactory LogFactory = new LogFactory(); |
| | | private readonly IUnitOfWorkManage _unitOfWorkManage; |
| | | private readonly IDt_OutOrderRepository _outOrderRepository; |
| | | private readonly IStockInfoRepository _stockInfoRepository; |
| | | private readonly IStockInfoDetailRepository _stockInfoDetailRepository; |
| | | private readonly IDt_Task_HtyRepository _task_HtyRepository; |
| | | private readonly IDt_OutOrderAndStockRepository _outOrderAndStockRepository; |
| | | private readonly IDt_OutOrderAndStock_HtyRepository _outOrderAndStock_HtyRepository; |
| | | private readonly IMapper _mapper; |
| | | private readonly IDt_MaterielInfoRepository _materielInfoRepository; |
| | | private readonly ILocationInfoRepository _locationRepository; |
| | | private readonly IDt_WareAreaInfoRepository _wareAreaInfoRepository; |
| | | private readonly IPointStackerRelationRepository _pointStackerRelationRepository; |
| | | private readonly ITaskExecuteDetailRepository _taskExecuteDetailRepository; |
| | | private readonly ILocationStatusChangeRecordRepository _locationStatusChangeRecordRepository; |
| | | private readonly IBoxingInfoRepository _boxingInfoRepository; //组盘 |
| | |
| | | private readonly IProcessApplyService _processApplyService; //工艺路线 |
| | | private readonly IDt_AreaInfoRepository _areaInfoRepository; //区域 |
| | | private readonly IAgingInOrOutInputService _agingInOrOutInputService; //静置\陈化 |
| | | private readonly IProductionRepository _productionRepository; //生产 |
| | | private readonly IDt_StationManagerRepository _stationManagerRepository; |
| | | private readonly ISys_ConfigService _configService; |
| | | |
| | | public Dt_TaskService(IDt_TaskRepository BaseDal, |
| | | IUnitOfWorkManage unitOfWorkManage, |
| | | IDt_OutOrderRepository outOrderRepository, |
| | | IStockInfoRepository stockInfoRepository, |
| | | IDt_OutOrderAndStockRepository dt_OutOrderAndStockRepository, |
| | | IDt_OutOrderAndStock_HtyRepository dt_OutOrderAndStock_HtyRepository, |
| | | IDt_Task_HtyRepository task_HtyRepository, |
| | | IMapper mapper, |
| | | IDt_MaterielInfoRepository materielInfoRepository, |
| | | ILocationInfoRepository locationRepository, |
| | | IDt_WareAreaInfoRepository wareAreaInfoRepository, |
| | | IPointStackerRelationRepository pointStackerRelationRepository, |
| | | ITaskExecuteDetailRepository taskExecuteDetailRepository, |
| | | ILocationStatusChangeRecordRepository locationStatusChangeRecordRepository, |
| | | IBoxingInfoRepository boxingInfoRepository, |
| | |
| | | IDt_AreaInfoRepository areaInfoRepository, |
| | | IAgingInOrOutInputService agingInOrOutInputService, |
| | | IStockInfoDetailRepository stockInfoDetailRepository, |
| | | IProductionRepository productionRepository, |
| | | IDt_StationManagerRepository stationManagerRepository) : base(BaseDal) |
| | | IDt_StationManagerRepository stationManagerRepository, |
| | | ISys_ConfigService configService) : base(BaseDal) |
| | | { |
| | | _unitOfWorkManage = unitOfWorkManage; |
| | | _outOrderRepository = outOrderRepository; |
| | | _stockInfoRepository = stockInfoRepository; |
| | | _outOrderAndStockRepository = dt_OutOrderAndStockRepository; |
| | | _outOrderAndStock_HtyRepository = dt_OutOrderAndStock_HtyRepository; |
| | | _task_HtyRepository = task_HtyRepository; |
| | | _mapper = mapper; |
| | | _materielInfoRepository = materielInfoRepository; |
| | | _locationRepository = locationRepository; |
| | | _wareAreaInfoRepository = wareAreaInfoRepository; |
| | | _pointStackerRelationRepository = pointStackerRelationRepository; |
| | | _taskExecuteDetailRepository = taskExecuteDetailRepository; |
| | | _locationStatusChangeRecordRepository = locationStatusChangeRecordRepository; |
| | | _boxingInfoRepository = boxingInfoRepository; |
| | |
| | | _areaInfoRepository = areaInfoRepository; |
| | | _agingInOrOutInputService = agingInOrOutInputService; |
| | | _stockInfoDetailRepository = stockInfoDetailRepository; |
| | | _productionRepository = productionRepository; |
| | | _stationManagerRepository = stationManagerRepository; |
| | | _configService = configService; |
| | | } |
| | | |
| | | #region 外部接口方法 |
| | |
| | | { |
| | | var agingOutputDto = MapToAgingOutputDto(stock); |
| | | content = await _agingInOrOutInputService.GetOCVOutputAsync(agingOutputDto); |
| | | ValidateResponse(content); |
| | | //ValidateResponse(content); |
| | | var result = JsonConvert.DeserializeObject<BasicResult>(content.Data.ToString()); |
| | | if (!result.Success) |
| | | { |
| | | task.Remark = "NG"; |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | await UpdateLocationAsync(loc); |
| | | await DeleteStockInfoAsync(stock.Id); |
| | | await DeleteStockInfoDetailsAsync(stock.StockInfoDetails); |
| | | //await DeleteTaskAsync(task.TaskId); |
| | | if (task.Roadway.Contains("FR") || task.Roadway.Contains("GW")) //如果是分容或高温出库 将任务删除 |
| | | await DeleteTaskAsync(task.TaskId); |
| | | }); |
| | | |
| | | return content.OK("任务完成成功"); |
| | | return content.OK("任务完成成功", task.Remark); |
| | | } |
| | | catch (Exception err) |
| | | { |
| | |
| | | var parameterInfo = JsonConvert.DeserializeObject<List<ParameterInfo>>(stock.ParameterInfos).FirstOrDefault(y => y.Description.Contains("时间")); |
| | | if (parameterInfo == null) throw new Exception(""); |
| | | |
| | | var outHours = (DateTime.Now - stock.OutboundTime.Value).TotalHours; |
| | | var outHours = (DateTime.Now - (stock.LinedProcessFeedbackTime == null ? stock.CreateDate : stock.LinedProcessFeedbackTime.ToDateTime())).TotalHours; |
| | | |
| | | //if (stock.LinedProcessFeedbackTime == null) |
| | | //{ |
| | | // outHours = (DateTime.Now - stock.CreateDate).TotalHours; |
| | | //} |
| | | //else |
| | | //{ |
| | | // outHours = (DateTime.Now - stock.LinedProcessFeedbackTime.ToDateTime()).TotalHours; |
| | | //} |
| | | |
| | | var isNG = outHours > parameterInfo.LowerSpecificationsLimit.ToDouble() && outHours < parameterInfo.UpperSpecificationsLimit.ToDouble(); |
| | | |
| | | var defectCode = string.Empty; |
| | | if (!isNG) defectCode = "TQCK"; |
| | | return new AgingOutputDto |
| | | { |
| | | OpFlag = 1, |
| | |
| | | TargetValue = parameterInfo.TargetValue, |
| | | LowerLomit = parameterInfo.LowerSpecificationsLimit, |
| | | UpperLimit = parameterInfo.UpperSpecificationsLimit, |
| | | DefectCode = defectCode |
| | | } |
| | | } |
| | | }).ToList() |
| | |
| | | |
| | | private void ValidateResponse(WebResponseContent content) |
| | | { |
| | | var result = JsonConvert.DeserializeObject<BasicResult>(content.Data.ToString()); |
| | | if (!result.Success) |
| | | { |
| | | throw new Exception(result.MOMMessage); |
| | | } |
| | | |
| | | } |
| | | |
| | | private (DtLocationInfo, Dt_Task) UpdateStockAndTaskStatus(DtStockInfo stock, Dt_Task task) |
| | | { |
| | | var location = _locationRepository.QueryFirst(x => x.LocationCode == task.SourceAddress); |
| | | var location = _locationRepository.QueryFirst(x => x.LocationCode == task.SourceAddress && x.RoadwayNo == task.Roadway); |
| | | //var details = _stockInfoDetailRepository.QueryData(x => x.StockId == stock.Id); |
| | | |
| | | location.LocationStatus = (int)LocationEnum.Free; |
| | |
| | | |
| | | // 获取装箱信息和目标位置信息 |
| | | var boxing = await _boxingInfoRepository.QueryFirstNavAsync(x => x.PalletCode == task.PalletCode); |
| | | var locationInf = await _locationRepository.QueryFirstAsync(x => x.LocationCode == task.TargetAddress); |
| | | var locationInf = await _locationRepository.QueryFirstAsync(x => x.LocationCode == task.TargetAddress && x.RoadwayNo == task.Roadway); |
| | | |
| | | // 更新目标位置状态为库存中 |
| | | locationInf.LocationStatus = (int)LocationEnum.InStock; |
| | |
| | | // 根据是否有组盘信息创建库存实例模型 |
| | | DtStockInfo stock = boxing == null ? CreateEmptyPalletStock(task, locationInf) : CreateFullPalletStock(task, locationInf, boxing); |
| | | |
| | | |
| | | // 执行数据库事务 |
| | | bool isResult = await ExecuteTransaction(stock, taskHty, locationInf, task.TaskId); |
| | | bool isResult = await ExecuteTransaction(stock, taskHty, locationInf, task.TaskId, boxing); |
| | | if (isResult) |
| | | { |
| | | content.OK("入库任务完成成功"); |
| | |
| | | CreateDate = DateTime.Now, |
| | | Creater = "system", |
| | | IsFull = false, |
| | | AreaCode = area.AreaCode, |
| | | AreaCode = area.AreaCode ?? "", |
| | | LocationId = loation.Id, |
| | | StockInfoDetails = new List<DtStockInfoDetail>() |
| | | { |
| | | new DtStockInfoDetail() |
| | | { |
| | | MaterielCode = "空托盘", |
| | | Id = 0, |
| | | Status = (int)StockStateEmun.已入库 |
| | | } |
| | | } |
| | | }; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 创建分容的实托盘的库存实例模型 |
| | | /// </summary> |
| | | private DtStockInfo CreateFullPalletStockByFR(Dt_Task task, DtLocationInfo locationInf) |
| | | { |
| | | var loation = _locationRepository.QueryFirst(x => x.RoadwayNo == task.Roadway && x.LocationCode == task.TargetAddress); |
| | | var area = _areaInfoRepository.QueryFirst(x => x.AreaID == loation.AreaId); |
| | | return new DtStockInfo() |
| | | { |
| | | PalletCode = task.PalletCode, |
| | | LocationCode = task.TargetAddress, |
| | | CreateDate = DateTime.Now, |
| | | Creater = "system", |
| | | IsFull = false, |
| | | AreaCode = area.AreaCode ?? "", |
| | | LocationId = loation.Id, |
| | | StockInfoDetails = new List<DtStockInfoDetail>() |
| | | { |
| | | new DtStockInfoDetail() |
| | | { |
| | | MaterielCode = "实托盘", |
| | | Id = 0, |
| | | Status = (int)StockStateEmun.已入库 |
| | | } |
| | |
| | | stock.LinedProcessFeedbackTime = respone.LinedProcessFeedbackTime; |
| | | stock.SpecialParameterDuration = respone.SpecialParameterDuration; |
| | | //2024年11月16日:新增字段计算应出库时间 |
| | | stock.OutboundTime = Convert.ToDateTime(respone.LinedProcessFeedbackTime).AddHours(Convert.ToDouble(respone.SpecialParameterDuration)); |
| | | stock.OutboundTime = Convert.ToDateTime(respone.LinedProcessFeedbackTime == null ? DateTime.Now : respone.LinedProcessFeedbackTime).AddHours(Convert.ToDouble(respone.SpecialParameterDuration)); |
| | | stock.ProductionLine = respone.ProductionLine; |
| | | stock.ParameterInfos = respone.ParameterInfos.ToJsonString(); |
| | | stock.StockStatus = 1; |
| | |
| | | } |
| | | LogFactory.GetLog("任务完成").InfoFormat(true, "验证任务是否存在", JsonConvert.SerializeObject(task)); |
| | | |
| | | if(task.TaskType == (int)TaskOutboundTypeEnum.InToOut) |
| | | if (task.TaskType == (int)TaskOutboundTypeEnum.InToOut) |
| | | { |
| | | return await CompleteInToOutTaskAsync(task); |
| | | return await CompleteInToOutTaskAsync(task); |
| | | } |
| | | |
| | | // 验证库存是否存在 |
| | |
| | | // TODO 创建任务送至NG排出口 |
| | | var efg = _stationManagerRepository.QueryData(x => x.stationType == 1 && x.stationChildCode == input.Position && x.stationArea == area.AreaCode).ToList(); |
| | | //List<string> NGStation = input.Position == "1088" ? new List<string>() { "1020" } : new List<string>() { "JZSC01" }; |
| | | if(efg.Count <= 0) |
| | | if (efg.Count <= 0) |
| | | { |
| | | throw new Exception("未找到NG入库站台配置"); |
| | | } |
| | |
| | | content = await RequestTrayInTaskAsync(input); |
| | | return content; |
| | | } |
| | | //Console.WriteLine("qqqqq"); |
| | | |
| | | // TODO 获取本地料框属性与整盘电芯属性获取的值进行对比,如果一致则继续,否则返回错误信息 |
| | | //var productions = await _productionRepository.QueryDataAsync(x => result.TrayBarcodePropertys.Select(x => x.TrayBarcodeProperty).ToList().Contains(x.TrayBarcodeProperty)); |
| | |
| | | |
| | | // 调用CreateBoxingInfo方法,创建组盘信息 |
| | | |
| | | var boxing = await CreateBoxingInfo(result, input.PalletCode); |
| | | var boxing = CreateBoxingInfo(result, input.PalletCode); |
| | | //Console.WriteLine(boxing.ToJsonString()); |
| | | if (boxing == null) return content.Error("组盘失败"); |
| | | |
| | | // 调用GetProcessApplyAsync方法,获取工艺路线 |
| | |
| | | |
| | | // 如果状态为false,则返回null |
| | | if (!content.Status) return content.Error("工艺申请失败"); |
| | | var resultProcessApply = JsonConvert.DeserializeObject<ResultProcessApply>(content.Data.ToString()); |
| | | if ((resultProcessApply.Success)) return content.Error("工艺申请失败"); |
| | | |
| | | //// 调用GetProcessResponseAsync方法,获取工艺响应 |
| | | var par = resultProcessApply.ProcessInfo.Where(x => x.ProcessCode == boxing.ProcessCode).FirstOrDefault().Number.ToInt32(); |
| | | |
| | | |
| | | // 调用GetProcessResponseAsync方法,获取工艺响应 |
| | | //var processResponse = await GetProcessResponseAsync(process, input.Position); |
| | | |
| | | //List<string> strings = input.Position == "1088" ? new List<string>() { "CHSC01" } : new List<string>() { "JZSC01" }; |
| | | ////List<string> strings = input.Position == "1088" ? new List<string>() { "CHSC01" } : new List<string>() { "JZSC01" }; |
| | | Console.WriteLine(area.AreaCode+"-----------------------"); |
| | | Console.WriteLine(input.Position + "-----------------------"); |
| | | var stationManagers = _stationManagerRepository.QueryData(x => x.stationType == 1 && x.stationChildCode == input.Position && x.stationArea == area.AreaCode).ToList(); |
| | | if (stationManagers.Count <= 0) |
| | | { |
| | | throw new Exception("未找到NG入库站台配置"); |
| | | } |
| | | List<string> strings = stationManagers.Select(x=>x.Roadway).ToList(); |
| | | // 调用CreateNewTask方法,创建新任务 |
| | | List<string> strings = stationManagers.Select(x => x.Roadway).ToList(); |
| | | //// 调用CreateNewTask方法,创建新任务 |
| | | content = await CreateNewTask(input, strings); |
| | | if (content.Status) |
| | | { |
| | |
| | | } |
| | | |
| | | // 获取组盘信息 |
| | | private async Task<DtBoxingInfo> CreateBoxingInfo(ResultTrayCellsStatus result, string palletCode) |
| | | private DtBoxingInfo CreateBoxingInfo(ResultTrayCellsStatus result, string palletCode) |
| | | { |
| | | return new DtBoxingInfo |
| | | { |
| | | PalletCode = palletCode, |
| | | IsFull = true, |
| | | ProcessCode = result.ProcessCode, |
| | | BoxingInfoDetails = result.SerialNos.Select(serialNoObj => new DtBoxingInfoDetail |
| | | { |
| | | SerialNumber = serialNoObj.SerialNo, |
| | |
| | | if (hasTask != null) |
| | | { |
| | | WMSTaskDTO taskDTO1 = CreateTaskDTO(hasTask); |
| | | return content.OK("已存在空盘出库任务", data: taskDTO1); |
| | | return content.OK("已存在出库任务", data: taskDTO1); |
| | | } |
| | | |
| | | // 创建新任务实例 |
| | |
| | | TaskState = (int)TaskOutStatusEnum.OutNew, |
| | | TaskType = tag == (int)TaskOutboundTypeEnum.Outbound ? (int)TaskOutboundTypeEnum.Outbound : (int)TaskOutboundTypeEnum.OutTray, |
| | | TaskNum = BaseDal.GetTaskNo().Result, |
| | | Creater = "System" // 修正拼写错误 |
| | | Creater = "System", // 修正拼写错误 |
| | | CreateDate = DateTime.Now, |
| | | TaskId = 0, |
| | | }; |
| | | } |
| | | |
| | |
| | | #region private 内部方法 |
| | | |
| | | /// <summary> |
| | | /// 更新出库订单和库存信息 |
| | | /// </summary> |
| | | /// <param name="stock">库存实例</param> |
| | | /// <param name="barCode">条码</param> |
| | | /// <returns>更新后的订单和库存信息</returns> |
| | | private async Task<Dt_OutOrderAndStock> UpdateOrderAndStockAsync(DtStockInfo stock, string barCode) |
| | | { |
| | | //根据PalletCode获取订单和库存信息 |
| | | var orderStock = await _outOrderAndStockRepository.GetOrderAndStock(palletCode: barCode); |
| | | |
| | | //完成数量增加 |
| | | orderStock.CompletedQuantity += stock.StockInfoDetails.Sum(x => x.StockQuantity); |
| | | |
| | | //订单详情完成数量增加 |
| | | orderStock.OrderList.OrderDetailList.CompletedQuantity += stock.StockInfoDetails.Sum(x => x.StockQuantity); |
| | | |
| | | //返回更新后的订单和库存信息 |
| | | return orderStock; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 判断订单是否完成 |
| | | /// </summary> |
| | | /// <param name="orderStock">订单和库存信息</param> |
| | | /// <returns>是否完成</returns> |
| | | // 判断订单是否完成 |
| | | private bool IsOrderComplete(Dt_OutOrderAndStock orderStock) |
| | | { |
| | | // 如果出库数量等于完成出库数量,则订单完成 |
| | | return orderStock.CompletedQuantity == orderStock.OutboundQuantity; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 创建历史任务记录 |
| | | /// </summary> |
| | | /// <param name="task"></param> |
| | |
| | | { |
| | | // 添加库存 |
| | | isUpdateStock = await _stockInfoRepository.AddDataNavAsync(stock); |
| | | isDeleteBoxing = await _boxingInfoRepository.Db.DeleteNav<DtBoxingInfo>(x => x.Id == boxingInfo.Id) |
| | | .Include(x => x.BoxingInfoDetails) |
| | | .ExecuteCommandAsync(); |
| | | if (boxingInfo != null) |
| | | { |
| | | isDeleteBoxing = await _boxingInfoRepository.Db.DeleteNav<DtBoxingInfo>(x => x.Id == boxingInfo.Id) |
| | | .Include(x => x.BoxingInfoDetails) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | // 添加历史任务 |
| | | var isTaskHtyAdd = await _task_HtyRepository.AddDataAsync(taskHty) > 0; |