浏览代码

添加文本日志记录功能及汇率检查逻辑

在 `GroupsController.cs` 中引入 `ITextFileLogger` 以支持文本日志记录。
更新 `GeneralMethod.cs` 中的 `EnterExitCostCheckRate` 方法,增加对已使用币种的检查并返回实时汇率信息。
在 `Program.cs` 中配置 `Serilog` 以记录日志,并创建新的日志目录。
新增 `RateRecordInfo` 类于 `EnterExitCostView.cs`,用于记录汇率变更信息。
在 `EnterExitCostRepository.cs` 中添加 `GetCheckCurrencies` 方法以查询已使用的币种集合。
新增 `ITextFileLogger` 接口和 `TextFileLogger` 类,实现文本日志记录功能。
Lyyyi 4 天之前
父节点
当前提交
87c98f0dd8

+ 82 - 1
OASystem/OASystem.Api/Controllers/GroupsController.cs

@@ -15,6 +15,7 @@ using OASystem.API.OAMethodLib.Hub.HubClients;
 using OASystem.API.OAMethodLib.Hub.Hubs;
 using OASystem.API.OAMethodLib.JuHeAPI;
 using OASystem.API.OAMethodLib.KiMiApi;
+using OASystem.API.OAMethodLib.Logging;
 using OASystem.API.OAMethodLib.QiYeWeChatAPI.AppNotice;
 using OASystem.Domain.AesEncryption;
 using OASystem.Domain.Attributes;
@@ -41,6 +42,7 @@ using System.Diagnostics;
 using System.Globalization;
 using System.IO.Compression;
 using System.Text.Json;
+using System.Text.RegularExpressions;
 using System.Web;
 using static OASystem.API.OAMethodLib.JWTHelper;
 using static OASystem.Infrastructure.Repositories.Groups.AirTicketResRepository;
