| | |
| | | using Org.BouncyCastle.Asn1.Ocsp; |
| | | using SqlSugar; |
| | | using System; |
| | | using System.Collections.Concurrent; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Net; |
| | |
| | | |
| | | namespace WIDESEA_BasicService |
| | | { |
| | | public class TransferDataDto |
| | | { |
| | | public DateTime TransferTime { get; set; } |
| | | public List<TransferItemDto> Items { get; set; } |
| | | } |
| | | |
| | | public class TransferItemDto |
| | | { |
| | | public string MaterialCode { get; set; } |
| | | public decimal TotalQuantity { get; set; } |
| | | public List<LocationInfoDto> Locations { get; set; } |
| | | } |
| | | public class LocationInfoDto |
| | | { |
| | | public string LocationCode { get; set; } |
| | | public decimal Quantity { get; set; } |
| | | public List<BarcodeInfoDto> Barcodes { get; set; } |
| | | } |
| | | |
| | | public class BarcodeInfoDto |
| | | { |
| | | public string Barcode { get; set; } |
| | | public decimal Quantity { get; set; } |
| | | } |
| | | public class InvokeMESService : IInvokeMESService |
| | | { |
| | | private readonly IHttpClientFactory _httpClientFactory; |
| | |
| | | private readonly IOutboundOrderService _outboundOrderService; |
| | | private readonly IOutboundOrderDetailService _outboundOrderDetailService; |
| | | private readonly IOutStockLockInfoService _outStockLockInfoService; |
| | | |
| | | // åå¨èµæºIDåå
¶å¯¹åºçé对象ãä½¿ç¨ ConcurrentDictionary ç¡®ä¿å¯¹åå
¸æä½æ¬èº«ç线ç¨å®å
¨ã |
| | | private static readonly ConcurrentDictionary<string, object> _resourceLocks = new ConcurrentDictionary<string, object>(); |
| | | |
| | | // å
¨å±éæéï¼ç¨äºä¿æ¤ _resourceLocks åå
¸ä¸ GetOrAdd æ TryRemove æ¶çç«äº |
| | | private static readonly object _globalLocker = new object(); |
| | | public InvokeMESService(IHttpClientFactory httpClientFactory, ILogger<InvokeMESService> logger, IRepository<Dt_FeedbackToMes> feedbacktomesRepository, IRepository<Dt_StockInfoDetail> stockInfoDetailRepository, IRepository<Dt_StockInfo> stockInfoRepository, IRepository<Dt_InboundOrder> inboundOrderRepository, IOutboundOrderService outboundOrderService, IOutboundOrderDetailService outboundOrderDetailService, IOutStockLockInfoService outStockLockInfoService, IMaterialUnitService materialUnitService, IRepository<Dt_PickingRecord> pickingRecoreRepository) |
| | | { |
| | | _httpClientFactory = httpClientFactory; |
| | |
| | | _client.DefaultRequestHeaders.Clear(); |
| | | _client.DefaultRequestHeaders.Add("Accept", "application/json"); |
| | | |
| | | _logger.LogInformation("InvokeMESService FeedbackOutbound : "+ model.orderNo +" , " + json); |
| | | _logger.LogInformation("InvokeMESService FeedbackOutbound : " + model.orderNo + " , " + json); |
| | | |
| | | var response = await _client.PostAsync("AldMaterialOutbound/MaterialOutbound", content); |
| | | string body = await response.Content.ReadAsStringAsync(); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | |
| | | /// <returns></returns> |
| | | public async Task<WebResponseContent> BatchOrderFeedbackToMes(List<string> orderNos, int inout) |
| | | { |
| | | if (inout == 1) |
| | | // 1. ãå
å鿢å ã |
| | | if (MemoryLockManager.TryAcquireLock(orderNos[0])) |
| | | { |
| | | foreach (var orderNo in orderNos) |
| | | try |
| | | { |
| | | try |
| | | if (inout == 1) |
| | | { |
| | | var stockinfos = _stockInfoRepository.Db.Queryable<Dt_StockInfo>("info").Where(info => info.StockStatus == 6) |
| | | .Where(it => SqlFunc.Subqueryable<Dt_StockInfoDetail>().Where(s => s.StockId == it.Id && s.OrderNo == orderNo).Any()) |
| | | .ToList(); |
| | | var feeds = _feedbacktomesRepository.Db.Queryable<Dt_FeedbackToMes>().Where(x => x.OrderNo == orderNo && x.ReportStatus == 1).Select(o => o.PalletCode).ToList(); |
| | | var unreports = stockinfos.Where(x => !feeds.Contains(x.PalletCode)).ToList(); |
| | | if (unreports != null && !unreports.Any()) |
| | | foreach (var orderNo in orderNos) |
| | | { |
| | | return WebResponseContent.Instance.Error("没æéè¦åä¼ çæ°æ®"); |
| | | } |
| | | foreach (var item in unreports) |
| | | { |
| | | var lists = _stockInfoDetailRepository.Db.Queryable<Dt_StockInfoDetail>().Where(x => x.StockId == item.Id).ToList(); |
| | | if (lists.Any()) |
| | | try |
| | | { |
| | | var inboundOrder = _inboundOrderRepository.Db.Queryable<Dt_InboundOrder>().First(x => x.InboundOrderNo == lists.FirstOrDefault().OrderNo); |
| | | if (inboundOrder != null) |
| | | var stockinfos = _stockInfoRepository.Db.Queryable<Dt_StockInfo>("info").Where(info => info.StockStatus == 6) |
| | | .Where(it => SqlFunc.Subqueryable<Dt_StockInfoDetail>().Where(s => s.StockId == it.Id && s.OrderNo == orderNo).Any()) |
| | | .ToList(); |
| | | var feeds = _feedbacktomesRepository.Db.Queryable<Dt_FeedbackToMes>().Where(x => x.OrderNo == orderNo && x.ReportStatus == 1).Select(o => o.PalletCode).ToList(); |
| | | var unreports = stockinfos.Where(x => !feeds.Contains(x.PalletCode)).ToList(); |
| | | if (unreports != null && !unreports.Any()) |
| | | { |
| | | if (inboundOrder.OrderType == (int)InOrderTypeEnum.AllocatInbound)//è°æ¨å
¥åº |
| | | return WebResponseContent.Instance.Error("没æéè¦åä¼ çæ°æ®"); |
| | | } |
| | | foreach (var item in unreports) |
| | | { |
| | | var lists = _stockInfoDetailRepository.Db.Queryable<Dt_StockInfoDetail>().Where(x => x.StockId == item.Id).ToList(); |
| | | if (lists.Any()) |
| | | { |
| | | var allocate = SqlSugarHelper.DbWMS.Queryable<Dt_AllocateOrder>().Where(x => x.OrderNo == inboundOrder.InboundOrderNo).First(); |
| | | var allocatefeedmodel = new AllocateDto |
| | | var inboundOrder = _inboundOrderRepository.Db.Queryable<Dt_InboundOrder>().First(x => x.InboundOrderNo == lists.FirstOrDefault().OrderNo); |
| | | if (inboundOrder != null) |
| | | { |
| | | ReqCode = Guid.NewGuid().ToString(), |
| | | ReqTime = DateTime.Now.ToString(), |
| | | BusinessType = "2", |
| | | FactoryArea = inboundOrder.FactoryArea, |
| | | OperationType = 1, |
| | | Operator = inboundOrder.Operator, |
| | | OrderNo = inboundOrder.UpperOrderNo, |
| | | fromWarehouse = allocate?.FromWarehouse ?? "", |
| | | toWarehouse = allocate?.ToWarehouse ?? "", |
| | | Details = new List<AllocateDtoDetail>() |
| | | if (inboundOrder.OrderType == (int)InOrderTypeEnum.AllocatInbound)//è°æ¨å
¥åº |
| | | { |
| | | var allocate = SqlSugarHelper.DbWMS.Queryable<Dt_AllocateOrder>().Where(x => x.OrderNo == inboundOrder.InboundOrderNo).First(); |
| | | var allocatefeedmodel = new AllocateDto |
| | | { |
| | | ReqCode = Guid.NewGuid().ToString(), |
| | | ReqTime = DateTime.Now.ToString(), |
| | | BusinessType = "2", |
| | | FactoryArea = inboundOrder.FactoryArea, |
| | | OperationType = 1, |
| | | Operator = inboundOrder.Operator, |
| | | OrderNo = inboundOrder.UpperOrderNo, |
| | | fromWarehouse = allocate?.FromWarehouse ?? "", |
| | | toWarehouse = allocate?.ToWarehouse ?? "", |
| | | Details = new List<AllocateDtoDetail>() |
| | | |
| | | }; |
| | | }; |
| | | |
| | | var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.InboundOrderRowNo, item.BarcodeUnit, item.WarehouseCode }) |
| | | .Select(group => new AllocateDtoDetail |
| | | { |
| | | MaterialCode = group.Key.MaterielCode, |
| | | LineNo = group.Key.InboundOrderRowNo, |
| | | WarehouseCode = group.Key.WarehouseCode, |
| | | Qty = group.Sum(x => x.BarcodeQty), |
| | | Unit = group.Key.BarcodeUnit, |
| | | Barcodes = group.Select(row => new BarcodeInfo |
| | | { |
| | | Barcode = row.Barcode, |
| | | Qty = row.BarcodeQty, |
| | | BatchNo = row.BatchNo, |
| | | SupplyCode = row.SupplyCode, |
| | | Unit = row.BarcodeUnit |
| | | }).ToList() |
| | | }).ToList(); |
| | | allocatefeedmodel.Details = groupedData; |
| | | var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.InboundOrderRowNo, item.BarcodeUnit, item.WarehouseCode }) |
| | | .Select(group => new AllocateDtoDetail |
| | | { |
| | | MaterialCode = group.Key.MaterielCode, |
| | | LineNo = group.Key.InboundOrderRowNo, |
| | | WarehouseCode = group.Key.WarehouseCode, |
| | | Qty = group.Sum(x => x.BarcodeQty), |
| | | Unit = group.Key.BarcodeUnit, |
| | | Barcodes = group.Select(row => new BarcodeInfo |
| | | { |
| | | Barcode = row.Barcode, |
| | | Qty = row.BarcodeQty, |
| | | BatchNo = row.BatchNo, |
| | | SupplyCode = row.SupplyCode, |
| | | Unit = row.BarcodeUnit |
| | | }).ToList() |
| | | }).ToList(); |
| | | allocatefeedmodel.Details = groupedData; |
| | | |
| | | var result = await FeedbackAllocate(allocatefeedmodel); |
| | | if (result != null && result.code == 200) |
| | | { |
| | | _feedbacktomesRepository.Db.Insertable(new Dt_FeedbackToMes { OrderNo = orderNo, PalletCode = item.PalletCode, ReportStatus = 1 }).ExecuteCommand(); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | var feedmodel = new FeedbackInboundRequestModel |
| | | { |
| | | reqCode = Guid.NewGuid().ToString(), |
| | | reqTime = DateTime.Now.ToString(), |
| | | business_type = inboundOrder.BusinessType, |
| | | factoryArea = inboundOrder.FactoryArea, |
| | | operationType = 1, |
| | | Operator = inboundOrder.Operator, |
| | | orderNo = inboundOrder.UpperOrderNo, |
| | | status = inboundOrder.OrderStatus, |
| | | details = new List<FeedbackInboundDetailsModel>() |
| | | var result = await FeedbackAllocate(allocatefeedmodel); |
| | | if (result != null && result.code == 200) |
| | | { |
| | | _feedbacktomesRepository.Db.Insertable(new Dt_FeedbackToMes { OrderNo = orderNo, PalletCode = item.PalletCode, ReportStatus = 1 }).ExecuteCommand(); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | var feedmodel = new FeedbackInboundRequestModel |
| | | { |
| | | reqCode = Guid.NewGuid().ToString(), |
| | | reqTime = DateTime.Now.ToString(), |
| | | business_type = inboundOrder.BusinessType, |
| | | factoryArea = inboundOrder.FactoryArea, |
| | | operationType = 1, |
| | | Operator = inboundOrder.Operator, |
| | | orderNo = inboundOrder.UpperOrderNo, |
| | | status = inboundOrder.OrderStatus, |
| | | details = new List<FeedbackInboundDetailsModel>() |
| | | |
| | | }; |
| | | }; |
| | | |
| | | var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.SupplyCode, item.BatchNo, item.InboundOrderRowNo, item.BarcodeUnit, item.WarehouseCode }) |
| | | .Select(group => new FeedbackInboundDetailsModel |
| | | { |
| | | materialCode = group.Key.MaterielCode, |
| | | supplyCode = group.Key.SupplyCode, |
| | | batchNo = group.Key.BatchNo, |
| | | lineNo = group.Key.InboundOrderRowNo, |
| | | qty = group.Sum(x => x.BarcodeQty), |
| | | // warehouseCode = group.Key.WarehouseCode=="0"?"1072": group.Key.WarehouseCode, |
| | | warehouseCode = group.Key.WarehouseCode, |
| | | unit = group.Key.BarcodeUnit, |
| | | barcodes = group.Select(row => new FeedbackBarcodesModel |
| | | { |
| | | barcode = row.Barcode, |
| | | qty = row.BarcodeQty |
| | | }).ToList() |
| | | }).ToList(); |
| | | feedmodel.details = groupedData; |
| | | var result = await FeedbackInbound(feedmodel); |
| | | if (result != null && result.code == 200) |
| | | { |
| | | _feedbacktomesRepository.Db.Insertable(new Dt_FeedbackToMes { OrderNo = orderNo, PalletCode = item.PalletCode, ReportStatus = 1 }).ExecuteCommand(); |
| | | var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.SupplyCode, item.BatchNo, item.InboundOrderRowNo, item.BarcodeUnit, item.WarehouseCode }) |
| | | .Select(group => new FeedbackInboundDetailsModel |
| | | { |
| | | materialCode = group.Key.MaterielCode, |
| | | supplyCode = group.Key.SupplyCode, |
| | | batchNo = group.Key.BatchNo, |
| | | lineNo = group.Key.InboundOrderRowNo, |
| | | qty = group.Sum(x => x.BarcodeQty), |
| | | // warehouseCode = group.Key.WarehouseCode=="0"?"1072": group.Key.WarehouseCode, |
| | | warehouseCode = group.Key.WarehouseCode, |
| | | unit = group.Key.BarcodeUnit, |
| | | barcodes = group.Select(row => new FeedbackBarcodesModel |
| | | { |
| | | barcode = row.Barcode, |
| | | qty = row.BarcodeQty |
| | | }).ToList() |
| | | }).ToList(); |
| | | feedmodel.details = groupedData; |
| | | var result = await FeedbackInbound(feedmodel); |
| | | if (result != null && result.code == 200) |
| | | { |
| | | _feedbacktomesRepository.Db.Insertable(new Dt_FeedbackToMes { OrderNo = orderNo, PalletCode = item.PalletCode, ReportStatus = 1 }).ExecuteCommand(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogInformation("InvokeMESService BatchOrderFeedbackToMes ååMES失败: " + ex.Message); |
| | | return WebResponseContent.Instance.Error(ex.Message); |
| | | } |
| | | |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | else if (inout == 2) |
| | | { |
| | | _logger.LogInformation("InvokeMESService BatchOrderFeedbackToMes ååMES失败: " + ex.Message); |
| | | return WebResponseContent.Instance.Error(ex.Message); |
| | | } |
| | | foreach (var orderNo in orderNos) |
| | | { |
| | | var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().FirstAsync(x => x.OrderNo == orderNo); |
| | | if (outboundOrder != null && outboundOrder.IsBatch == 0) |
| | | { |
| | | var result = await HandleOutboundOrderToMESCompletion(outboundOrder, orderNo); |
| | | return result; |
| | | } |
| | | else if (outboundOrder != null && outboundOrder.IsBatch == 1) |
| | | { |
| | | var result = await HandleOutboundOrderBatchToMESCompletion(outboundOrder, orderNo); |
| | | return result; |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | // 2. ãéæ¾å
åéãæ è®ºæå失败ï¼å¿
须鿾 |
| | | MemoryLockManager.ReleaseLock(orderNos[0]); |
| | | } |
| | | } |
| | | else if (inout == 2) |
| | | else |
| | | { |
| | | foreach (var orderNo in orderNos) |
| | | { |
| | | var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().FirstAsync(x => x.OrderNo == orderNo); |
| | | if (outboundOrder != null && outboundOrder.IsBatch == 0) |
| | | { |
| | | var result = await HandleOutboundOrderToMESCompletion(outboundOrder, orderNo); |
| | | return result; |
| | | } |
| | | else if (outboundOrder != null && outboundOrder.IsBatch == 1) |
| | | { |
| | | var result = await HandleOutboundOrderBatchToMESCompletion(outboundOrder, orderNo); |
| | | return result; |
| | | } |
| | | } |
| | | // æ¢é失败ï¼è¯´ææå¦ä¸ä¸ªçº¿ç¨ï¼WCSåè°æäººå·¥æä½ï¼æ£å¨å¤ç |
| | | |
| | | return WebResponseContent.Instance.OK("WMSæ£å¨å¤çæ¤åä¼ ä»»å¡ï¼è¯·å¿é夿ä½ã"); |
| | | } |
| | | return WebResponseContent.Instance.OK(); |
| | | } |
| | |
| | | business_type = outboundOrder.BusinessType, |
| | | factoryArea = outboundOrder.FactoryArea, |
| | | operationType = 1, |
| | | Operator = outboundOrder.Operator!=""? outboundOrder.Operator:App.User.UserName, |
| | | Operator = outboundOrder.Operator != "" ? outboundOrder.Operator : App.User.UserName, |
| | | orderNo = outboundOrder.UpperOrderNo, |
| | | documentsNO = documentNo, |
| | | status = outboundOrder.OrderStatus, |
| | |
| | | else |
| | | { |
| | | barModel.qty = item.PickQuantity; |
| | | } |
| | | } |
| | | detailModel.currentDeliveryQty += barModel.qty; |
| | | detailModel.barcodes.Add(barModel); |
| | | } |
| | |
| | | feedModel.details.Add(detailModel); |
| | | } |
| | | |
| | | feedModel.details = feedModel.details.GroupBy(item => new { item.materialCode, item.lineNo, item.warehouseCode, item.unit,item.qty }).Select(group => new FeedbackOutboundDetailsModel |
| | | feedModel.details = feedModel.details.GroupBy(item => new { item.materialCode, item.lineNo, item.warehouseCode, item.unit, item.qty }).Select(group => new FeedbackOutboundDetailsModel |
| | | { |
| | | materialCode = group.Key.materialCode, |
| | | lineNo = group.Key.lineNo, |
| | |
| | | var now = DateTime.Now; |
| | | string datePart = now.ToString("MMdd"); |
| | | long ticksPart = now.Ticks; |
| | | // æ¼æ¥ï¼è®¡æ°å¨è¡¥0为3ä½ï¼é¿å
使°ä¸ä¸è´ï¼ |
| | | return $"{datePart}{ticksPart}"; |
| | | } |
| | | |
| | | public static string GenerateCount() |
| | | { |
| | | var now = DateTime.Now; |
| | | string datePart = now.ToString("yyyyMMddHHmmss"); |
| | | |
| | | |
| | | // ååéå¢è®¡æ°å¨ï¼å模1000ï¼ç¡®ä¿è®¡æ°å¨ä»
3ä½ï¼æ§å¶é¿åº¦ï¼ |
| | | long counterPart = Interlocked.Increment(ref _counter) % 1000; |
| | | |
| | | // æ¼æ¥ï¼è®¡æ°å¨è¡¥0为3ä½ï¼é¿å
使°ä¸ä¸è´ï¼ |
| | | return $"{datePart}{ticksPart}"; |
| | | return $"{datePart}{counterPart:D3}"; |
| | | } |
| | | } |
| | | |
| | | |
| | | public static class MemoryLockManager |
| | | { |
| | | // åå¨èµæºIDåå
¶å¯¹åºçé对象ãä½¿ç¨ ConcurrentDictionary ç¡®ä¿å¯¹åå
¸æä½æ¬èº«ç线ç¨å®å
¨ã |
| | | private static readonly ConcurrentDictionary<string, object> _resourceLocks = new ConcurrentDictionary<string, object>(); |
| | | |
| | | // å
¨å±éæéï¼ç¨äºä¿æ¤ _resourceLocks åå
¸ä¸ GetOrAdd æ TryRemove æ¶çç«äº |
| | | private static readonly object _globalLocker = new object(); |
| | | |
| | | /// <summary> |
| | | /// å°è¯éå®ä¸ä¸ªèµæºIDã |
| | | /// </summary> |
| | | /// <param name="resourceId">è¦éå®çèµæºIDï¼ä¾å¦ InboundRecord IDï¼</param> |
| | | /// <returns>æ¯å¦æåè·åé</returns> |
| | | public static bool TryAcquireLock(string resourceId) |
| | | { |
| | | object lockObject = null; |
| | | |
| | | // æ ¸å¿æè·¯ï¼ä¸ºæ¯ä¸ªèµæºå建ä¸ä¸ªå¯ä¸çé对象 |
| | | lock (_globalLocker) |
| | | { |
| | | // å¦æèµæºIDä¸å¨åå
¸ä¸ï¼åæ·»å ä¸ä¸ªæ°çé对象 |
| | | // å¦åï¼ä½¿ç¨å·²åå¨çé对象 |
| | | lockObject = _resourceLocks.GetOrAdd(resourceId, new object()); |
| | | } |
| | | |
| | | // å°è¯è·åèµæºç¹å®çé |
| | | // ä½¿ç¨ Monitor.TryEnter é¿å
é»å¡ï¼å¹¶å®ç°éé»å¡çæ¢é |
| | | return Monitor.TryEnter(lockObject); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// éæ¾èµæºIDçéå®ã |
| | | /// </summary> |
| | | /// <param name="resourceId">è¦éæ¾çèµæºID</param> |
| | | public static void ReleaseLock(string resourceId) |
| | | { |
| | | if (_resourceLocks.TryGetValue(resourceId, out object lockObject)) |
| | | { |
| | | // ç¡®ä¿éæ¾çæ¯å½åçº¿ç¨ææçé |
| | | if (Monitor.IsEntered(lockObject)) |
| | | { |
| | | Monitor.Exit(lockObject); |
| | | |
| | | // éæ¾éåï¼å°è¯ä»åå
¸ä¸ç§»é¤è¿ä¸ªéå¯¹è±¡ï¼æ¸
çå
åã |
| | | // å¿
é¡»å¨ Monitor.Exit ä¹åæ§è¡ã |
| | | lock (_globalLocker) |
| | | { |
| | | _resourceLocks.TryRemove(resourceId, out _); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |