helongyang
10 小时以前 3cd89b88edd913530062e13e20e7d6b866fd190f
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoService.cs
@@ -1,10 +1,12 @@
using AutoMapper;
using MailKit.Search;
using Newtonsoft.Json;
using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Common.StockEnum;
@@ -237,7 +239,7 @@
                {
                    Dt_StockInfo stockInfo = stockInfos[index];
                    float useableStockQuantity = stockInfo.Details.Where(x => x.MaterielCode == materielCode).Sum(x => x.StockQuantity - x.OutboundQuantity);
                    if (useableStockQuantity < needQuantity)
                    if (useableStockQuantity < needQuantity && useableStockQuantity>0)
                    {
                        stockInfo.Details.ForEach(x => x.OutboundQuantity = x.StockQuantity);
                        needQuantity -= useableStockQuantity;
@@ -267,36 +269,7 @@
            }
            else
            {
                for (int i = 0; i < stockInfos.Count; i++)
                {
                    Dt_StockInfo stockInfo = stockInfos[i];
                    float useableStockQuantity = stockInfo.Details.Where(x => x.MaterielCode == materielCode).Sum(x => x.StockQuantity - x.OutboundQuantity);
                    if (useableStockQuantity < needQuantity)
                    {
                        stockInfo.Details.ForEach(x => x.OutboundQuantity = x.StockQuantity);
                        needQuantity -= useableStockQuantity;
                    }
                    else
                    {
                        stockInfo.Details.ForEach(x =>
                        {
                            if (x.StockQuantity > x.OutboundQuantity && x.MaterielCode == materielCode)
                            {
                                if (x.StockQuantity - x.OutboundQuantity >= needQuantity)
                                {
                                    x.OutboundQuantity += needQuantity;
                                    needQuantity = 0;
                                }
                                else
                                {
                                    needQuantity -= (x.StockQuantity - x.OutboundQuantity);
                                    x.OutboundQuantity = x.StockQuantity;
                                }
                            }
                        });
                    }
                    outStocks.Add(stockInfo);
                }
                throw new Exception("库存不足");
            }
            residueQuantity = needQuantity;
            return outStocks;
@@ -318,5 +291,162 @@
            return BaseDal.GetStockInfos(materielCode, batchNo, locationCodes);
        }
        public WebResponseContent UpdateExpirationlabel()
        {
            try
            {
                var today = DateTime.Today;
                int batchSize = 1000;
                int totalUpdated = 0;
                int skipCount = 0;
                // åªæŸ¥è¯¢éœ€è¦çš„字段,减少数据传输和内存占用
                var query = BaseDal.Db.Queryable<Dt_StockInfoDetail>()
                    .InnerJoin<Dt_StockInfo>((detail, master) => detail.StockId == master.Id)
                    .Select((detail, master) => new
                    {
                        MasterId = master.Id,
                        master.WarehouseId,
                        detail.EffectiveDate,
                        CurrentExpirationlabel = master.Expirationlabel
                    });
                while (true)
                {
                    var batchData = query.Skip(skipCount).Take(batchSize).ToList();
                    if (!batchData.Any()) break;
                    var groupedData = batchData.GroupBy(item => item.MasterId)
                        .Select(g => new
                        {
                            MasterId = g.Key,
                            WarehouseId = g.First().WarehouseId,
                            // å–最早的有效日期
                            EarliestEffectiveDate = g.Min(item =>
                            {
                                DateTime.TryParse(item.EffectiveDate, out DateTime date);
                                return date;
                            }),
                            CurrentExpirationlabel = g.First().CurrentExpirationlabel
                        })
                        .ToList();
                    var updateDic = new Dictionary<long, int>();
                    foreach (var group in groupedData)
                    {
                        DateTime effectiveDate = group.EarliestEffectiveDate;
                        if (effectiveDate == default(DateTime)) // å¤„理解析失败的情况
                        {
                            Console.WriteLine($"主表ID {group.MasterId} ä¸‹æ— æœ‰æ•ˆæ—¥æœŸï¼Œè·³è¿‡");
                            continue;
                        }
                        int newLabel;
                        if (effectiveDate < today)
                        {
                            newLabel = ExpirationlabelEnum.过期.ObjToInt();
                        }
                        else if (group.WarehouseId == 3)
                        {
                            int daysDiff = (effectiveDate - today).Days;
                            newLabel = daysDiff < 60
                                ? ExpirationlabelEnum.临期预警.ObjToInt()
                                : ExpirationlabelEnum.未临期.ObjToInt();
                        }
                        else
                        {
                            int daysDiff = (effectiveDate - today).Days;
                            newLabel = daysDiff < 30
                                ? ExpirationlabelEnum.临期预警.ObjToInt()
                                : ExpirationlabelEnum.未临期.ObjToInt();
                        }
                        if (newLabel != group.CurrentExpirationlabel && !updateDic.ContainsKey(group.MasterId))
                        {
                            updateDic[group.MasterId] = newLabel;
                        }
                    }
                    if (updateDic.Any())
                    {
                        var updateBuilder = BaseDal.Db.Updateable<Dt_StockInfo>();
                        var idsToUpdate = updateDic.Keys.ToList();
                        int updateValue = updateDic.First().Value;
                        updateBuilder.SetColumns(m => m.Expirationlabel == updateValue)
                                     .Where(m => idsToUpdate.Contains(m.Id));
                        int batchUpdated = updateBuilder.ExecuteCommand();
                        totalUpdated += batchUpdated;
                        Console.WriteLine($"批次更新:{batchUpdated} æ¡ï¼Œç´¯è®¡æ›´æ–°ï¼š{totalUpdated} æ¡ï¼Œæ›´æ–°æ¡ä»¶ï¼š{JsonConvert.SerializeObject(idsToUpdate)}");
                    }
                    skipCount += batchSize;
                }
                return WebResponseContent.Instance.OK($"更新成功,共更新 {totalUpdated} æ¡è®°å½•");
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error("更新失败,请联系管理员");
            }
        }
        /// <summary>
        /// é’‰é’‰æœºå™¨äººæ¶ˆæ¯æŽ¨é€æµ‹è¯•
        /// </summary>
        /// <returns></returns>
        public async Task T0DingTalkText(string webhookUrl, string secret)
        {
            try
            {
                if (webhookUrl == null || secret == null)
                {
                    webhookUrl = "https://oapi.dingtalk.com/robot/send?access_token=fbc3aaf4133ea650d8116fb86b3ebfd0c5e0d46775966ce87893a41886bdf9dc";
                    secret = "SECf221842b26356f22ccac84c4e60714e5287408ee8332a8f63503791382c3f5fb";
                }
                HttpClient httpClient = new HttpClient();
                ///获取时间戳
                var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
                ///生成签名
                var sign = GenerateSign(timestamp,secret);
                // æž„建请求URL
                var url = $"{webhookUrl.Split('?')[0]}?access_token={new Uri(webhookUrl).Query.Split('=')[1]}&timestamp={timestamp}&sign={sign}";
                var requestBody = new
                {
                    msgtype = "text",
                    text = new { content = "小洋主人说: å°æ´‹è¦å’Œå°å¦å¤©ä¸‹ç¬¬ä¸€æœ€æœ€å¥½" },
                };
                var jsonBody = JsonConvert.SerializeObject(requestBody);
                var content = new StringContent(jsonBody, Encoding.UTF8, "application/json");
                // å‘送POST请求
                var response = await httpClient.PostAsync(url, content);
                if (!response.IsSuccessStatusCode)
                {
                    // å¤„理请求失败的情况
                    var errorContent = await response.Content.ReadAsStringAsync();
                    throw new Exception($"钉钉消息发送失败,状态码: {response.StatusCode},错误内容: {errorContent}");
                }
            }
            catch(Exception ex)
            {
                throw new Exception($"钉钉消息发送失败,错误内容: {ex.Message}");
            }
        }
        /// <summary>
        /// ç”ŸæˆåŠ ç­¾ç­¾å
        /// </summary>
        /// <param name="timestamp">时间戳</param>
        /// <returns>签名</returns>
        private string GenerateSign(long timestamp,string secret)
        {
            var stringToSign = $"{timestamp}\n{secret}";
            using (var hmacsha256 = new System.Security.Cryptography.HMACSHA256(Encoding.UTF8.GetBytes(secret)))
            {
                var hashBytes = hmacsha256.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
                return Convert.ToBase64String(hashBytes).Replace("+", "%2B").Replace("/", "%2F");
            }
        }
    }
}