Browse Source

优化团组费用确认逻辑,新增批量与单个操作

- 在 `GroupsController.cs` 中新增条件过滤,优化批量确认逻辑,避免重复插入记录,并新增单个团组确认操作方法。
- 增加操作日志记录,便于审计。
- 在 `FeeEntryAcknowledgeDtos.cs` 中新增基类 `FeeEntryAcknowledgeBaseDto`,减少代码重复,新增单个确认操作的 DTO。
- 优化 `Grp_FeeEntryAcknowledge.cs` 中字段注释,明确字段用途。
- 提升代码可读性和可维护性,增强异常处理,提供更灵活的操作支持。
Lyyyi 1 day ago
parent
commit
b057a9999f

+ 143 - 33
OASystem/OASystem.Api/Controllers/GroupsController.cs

@@ -366,6 +366,7 @@ namespace OASystem.API.Controllers
                 // 新增条件:不在确认记录表中(排除已确认的团组)
                 .Where(di => !SqlFunc.Subqueryable<Grp_FeeEntryAcknowledge>()
                     .Where(ack => ack.GroupId == di.Id && ack.IsDel == 0 && ack.UserId == currUserId)
+                    .Where(ack => feeTypeIds.Contains(ack.FeeTypeId))
                     .Where(ack => ack.IsAcknowledged == AcknowledgeStatusEnum.Acknowledged) // 只排除已确认的记录
                     .Any())
                 .Select(di => new
@@ -387,7 +388,7 @@ namespace OASystem.API.Controllers
 
         /// <summary>
         /// 提示用户录入团组费用信息
-        /// 已知晓确认操作记录(添加)
+        /// 已知晓确认操作记录(添加) 批量
         /// </summary>
         /// <param name="dto">请求体</param>
         /// <returns></returns>
@@ -397,37 +398,26 @@ namespace OASystem.API.Controllers
         {
             // 1. 参数验证
             if (dto?.GroupIds == null || !dto.GroupIds.Any())
-            {
                 return Ok(JsonView(false, "请选择需要确认的团组!"));
-            }
 
             if (dto.GroupIds.Count > 100)
-            {
                 return Ok(JsonView(false, "一次性确认团组数量不能超过100个!"));
-            }
 
             if (dto.CurrUserId <= 0)
-            {
                 return Ok(JsonView(false, "用户ID无效!"));
-            }
 
-            //2. 验证用户存在性
+            // 2. 验证用户存在性
             var userInfo = await _sqlSugar.Queryable<Sys_Users>()
                 .Where(x => x.Id == dto.CurrUserId && x.IsDel == 0)
                 .Select(x => new { x.Id, x.JobPostId, x.CnName })
                 .FirstAsync();
 
             if (userInfo == null)
-            {
                 return Ok(JsonView(false, "用户不存在或已被禁用!"));
-            }
 
             // 3. 获取费用类型
-            var feeTypeIds = new List<int>() { };
-            if (_dataInit.TryGetValue(userInfo.JobPostId, out var values))
-            {
-                feeTypeIds = values;
-            }
+            if (!_dataInit.TryGetValue(userInfo.JobPostId, out var feeTypeIds) || feeTypeIds?.Count == 0)
+                return Ok(JsonView(false, "当前用户岗位无对应的费用类型配置!"));
 
             // 4. 验证团组存在性
             var validGroupIds = await _sqlSugar.Queryable<Grp_DelegationInfo>()
@@ -436,31 +426,56 @@ namespace OASystem.API.Controllers
                 .ToListAsync();
 
             if (!validGroupIds.Any())
-            {
                 return Ok(JsonView(false, "未找到有效的团组信息!"));
+
+            // 5. 检查团组费用表中是否存在对应费用类型的数据
+            var existingFeeRecords = await _sqlSugar.Queryable<Grp_CreditCardPayment>()
+                .Where(x => validGroupIds.Contains(x.DIId) && x.IsDel == 0)
+                .Where(x => feeTypeIds.Contains(x.CTable))
+                .Select(x => new { GroupId = x.DIId, FeeTypeId = x.CTable })
+                .ToListAsync();
+
+            if (existingFeeRecords.Count > 0)
+            {
+                // 找出有问题的团组和费用类型
+                var problematicGroups = existingFeeRecords
+                    .GroupBy(x => x.GroupId)
+                    .Select(g => new
+                    {
+                        GroupId = g.Key,
+                        FeeTypeIds = string.Join(",", g.Select(x => x.FeeTypeId).Distinct())
+                    })
+                    .ToList();
+
+                var errorMessage = $"以下团组的费用表中已存在费用数据,不可添加确认记录:";
+                foreach (var group in problematicGroups)
+                {
+                    errorMessage += $"\n团组 {group.GroupId} - 费用类型ID: [{group.FeeTypeIds}]";
+                }
+
+                return Ok(JsonView(false, errorMessage));
             }
 
-            // 5. 检查是否已存在确认记录(避免重复确认)
-            var existingRecords = await _sqlSugar.Queryable<Grp_FeeEntryAcknowledge>()
-                .Where(x => validGroupIds.Contains(x.GroupId) &&
-                           x.UserId == dto.CurrUserId &&
-                           x.IsDel == 0)
+            // 6. 检查是否已存在确认记录(避免重复确认)
+            var existingAcknowledgeRecords = await _sqlSugar.Queryable<Grp_FeeEntryAcknowledge>()
+                .Where(x => x.UserId == dto.CurrUserId && x.IsDel == 0)
+                .Where(x => validGroupIds.Contains(x.GroupId))
+                .Where(x => feeTypeIds.Contains(x.FeeTypeId))
                 .Select(x => new { x.GroupId, x.FeeTypeId })
                 .ToListAsync();
 
-            // 6. 准备插入数据(过滤已存在的记录)
-            var infos = new List<Grp_FeeEntryAcknowledge>();
+            // 7. 准备插入数据(过滤已存在的记录)
+            var recordsToInsert = new List<Grp_FeeEntryAcknowledge>();
 
             foreach (var groupId in validGroupIds)
             {
-                // 为每个费用类型创建确认记录
                 foreach (var feeTypeId in feeTypeIds)
                 {
                     // 检查是否已存在相同记录
-                    var exists = existingRecords.Any(x => x.GroupId == groupId && x.FeeTypeId == feeTypeId);
+                    var exists = existingAcknowledgeRecords.Any(x => x.GroupId == groupId && x.FeeTypeId == feeTypeId);
                     if (!exists)
                     {
-                        infos.Add(new Grp_FeeEntryAcknowledge()
+                        recordsToInsert.Add(new Grp_FeeEntryAcknowledge()
                         {
                             GroupId = groupId,
                             UserId = dto.CurrUserId,
@@ -470,23 +485,118 @@ namespace OASystem.API.Controllers
                             AcknowledgeTime = DateTime.Now,
                             AcknowledgeType = Domain.Enums.AcknowledgeTypeEnum.WebConfirm,
                             CreateUserId = 4, // 系统创建
+                            CreateTime = DateTime.Now
                         });
                     }
                 }
             }
 
-            if (!infos.Any())
-            {
+            if (!recordsToInsert.Any())
                 return Ok(JsonView(true, "所选团组已确认,无需重复操作!"));
-            }
 
-            // 7. 批量插入数据
-            var successCount = await _sqlSugar.Insertable(infos).ExecuteCommandAsync();
-            if (successCount < 1)
+            // 8. 批量插入数据
+            var successCount = await _sqlSugar.Insertable(recordsToInsert).ExecuteCommandAsync();
+            if (successCount <= 0)
+                return Ok(JsonView(false, "操作失败,未能保存确认记录!"));
+
+            // 9. 记录操作日志
+            _logger.LogInformation("用户 {UserName}(ID:{UserId}) 批量确认了 {GroupCount} 个团组的费用类型,共添加 {RecordCount} 条确认记录",
+                userInfo.CnName, dto.CurrUserId, validGroupIds.Count, successCount);
+
+            return Ok(JsonView(true, $"操作成功!共为 {validGroupIds.Count} 个团组添加了 {successCount} 条确认记录"));
+        }
+
+        /// <summary>
+        /// 提示用户录入团组费用信息
+        /// 已知晓确认操作记录(添加) 单个
+        /// </summary>
+        /// <param name="dto">请求体</param>
+        /// <returns></returns>
+        [HttpPost]
+        [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
+        public async Task<IActionResult> FeeEntryAcknowledgeSingle(FeeEntryAcknowledgeSingleDto dto)
+        {
+
+            // 1. 参数验证
+            if (dto.GroupId <= 0)
+                return Ok(JsonView(false, "请选择有效的团组ID!"));
+
+            if (dto.CurrUserId <= 0)
+                return Ok(JsonView(false, "用户ID无效!"));
+
+            // 2. 验证用户存在性
+            var userInfo = await _sqlSugar.Queryable<Sys_Users>()
+                .Where(x => x.Id == dto.CurrUserId && x.IsDel == 0)
+                .Select(x => new { x.Id, x.JobPostId, x.CnName })
+                .FirstAsync();
+
+            if (userInfo == null)
+                return Ok(JsonView(false, "用户不存在或已被禁用!"));
+
+            // 3. 获取费用类型
+            if (!_dataInit.TryGetValue(userInfo.JobPostId, out var feeTypeIds) || feeTypeIds?.Count == 0)
+                return Ok(JsonView(false, "当前用户岗位无对应的费用类型配置!"));
+
+            // 4. 验证团组存在性
+            var groupExists = await _sqlSugar.Queryable<Grp_DelegationInfo>()
+                .AnyAsync(x => x.Id == dto.GroupId && x.IsDel == 0);
+
+            if (!groupExists)
+                return Ok(JsonView(false, "未找到有效的团组信息!"));
+
+            // 5. 检查团组费用表中是否存在对应费用类型的数据
+            var existingFeeRecords = await _sqlSugar.Queryable<Grp_CreditCardPayment>()
+                .Where(x => x.DIId == dto.GroupId && x.IsDel == 0)
+                .Where(x => feeTypeIds.Contains(x.CTable))
+                .Select(x => new { x.CTable }) 
+                .ToListAsync();
+
+            if (existingFeeRecords.Count > 0)
             {
-                return Ok(JsonView(false, $"操作失败!"));
+                var existingFeeTypeNames = existingFeeRecords.Select(x => x.CTable).Distinct().ToList();
+                return Ok(JsonView(false, $"团组费用表中已存在费用类型ID [{string.Join(",", existingFeeTypeNames)}] 的数据,不可添加确认无费用记录!"));
             }
 
+            // 6. 检查已存在的确认记录
+            var existingAcknowledgeRecords = await _sqlSugar.Queryable<Grp_FeeEntryAcknowledge>()
+                .Where(x => x.UserId == dto.CurrUserId && x.IsDel == 0)
+                .Where(x => x.GroupId == dto.GroupId)
+                .Where(x => feeTypeIds.Contains(x.FeeTypeId))
+                .Select(x => new { x.FeeTypeId })
+                .ToListAsync();
+
+            var existingAcknowledgeFeeTypeIds = existingAcknowledgeRecords.Select(x => x.FeeTypeId).ToHashSet();
+
+            // 7. 准备插入数据(过滤已存在的记录)
+            var recordsToInsert = feeTypeIds
+                .Where(feeTypeId => !existingAcknowledgeFeeTypeIds.Contains(feeTypeId))
+                .Select(feeTypeId => new Grp_FeeEntryAcknowledge
+                {
+                    GroupId = dto.GroupId,
+                    UserId = dto.CurrUserId,
+                    JobPostId = userInfo.JobPostId,
+                    FeeTypeId = feeTypeId,
+                    IsAcknowledged = Domain.Enums.AcknowledgeStatusEnum.Acknowledged,
+                    AcknowledgeTime = DateTime.Now,
+                    AcknowledgeType = Domain.Enums.AcknowledgeTypeEnum.WebConfirm,
+                    CreateUserId = 4, // 系统创建
+                    CreateTime = DateTime.Now
+                })
+                .ToList();
+
+            if (recordsToInsert.Count == 0)
+                return Ok(JsonView(true, "所选团组已确认,无需重复操作!"));
+
+            // 8. 批量插入数据
+            var successCount = await _sqlSugar.Insertable(recordsToInsert).ExecuteCommandAsync();
+
+            if (successCount <= 0)
+                return Ok(JsonView(false, "操作失败,未能保存确认记录!"));
+
+            // 9. 记录操作日志(可选)
+            _logger.LogInformation("用户 {UserName}(ID:{UserId}) 确认了团组 {GroupId} 的费用类型",
+                userInfo.CnName, dto.CurrUserId, dto.GroupId);
+
             return Ok(JsonView(true, $"操作成功!"));
         }
 

+ 12 - 2
OASystem/OASystem.Domain/Dtos/Groups/FeeEntryAcknowledgeDtos.cs

@@ -10,18 +10,28 @@ namespace OASystem.Domain.Dtos.Groups
     {
     }
 
-    public class FeeEntryAcknowledgeCrateDto
+    public class FeeEntryAcknowledgeBaseDto
     {
 
         /// <summary>
         /// 人员ID
         /// </summary>
         public int CurrUserId { get; set; }
+    }
+
+    public class FeeEntryAcknowledgeCrateDto : FeeEntryAcknowledgeBaseDto
+    {
 
         /// <summary>
         /// 团组ID
         /// </summary>
         public List<int> GroupIds { get; set; }
-        
+
+    }
+
+    public class FeeEntryAcknowledgeSingleDto : FeeEntryAcknowledgeBaseDto
+    {
+
+        public int GroupId { get; set; }
     }
 }

+ 1 - 1
OASystem/OASystem.Domain/Entities/Groups/Grp_FeeEntryAcknowledge.cs

@@ -38,7 +38,7 @@ namespace OASystem.Domain.Entities.Groups
         public int FeeTypeId { get; set; }
 
         /// <summary>
-        /// 是否已确认:0-未确认 1-已确认
+        /// 是否已确认(此团组->板块 无成本费用数据确认):0-未确认 1-已确认
         /// </summary>
         [SugarColumn(ColumnDescription = "是否已确认", IsNullable = true, ColumnDataType = "int")]
         public AcknowledgeStatusEnum IsAcknowledged { get; set; } = AcknowledgeStatusEnum.Acknowledged;