@@ -58,6 +60,7 @@ namespace OASystem.API.Controllers
     public class GroupsController : ControllerBase
     {
         private readonly ILogger<GroupsController> _logger;
+        private readonly ITextFileLogger _eec_textLogger;
         private readonly GrpScheduleRepository _grpScheduleRep;
         private readonly IMapper _mapper;
         private readonly DelegationInfoRepository _groupRepository;
@@ -112,6 +115,7 @@ namespace OASystem.API.Controllers
         /// 构造函数
         /// </summary>
         /// <param name="logger"></param>
+        /// <param name="eec_textLogger"></param>
         /// <param name="mapper"></param>
         /// <param name="hubContext"></param>
         /// <param name="sqlSugar"></param>
@@ -154,6 +158,7 @@ namespace OASystem.API.Controllers
         /// <param name="grpOrderPreInfoRep"></param>
         public GroupsController(
             ILogger<GroupsController> logger,
+            ITextFileLogger eec_textLogger,
             IMapper mapper,
             IHubContext<ChatHub, IChatClient> hubContext,
             SqlSugarClient sqlSugar,
@@ -197,6 +202,7 @@ namespace OASystem.API.Controllers
             )
         {
             _logger = logger;
+            _eec_textLogger = eec_textLogger;
             _mapper = mapper;
             _grpScheduleRep = grpScheduleRep;
             _groupRepository = groupRepository;
@@ -7350,6 +7356,46 @@ FROM
         {
             try
             {
+                var rateRecords = new List<RateRecordInfo>();
+                #region 汇率保存前存储
+                var info = await _sqlSugar.Queryable<Grp_EnterExitCost>().FirstAsync(x => x.IsDel == 0 && x.DiId == dto.DiId);
+                if (info != null)
+                {
+                    var cacheRateInfos = CommonFun.GetCurrencyChinaToList(info.CurrencyRemark);
+                    if (cacheRateInfos != null && cacheRateInfos.Count > 0)
+                    {
+                        rateRecords = cacheRateInfos.Select(x => new RateRecordInfo()
+                        {
+                            CurrencyCode = x.CurrencyCode,
+                            CurrencyName = x.CurrencyName,
+                            UpdatePreRate = x.Rate,
+                            UpdateBreRate = dto.Currencys.Where(x1 => x1.CurrencyName.Equals(x.CurrencyName)).FirstOrDefault()?.Rate ?? 0.00M
+                        }).ToList();
+                    }
+                    else
+                    {
+                        rateRecords = dto.Currencys.Select(x => new RateRecordInfo()
+                        {
+                            CurrencyCode = x.CurrencyCode,
+                            CurrencyName = x.CurrencyName,
+                            UpdatePreRate = 0.00M,
+                            UpdateBreRate = x.Rate
+                        }).ToList();
+                    }
+                }
+                else
+                {
+                    rateRecords = dto.Currencys.Select(x => new RateRecordInfo()
+                    {
+                        CurrencyCode = x.CurrencyCode,
+                        CurrencyName = x.CurrencyName,
+                        UpdatePreRate = 0.00M,
+                        UpdateBreRate = x.Rate
+                    }).ToList();
+                }
+
+                #endregion
+
                 var data = await _enterExitCostRep.PostEnterExitCostOperate(dto);
 
                 if (dto.DayOtherPriceData.Any())
@@ -7423,14 +7469,49 @@ FROM
                 //汇率信息记录
                 await GeneralMethod.RateRecordSave(dto.UserId, sign, "出入境费用");
 
+                var checkCurrencys = await _enterExitCostRep.GetCheckCurrencies(dto.DiId);
                 //汇率验证、反推 
-                (bool isSendMsg,string msgContent) = await GeneralMethod.EnterExitCostCheckRate(dto.DiId);
+                (bool isSendMsg,string msgContent,List<CurrencyInfo> liveRates) = await GeneralMethod.EnterExitCostCheckRate(dto.DiId, checkCurrencys);
                 if (isSendMsg)
                 {
                     //消息推送
                     await AppNoticeLibrary.SendUserMsg_GroupShare_ToFin(dto.DiId,dto.UserId,msgContent);
+
                 }
 
+                #region //日志汇率记录
+
+                //按照已使用币种记录
+                if (checkCurrencys != null && checkCurrencys.Count > 0)
+                {
+                    rateRecords = rateRecords.Where(x => checkCurrencys.Select(x1 => x1.CurrencyName).ToList().Contains(x.CurrencyName)).ToList();
+
+                    //汇率记录中加入实时汇率
+                    if (liveRates != null && liveRates.Count > 0)
+                    {
+                        foreach (var item in rateRecords)
+                        {
+                            item.CurrLiveRate = liveRates.Where(x => x.CurrencyName.Equals(item.CurrencyName)).FirstOrDefault()?.Rate ?? 0.00M;
+                        }
+                    }
+
+                    var teamName = await _sqlSugar.Queryable<Grp_DelegationInfo>().Where(x => x.Id == dto.DiId && x.IsDel == 0).Select(x => x.TeamName).FirstAsync();
+                    var operationName = await _sqlSugar.Queryable<Sys_Users>().Where(x => x.Id == dto.UserId && x.IsDel == 0).Select(x => x.CnName).FirstAsync();
+
+                    var logContent = new StringBuilder();
+                    foreach (var item in rateRecords)
+                    {
+
+                        var blRate = (item.CurrLiveRate * 1.0350M).TruncDecimals(4);
+
+                        string msg = $">- {item.CurrencyName}汇率:(页面保存前){item.UpdatePreRate:#0.0000}/(页面保存){item.UpdateBreRate:#0.0000}/实时汇率(已上浮1.0350):{blRate:#0.0000}【注:原接口输出汇率为:{item.CurrLiveRate:#0.0000}】";
+
+                        logContent.AppendLine(msg);
+                    }
+
+                    _eec_textLogger.LogInformation("团组:【{teamName}({groupId})】 操作人:【{operationName}】 操作时间:【{operationTime}】\r\n{logContent}", teamName, dto.DiId, operationName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), logContent.ToString());
+                }
+                #endregion
 
                 return Ok(JsonView(true, data.Msg, data.Data));
             }

+ 16 - 7
OASystem/OASystem.Api/OAMethodLib/GeneralMethod.cs

@@ -4296,11 +4296,14 @@ namespace OASystem.API.OAMethodLib
         /// 出入境费用 汇率验证
         /// </summary>
         /// <param name="groupId"></param>
+        /// <param name="checkCurrencys">已使用币种</param>
         /// <returns></returns>
-        public static async Task<(bool,string)> EnterExitCostCheckRate(int groupId)
+        public static async Task<(bool,string, List<CurrencyInfo>)> EnterExitCostCheckRate(int groupId,List<CurrencyInfo> checkCurrencys)
         {
+            if (checkCurrencys == null || checkCurrencys.Count < 1) return (false, string.Empty,new List<CurrencyInfo>());
+
             var info = await _sqlSugar.Queryable<Grp_EnterExitCost>().FirstAsync(x => x.IsDel == 0 && x.DiId == groupId);
-            if (info == null) return (false, string.Empty);
+            if (info == null) return (false, string.Empty, new List<CurrencyInfo>());
 
             List<CurrencyInfo> liveRates;
             var cacheRateInfo = await _sqlSugar.Queryable<Sys_ExchangeRateRecord>()
@@ -4309,7 +4312,7 @@ namespace OASystem.API.OAMethodLib
             if (cacheRateInfo == null)
             {
                 var _currencyRate = await _juHeApi.PostItemRateAsync(Array.Empty<string>());
-                if (_currencyRate.Count < 1) return (false, "获取汇率失败,请稍后再试!");
+                if (_currencyRate.Count < 1) return (false, "获取汇率失败,请稍后再试!", new List<CurrencyInfo>());
 
                 liveRates = _currencyRate.Select(it => new CurrencyInfo
                 {
@@ -4330,6 +4333,12 @@ namespace OASystem.API.OAMethodLib
             var isSendMsg = false;
             var msgContent = new StringBuilder();
 
+            //去掉费用未使用得币种
+            if (checkCurrencys != null && checkCurrencys.Count > 0)
+            {
+                cacheRateInfos = cacheRateInfos.Where(x => checkCurrencys.Select(x1 => x1.CurrencyName).ToList().Contains(x.CurrencyName)).ToList();
+            }
+
             if (cacheRateInfos.Any())
             {
                 decimal rowthRate = 1.0350M;
@@ -4339,17 +4348,17 @@ namespace OASystem.API.OAMethodLib
                     if (liveRate == null) continue;
 
                     var currRate = (rowthRate * liveRate.Rate).TruncDecimals(4);
-                    if (cacheRate.Rate > currRate)
+                    if (cacheRate.Rate != currRate)
                     {
                         isSendMsg = true;
                         //>团组归属:<font color='info'>{groupName}</font>
-                        msgContent.AppendLine($">- {cacheRate.CurrencyName}:存储汇率超过实时汇率,请注意!!!(存储汇率:{cacheRate.Rate.ToString("#0.0000")}  聚合API实时汇率:{currRate.ToString("#0.0000")}(已计算涨幅比例1.0350))");
+                        msgContent.AppendLine($">- {cacheRate.CurrencyName}:汇率:{cacheRate.Rate.ToString("#0.0000")}  实时汇率(已上浮1.035):{currRate.ToString("#0.0000")}【原接口输出汇率为:{liveRate.Rate.ToString("#0.0000")}】");
                     }
                 }
-                return (isSendMsg, msgContent.ToString());
+                return (isSendMsg, msgContent.ToString(), liveRates);
             }
 
-            return (false, string.Empty);
+            return (false, string.Empty, new List<CurrencyInfo>());
         }
 
         #endregion

+ 12 - 0
OASystem/OASystem.Api/OAMethodLib/Logging/ITextFileLogger.cs

@@ -0,0 +1,12 @@
+namespace OASystem.API.OAMethodLib.Logging
+{
+    /// <summary>
+    /// 文本日志接口
+    /// </summary>
+    public interface ITextFileLogger
+    {
+        void LogInformation(string message, params object[] args);
+        void LogWarning(string message, params object[] args);
+        void LogError(Exception ex, string message, params object[] args);
+    }
+}

+ 19 - 0
OASystem/OASystem.Api/OAMethodLib/Logging/TextFileLogger.cs

@@ -0,0 +1,19 @@
+using ILogger = Serilog.ILogger;
+
+namespace OASystem.API.OAMethodLib.Logging
+{
+    public class TextFileLogger : ITextFileLogger
+    {
+        private readonly ILogger _logger;
+        public TextFileLogger(ILogger logger) => _logger = logger;
+
+        public void LogInformation(string message, params object[] args)
+            => _logger.Information(message, args);
+
+        public void LogWarning(string message, params object[] args)
+            => _logger.Warning(message, args);
+
+        public void LogError(Exception ex, string message, params object[] args)
+            => _logger.Error(ex, message, args);
+    }
+}

+ 25 - 0
OASystem/OASystem.Api/Program.cs

@@ -19,6 +19,7 @@ using QuzrtzJob.Factory;
 using Serilog.Events;
 using System.Diagnostics;
 using System.IO.Compression;
+using OASystem.API.OAMethodLib.Logging;
 
 Console.Title = $"FMGJ OASystem Server";
 var builder = WebApplication.CreateBuilder(args);
@@ -360,8 +361,32 @@ Log.Logger = new LoggerConfiguration()
        .WriteTo.File(Path.Combine("Logs", @"Log.txt"), rollingInterval: RollingInterval.Day)
        .CreateLogger();
 
+// 创建出入境费用明细日志记录器专门用于文本记录
+
+// 指定磁盘绝对路径(示例:D盘的AppLogs文件夹)
+var logDirectory = @"D:\OASystem\Logs\EnterExitCost";
+
+// 自动创建目录(如果不存在)
+try
+{
+    Directory.CreateDirectory(logDirectory);
+    Log.Information($"日志目录已创建/确认存在: {logDirectory}");
+}
+catch (Exception ex)
+{
+    Log.Fatal($"无法创建日志目录 {logDirectory}: {ex.Message}");
+    throw;
+}
+
+var eec_TextLogger = new LoggerConfiguration()
+    .MinimumLevel.Information()
+    .WriteTo.File(Path.Combine(logDirectory, "text-records-.txt"), rollingInterval: RollingInterval.Month)
+    .CreateLogger();
+
 // 配置Serilog为Log;
 builder.Host.UseSerilog();
+
+builder.Services.AddSingleton<ITextFileLogger>(new TextFileLogger(eec_TextLogger));
 #endregion
 
 #region 引入注册Autofac Module

+ 32 - 0
OASystem/OASystem.Domain/ViewModels/Groups/EnterExitCostView.cs

@@ -1207,6 +1207,38 @@ namespace OASystem.Domain.ViewModels.Groups
         public string Remark { get; set; }
     }
 
+    /// <summary>
+    /// 汇率记录
+    /// </summary>
+    public class RateRecordInfo
+    {
+        /// <summary>
+        /// 币种Code
+        /// </summary>
+        public string? CurrencyCode { get; set; }
+
+        /// <summary>
+        /// 币种名称
+        /// </summary>
+        public string? CurrencyName { get; set; }
+
+        /// <summary>
+        /// 更改前汇率
+        /// </summary>
+        public decimal UpdatePreRate { get; set; }
+
+        /// <summary>
+        /// 更改后汇率
+        /// </summary>
+        public decimal UpdateBreRate { get; set; }
+
+        /// <summary>
+        /// 当时实时汇率
+        /// </summary>
+        public decimal CurrLiveRate { get; set; }
+
+    }
+
     /// <summary>
     /// 币种详情
     /// </summary>

+ 25 - 0
OASystem/OASystem.Infrastructure/Repositories/Groups/EnterExitCostRepository.cs

@@ -273,6 +273,31 @@ namespace OASystem.Infrastructure.Repositories.Groups
             return (false, msg);
         }
 
+
+        /// <summary>
+        /// 查询已使用币种集合
+        /// </summary>
+        /// <param name="groupId"></param>
+        /// <returns></returns>
+        public async Task<List<CurrencyInfo>> GetCheckCurrencies(int groupId)
+        {
+           var currencyInfos = new List<CurrencyInfo>();
+
+            if (groupId < 1) return currencyInfos;
+
+            var dayCurrencys = await _sqlSugar.Queryable<Grp_DayAndCost>()
+                .LeftJoin<Sys_SetData>((x,y) => x.Currency == y.Id)
+                .Where((x, y) => x.DiId == groupId && x.IsDel == 0)
+                .Select((x, y) => new CurrencyInfo
+                {
+                   CurrencyCode = y.Name,
+                   CurrencyName = y.Remark
+                })
+                .ToListAsync();
+
+            currencyInfos.AddRange(dayCurrencys);
+            return currencyInfos;
+        }
         /// <summary>
         /// 查询 根据 Diid 查询
         /// </summary>