| using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime; | 
| using System; | 
| using System.Collections.Generic; | 
| using System.Linq; | 
| using System.Text; | 
| using System.Threading.Tasks; | 
| using WIDESEA_Common.LocationEnum; | 
| using WIDESEA_Common.OrderEnum; | 
| using WIDESEA_Common.StockEnum; | 
| using WIDESEA_Common.WareHouseEnum; | 
| using WIDESEA_Core; | 
| using WIDESEA_Core.BaseRepository; | 
| using WIDESEA_Core.BaseServices; | 
| using WIDESEA_Core.Helper; | 
| using WIDESEA_DTO.ERP; | 
| using WIDESEA_External.ERPService; | 
| using WIDESEA_External.Model; | 
| using WIDESEA_IBasicService; | 
| using WIDESEA_IOutboundRepository; | 
| using WIDESEA_IOutboundService; | 
| using WIDESEA_IRecordService; | 
| using WIDESEA_IStockRepository; | 
| using WIDESEA_IStockService; | 
| using WIDESEA_Model.Models; | 
| using WIDESEA_OutboundRepository; | 
|   | 
| namespace WIDESEA_OutboundService | 
| { | 
|     public partial class ErpProScrapSheetDetailService : ServiceBase<Dt_ErpProScrapSheetDetail, IErpProScrapSheetDetailRepository>, IErpProScrapSheetDetailService | 
|     { | 
|         private readonly IUnitOfWorkManage _unitOfWorkManage; | 
|         public IErpProScrapSheetDetailRepository Repository => BaseDal; | 
|         public IErpProScrapSheetRepository _proScrapSheetRepository; | 
|         public IInvokeERPService _invokeERPService; | 
|         public IStockRepository _stockRepository; | 
|         public IStockService _stockService; | 
|         public IOutProStockInfoService _outProStockInfoService; | 
|         public IBasicService _basicService; | 
|         public IRecordService _recordService; | 
|   | 
|         public ErpProScrapSheetDetailService(IErpProScrapSheetDetailRepository BaseDal, IUnitOfWorkManage unitOfWorkManage, IErpProScrapSheetRepository proScrapSheetRepository, IInvokeERPService invokeERPService, IStockRepository stockRepository, IStockService stockService, IOutProStockInfoService outProStockInfoService, IRecordService recordService, IBasicService basicService) : base(BaseDal) | 
|         { | 
|             _unitOfWorkManage = unitOfWorkManage; | 
|             _proScrapSheetRepository = proScrapSheetRepository; | 
|             _invokeERPService = invokeERPService; | 
|             _stockRepository = stockRepository; | 
|             _stockService = stockService; | 
|             _outProStockInfoService = outProStockInfoService; | 
|             _recordService = recordService; | 
|             _basicService = basicService; | 
|         } | 
|         //获取对应单号的报废明细 | 
|         public List<Dt_ErpProScrapSheetDetail> GetByDetails(string scrapNo) | 
|         { | 
|             List<Dt_ErpProScrapSheetDetail> proScrapSheetDetails = _proScrapSheetRepository.Db.Queryable<Dt_ErpProScrapSheet, Dt_ErpProScrapSheetDetail>((master, detail) => master.Id == detail.ProScrapSheetId) | 
|                 .Where((master, detail) => master.ProScrapSheetOrderNo==scrapNo) | 
|                 .Select((master, detail) => detail) | 
|                 .ToList(); | 
|             return proScrapSheetDetails; | 
|         } | 
|         /// <summary> | 
|         /// 提交报废操作 | 
|         /// </summary> | 
|         /// <returns></returns> | 
|         public WebResponseContent UpProScrap(string scrapNo,int[] keys) | 
|         { | 
|             WebResponseContent content = new WebResponseContent(); | 
|             try | 
|             { | 
|                 //获取所有的报废明细 | 
|                 Dt_ErpProScrapSheet erpProScrapSheet = _proScrapSheetRepository.Db.Queryable<Dt_ErpProScrapSheet>().Where(x => x.ProScrapSheetOrderNo == scrapNo).Includes(x => x.Details).First(); | 
|                 if (erpProScrapSheet == null) | 
|                 { | 
|                     return content.Error($"未找到对应报废单{scrapNo}"); | 
|                 } | 
|                 if (erpProScrapSheet.Details == null || erpProScrapSheet.Details.Count<=0) | 
|                 { | 
|                     return content.Error($"未找到对应报废单{scrapNo}明细"); | 
|                 } | 
|                 List<Dt_ErpProScrapSheetDetail> erpProScrapSheetDetails = erpProScrapSheet.Details.Where(x=> keys.Contains(x.Id) && x.ScrapProDetailStatus== OutOrderStatusEnum.出库完成.ObjToInt()).ToList(); | 
|                 List<Dt_ErpProScrapSheetDetail> overDetails= erpProScrapSheet.Details.Where(x => x.ScrapProDetailStatus == OutOrderStatusEnum.关闭.ObjToInt()).ToList(); | 
|                 int overCount = overDetails.Count; | 
|                 //进行报废提交操作 | 
|                 if (erpProScrapSheetDetails.Count!= keys.Length) | 
|                 { | 
|                     return content.Error($"提交了已报废明细或正在出库中,请检查"); | 
|                 } | 
|                 if ((overCount + keys.Length) == erpProScrapSheet.Details.Count) | 
|                 { | 
|                     erpProScrapSheet.ProScrapStatus = ProScrapSheetStatusEnum.Valid.ObjToInt(); | 
|                 } | 
|                 List<ScrapSheetItem> scrapSheetItems = new List<ScrapSheetItem>(); | 
|                 foreach (var item in erpProScrapSheetDetails) | 
|                 { | 
|                     item.ScrapProDetailStatus = OutOrderStatusEnum.关闭.ObjToInt(); | 
|                     item.OverScrapPcsQty = item.ScrapPcsQty; | 
|                     item.OverScrapSETQty = item.ScrapSETQty; | 
|                     ScrapSheetItem scrapSheetItem = new ScrapSheetItem() | 
|                     { | 
|                         PartNum = item.ScrapProCode, | 
|                         PartRev = item.ScrapProVersion, | 
|                         Lotno = item.ScrapProCode, | 
|                         QtyOfArray = item.ScrapSETQty, | 
|                         QtyOfUnit = item.ScrapPcsQty, | 
|                         QtyOfArray_Alloc = 0, | 
|                         QtyOfUnit_Alloc = 0, | 
|                     }; | 
|                     scrapSheetItems.Add(scrapSheetItem); | 
|                 } | 
|                 _unitOfWorkManage.BeginTran(); | 
|                 _proScrapSheetRepository.UpdateData(erpProScrapSheet); | 
|                 BaseDal.UpdateData(erpProScrapSheetDetails); | 
|                 if (erpProScrapSheet.ProScrapStatus == ProScrapSheetStatusEnum.Valid.ObjToInt()) | 
|                 { | 
|                     ERPScrapSheetModel scrapSheetModel = new ERPScrapSheetModel() | 
|                     { | 
|                         Way = 1, | 
|                         UniqueTag = erpProScrapSheet.Id.ToString(), | 
|                         Code = erpProScrapSheet.ProScrapSheetOrderNo, | 
|                         Status = ProScrapSheetStatusEnum.Valid.ToString(), | 
|                         Createtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), | 
|                         Createuser = erpProScrapSheet.Creater, | 
|                         WarehouseCode = WarehouseEnum.HA71.ToString(), | 
|                         DataItem = new List<ScrapSheetItem>() | 
|                     }; | 
|                     if (overCount>0) | 
|                     { | 
|                         foreach (var item in overDetails) | 
|                         { | 
|                             ScrapSheetItem scrapSheetItem = new ScrapSheetItem() | 
|                             { | 
|                                 PartNum = item.ScrapProCode, | 
|                                 PartRev = item.ScrapProVersion, | 
|                                 Lotno = item.ScrapProCode, | 
|                                 QtyOfArray = item.ScrapSETQty, | 
|                                 QtyOfUnit = item.ScrapPcsQty, | 
|                                 QtyOfArray_Alloc = 0, | 
|                                 QtyOfUnit_Alloc = 0, | 
|                             }; | 
|                             scrapSheetItems.Add(scrapSheetItem); | 
|                         } | 
|                     } | 
|                     scrapSheetModel.DataItem = scrapSheetItems; | 
|                     //上传ERP报废 | 
|                     string response = _invokeERPService.InvokeProScrapSheetApi(scrapSheetModel); | 
|                     ErpRequestContent requestContent = response.DeserializeObject<ErpRequestContent>(); | 
|                     if (requestContent.res != 1) | 
|                     { | 
|                         throw new Exception($"{requestContent.Data}"); | 
|                     } | 
|                 } | 
|                 _unitOfWorkManage.CommitTran(); | 
|                 content.OK(); | 
|             } | 
|             catch (Exception ex) | 
|             { | 
|                 _unitOfWorkManage.RollbackTran(); | 
|                 content.Error(ex.Message); | 
|             } | 
|             return content; | 
|         } | 
|         /// <summary> | 
|         /// 报废数据处理 | 
|         /// </summary> | 
|         public WebResponseContent LockOutboundStockDataUpdate(List<Dt_ProStockInfo> proStockInfos, List<Dt_ErpProScrapSheetDetail> scrapSheetDetails, List<Dt_OutProStockInfo> outProStockInfos, List<Dt_LocationInfo> locationInfos, LocationStatusEnum locationStatus = LocationStatusEnum.Lock, List<Dt_Task>? tasks = null) | 
|         { | 
|             try | 
|             { | 
|                 //更新库存属性 | 
|                 _stockService.ProStockInfoService.Repository.UpdateData(proStockInfos); | 
|                 List<Dt_ProStockInfoDetail> proStockInfoDetails = new List<Dt_ProStockInfoDetail>(); | 
|                 foreach (var item in proStockInfos) | 
|                 { | 
|                     proStockInfoDetails.AddRange(item.proStockInfoDetails); | 
|                 } | 
|                 //更新库存明细 | 
|                 proStockInfoDetails.ForEach(x => x.ProOutDetailStatus = StockStatusEmun.出库锁定.ObjToInt()); | 
|                 _stockService.ProStockInfoDetailService.Repository.UpdateData(proStockInfoDetails); | 
|                  | 
|                 BaseDal.UpdateData(scrapSheetDetails); | 
|   | 
|                 List<Dt_OutProStockInfo> addOutStockLockInfos = outProStockInfos.Where(x => x.Id == 0).ToList(); | 
|                 if (addOutStockLockInfos != null && addOutStockLockInfos.Any()) | 
|                 { | 
|                     if (tasks != null) | 
|                     { | 
|                         addOutStockLockInfos.ForEach(x => | 
|                         { | 
|                             x.TaskNum = tasks.FirstOrDefault(v => v.PalletCode == x.PalletCode)?.TaskNum; | 
|                         }); | 
|                     } | 
|   | 
|                     _outProStockInfoService.Repository.AddData(addOutStockLockInfos); | 
|                 } | 
|                 List<Dt_OutProStockInfo> updateOutStockLockInfos = outProStockInfos.Where(x => x.Id > 0).ToList(); | 
|                 if (updateOutStockLockInfos != null && updateOutStockLockInfos.Any()) | 
|                 { | 
|                     _outProStockInfoService.Repository.UpdateData(updateOutStockLockInfos); | 
|                 } | 
|   | 
|                 _recordService.LocationStatusChangeRecordSetvice.AddLocationStatusChangeRecord(locationInfos, locationStatus, LocationChangeType.OutboundAssignLocation, "", tasks?.Select(x => x.TaskNum).ToList()); | 
|                 _basicService.LocationInfoService.Repository.UpdateLocationStatus(locationInfos, locationStatus); | 
|                 return WebResponseContent.Instance.OK(); | 
|             } | 
|             catch (Exception ex) | 
|             { | 
|                 return WebResponseContent.Instance.Error(ex.Message); | 
|             } | 
|         } | 
|         public (List<Dt_ProStockInfo>, List<Dt_ErpProScrapSheetDetail>, List<Dt_OutProStockInfo>, List<Dt_LocationInfo>) AssignProStockOut(List<Dt_ErpProScrapSheetDetail> proOutOrderDetails, Dt_ErpProScrapSheet scrapSheet) | 
|         { | 
|             List<Dt_ProStockInfo> outStocks = new List<Dt_ProStockInfo>(); | 
|             List<Dt_OutProStockInfo> outProStockInfos = new List<Dt_OutProStockInfo>(); | 
|             List<Dt_LocationInfo> locationInfos = new List<Dt_LocationInfo>(); | 
|             foreach (var item in proOutOrderDetails) | 
|             { | 
|                 float needQty = item.ScrapPcsQty; | 
|                 //查找可用库存 | 
|                 List<Dt_ProStockInfo> stockInfoss = _stockService.ProStockInfoService.GetUseableStocks(scrapSheet.WarehouseId, item); | 
|                 if (!stockInfoss.Any()) | 
|                 { | 
|                     throw new Exception("未找到可分配库存"); | 
|                 } | 
|                 //获取出库库存 | 
|                 List<Dt_ProStockInfo> assignOutStocks = _stockService.ProStockInfoService.GetOutboundStocks(stockInfoss, item, needQty, out float residueQuantity); | 
|                 item.LockPcsQty += (int)(needQty - residueQuantity); | 
|                 if (item.ScrapPcsQty > item.LockPcsQty) | 
|                 { | 
|                     throw new Exception($"产品编码{item.ScrapProCode}可分配数量不足,可用数量{item.LockPcsQty}"); | 
|                 } | 
|                 outStocks.AddRange(assignOutStocks); | 
|                 item.LockPcsQty = 0; | 
|                 for (int j = 0; j < assignOutStocks.Count; j++) | 
|                 { | 
|                     //出库订单明细已分配数量 | 
|                     float detailAssignQuantity = outProStockInfos.Where(x => x.OrderDetailId == item.Id).Sum(x => x.AssignQuantity); | 
|                     float orderDetailNeedQuantity = item.ScrapPcsQty - detailAssignQuantity; | 
|                     if (orderDetailNeedQuantity > assignOutStocks[j].proStockInfoDetails.Sum(x => x.OutboundQuantity)) | 
|                     { | 
|                         item.LockPcsQty += (int)assignOutStocks[j].proStockInfoDetails.Sum(x => x.OutboundQuantity); | 
|                         Dt_OutProStockInfo outStockLockInfo = _outProStockInfoService.GetOutStockLockInfo(scrapSheet, item, assignOutStocks[j], assignOutStocks[j].proStockInfoDetails.Sum(x => x.OutboundQuantity)); | 
|                         outProStockInfos.Add(outStockLockInfo); | 
|                     } | 
|                     else | 
|                     { | 
|                         Dt_OutProStockInfo outStockLockInfo = _outProStockInfoService.GetOutStockLockInfo(scrapSheet, item, assignOutStocks[j], item.ScrapPcsQty - detailAssignQuantity); | 
|                         outProStockInfos.Add(outStockLockInfo); | 
|                         item.LockPcsQty = item.ScrapPcsQty; | 
|                         break; | 
|                     } | 
|                     //} | 
|                 } | 
|                 List<string> locationCodes = outStocks.Select(x => x.LocationCode).ToList(); | 
|                 List<Dt_LocationInfo> locationInfos1 = _basicService.LocationInfoService.Repository.GetLocationInfos(locationCodes); | 
|                 if (locationInfos1 == null)  | 
|                 { | 
|                     throw new Exception($"{locationCodes}货位查询为空,请检查"); | 
|                 } | 
|                 locationInfos.AddRange(locationInfos1); | 
|             } | 
|             return (outStocks, proOutOrderDetails, outProStockInfos, locationInfos); | 
|         } | 
|     } | 
| } |