浏览代码

Merge branch 'test' of http://110.188.24.182:10023/Fengwo/hotline into test

xf 3 月之前
父节点
当前提交
c3ddb68c9e
共有 31 个文件被更改,包括 582 次插入150 次删除
  1. 91 91
      src/Hotline.Api/Controllers/Bi/BiOrderController.cs
  2. 9 5
      src/Hotline.Api/Controllers/Bigscreen/DataScreenController.cs
  3. 4 2
      src/Hotline.Api/Controllers/OrderController.cs
  4. 1 0
      src/Hotline.Api/Controllers/PlanController.cs
  5. 56 0
      src/Hotline.Api/Controllers/Snapshot/InviteCodeController.cs
  6. 17 0
      src/Hotline.Api/Controllers/Snapshot/RedPackController.cs
  7. 4 3
      src/Hotline.Api/Controllers/Snapshot/SnapshotOrderController.cs
  8. 43 0
      src/Hotline.Application.Tests/Application/InviteCodeApplicationTest.cs
  9. 13 0
      src/Hotline.Application.Tests/Application/RedPackApplicationTest.cs
  10. 2 1
      src/Hotline.Application.Tests/appsettings.Development.json
  11. 12 3
      src/Hotline.Application/Orders/Handles/SnapshotHandler/GuiderSystemTimeoutHandler.cs
  12. 1 1
      src/Hotline.Application/Orders/OrderApplication.cs
  13. 15 0
      src/Hotline.Application/Snapshot/IInviteCodeApplication.cs
  14. 42 0
      src/Hotline.Application/Snapshot/InviteCodeApplication.cs
  15. 22 1
      src/Hotline.Application/Snapshot/RedPackApplication.cs
  16. 2 1
      src/Hotline.Application/Snapshot/SnapshotApplicationBase.cs
  17. 3 2
      src/Hotline.Application/StatisticalReport/OrderReportApplication.cs
  18. 1 1
      src/Hotline.Repository.SqlSugar/Snapshot/IndustryRepository.cs
  19. 18 0
      src/Hotline.Repository.SqlSugar/Snapshot/InviteCodeRepository.cs
  20. 2 1
      src/Hotline.Repository.SqlSugar/System/SystemLogRepository.cs
  21. 1 1
      src/Hotline.Share/Dtos/Bigscreen/BigscreenDto.cs
  22. 5 0
      src/Hotline.Share/Dtos/FlowEngine/NextStepsDto.cs
  23. 47 0
      src/Hotline.Share/Dtos/Snapshot/InviteCodeDto.cs
  24. 91 1
      src/Hotline.Share/Dtos/Snapshot/RedPackRecordDto.cs
  25. 1 1
      src/Hotline/Caching/Interfaces/ISystemSettingCacheManager.cs
  26. 2 2
      src/Hotline/Caching/Services/SystemSettingCacheManager.cs
  27. 1 1
      src/Hotline/Settings/ISystemLogRepository.cs
  28. 1 1
      src/Hotline/Snapshot/Interfaces/IIndustryRepository.cs
  29. 13 0
      src/Hotline/Snapshot/Interfaces/IInviteCodeRepository.cs
  30. 31 31
      src/Hotline/Snapshot/InviteCode.cs
  31. 31 0
      src/Hotline/dataview.md

+ 91 - 91
src/Hotline.Api/Controllers/Bi/BiOrderController.cs

@@ -1916,11 +1916,11 @@ namespace Hotline.Api.Controllers.Bi
                 .Select(o => new CenterReportCallDto
                 {
                     EffectiveCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.OnState == EOnState.On, 1, 0)),//有效
-					InTotal = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallDirection == ECallDirection.In, 1, 0)),//呼入总量
-					OutTotal = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallDirection == ECallDirection.Out, 1, 0)),//呼出总量
-					InConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallDirection == ECallDirection.In && o.AnsweredTime != null, 1, 0)),//呼入接通量
-					OutConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(o.TelNo != "0" && o.CallDirection == ECallDirection.Out && o.AnsweredTime != null, 1, 0)),//呼出接通量
-					InvalidCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.OnState == EOnState.NoOn /*&& o.BeginIvrTime.HasValue && o.BeginQueueTime.HasValue && o.BeginRingTime.HasValue*/, 1, 0)), //无效(排除队列挂断和IVR挂断)
+                    InTotal = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallDirection == ECallDirection.In, 1, 0)),//呼入总量
+                    OutTotal = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallDirection == ECallDirection.Out, 1, 0)),//呼出总量
+                    InConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallDirection == ECallDirection.In && o.AnsweredTime != null, 1, 0)),//呼入接通量
+                    OutConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(o.TelNo != "0" && o.CallDirection == ECallDirection.Out && o.AnsweredTime != null, 1, 0)),//呼出接通量
+                    InvalidCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.OnState == EOnState.NoOn /*&& o.BeginIvrTime.HasValue && o.BeginQueueTime.HasValue && o.BeginRingTime.HasValue*/, 1, 0)), //无效(排除队列挂断和IVR挂断)
                     QueueByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallDirection == ECallDirection.In && o.QueueTims > 0 && o.RingTimes == 0 && o.OnState == EOnState.NoOn, 1, 0)), //队列挂断
                     IvrByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallDirection == ECallDirection.In && o.BeginIvrTime.HasValue && !o.BeginQueueTime.HasValue && !o.BeginRingTime.HasValue && o.OnState == EOnState.NoOn, 1, 0)), //IVR挂断
                 })
@@ -2086,8 +2086,8 @@ namespace Hotline.Api.Controllers.Bi
             {
                 sourceChannel.Add(new CenterReportOrderSourceChannelDto
                 {
-					AllCountNum = sourceChannelCount,
-					Name = item.DicDataName,
+                    AllCountNum = sourceChannelCount,
+                    Name = item.DicDataName,
                     Code = item.DicTypeCode,
                     CountNum = sourceChannelData.Find(p => p.Code == item.DicDataValue)?.CountNum ?? 0
                 });
@@ -2495,14 +2495,14 @@ namespace Hotline.Api.Controllers.Bi
 
             if (enterpriseOrderDto2 != null)
             {
-				centerReportStatisticsDto.EnterpriseOrderDto.VisitdCount = enterpriseOrderDto2.VisitdCount;
-				centerReportStatisticsDto.EnterpriseOrderDto.Dissatisfied = enterpriseOrderDto2.Dissatisfied;
-				centerReportStatisticsDto.EnterpriseOrderDto.CityDissatisfied = enterpriseOrderDto2.CityDissatisfied;
-				centerReportStatisticsDto.EnterpriseOrderDto.CountyDissatisfied = enterpriseOrderDto2.CountyDissatisfied;
-				centerReportStatisticsDto.EnterpriseOrderDto.Satisfied = enterpriseOrderDto2.Satisfied;
-				centerReportStatisticsDto.EnterpriseOrderDto.CitySatisfied = enterpriseOrderDto2.CitySatisfied;
-				centerReportStatisticsDto.EnterpriseOrderDto.CountySatisfied = enterpriseOrderDto2.CountySatisfied;
-			}
+                centerReportStatisticsDto.EnterpriseOrderDto.VisitdCount = enterpriseOrderDto2.VisitdCount;
+                centerReportStatisticsDto.EnterpriseOrderDto.Dissatisfied = enterpriseOrderDto2.Dissatisfied;
+                centerReportStatisticsDto.EnterpriseOrderDto.CityDissatisfied = enterpriseOrderDto2.CityDissatisfied;
+                centerReportStatisticsDto.EnterpriseOrderDto.CountyDissatisfied = enterpriseOrderDto2.CountyDissatisfied;
+                centerReportStatisticsDto.EnterpriseOrderDto.Satisfied = enterpriseOrderDto2.Satisfied;
+                centerReportStatisticsDto.EnterpriseOrderDto.CitySatisfied = enterpriseOrderDto2.CitySatisfied;
+                centerReportStatisticsDto.EnterpriseOrderDto.CountySatisfied = enterpriseOrderDto2.CountySatisfied;
+            }
 
             if (listInfo != null && listInfo.Rows.Count > 0 && centerReportStatisticsDto.EnterpriseOrderDto != null)
             {
@@ -2525,65 +2525,65 @@ namespace Hotline.Api.Controllers.Bi
                 centerReportStatisticsDto.EnterpriseOrderDto.CountySatisfied = centerReportStatisticsDto.EnterpriseOrderDto.CountySatisfied + Convert.ToInt32(listInfo.Rows[0]["EnterpriseCountySatisfaction"]);
             }
 
-			#endregion
-
-			#region 企业信件分类
-			//信件来源
-			var enterpriseAcceptTypeData = await _orderRepository.Queryable(false, false, false)
-				.Where(p => p.CreationTime >= StartTime && p.CreationTime <= EndTime && p.IdentityType == EIdentityType.Enterprise)
-				.Select(it => new
-				{
-					AcceptTypeCode = SqlFunc.IIF(SqlFunc.IsNullOrEmpty(it.AcceptTypeCode), "40", it.AcceptTypeCode),
-					FileOrgIsCenter = it.FileOrgIsCenter.HasValue ? it.FileOrgIsCenter : true,
-					CreationTimeHandleDurationWorkday = it.CreationTimeHandleDurationWorkday.HasValue ? it.CenterToOrgHandleDurationWorkday : 0,
-					CenterToOrgHandleDurationWorkday = it.CenterToOrgHandleDurationWorkday.HasValue ? it.CenterToOrgHandleDurationWorkday : 0,
-				})
-				.MergeTable()//将查询出来的结果合并成一个新表
-				 .GroupBy(temp => new { temp.AcceptTypeCode })//对新表进行分组
-				 .Select(temp => new CenterReportOrderSourceChannelDto
-				 {
-					 Code = temp.AcceptTypeCode,
-					 CountNum = SqlFunc.AggregateCount(temp.AcceptTypeCode),
-					 CompletedAging = SqlFunc.AggregateSum(SqlFunc.IIF(temp.FileOrgIsCenter == true, temp.CreationTimeHandleDurationWorkday, temp.CenterToOrgHandleDurationWorkday))
-				 })
-				 .ToListAsync();
-			List<CenterReportOrderSourceChannelDto> enterpriseAcceptType = new();
-			var enterpriseAcceptTypeDic = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType);
-			foreach (var item in enterpriseAcceptTypeDic)
-			{
-				enterpriseAcceptType.Add(new CenterReportOrderSourceChannelDto
-				{
-					AllCountNum = sourceChannelCount,
-					Name = item.DicDataName,
-					Code = item.DicTypeCode,
-					CountNum = enterpriseAcceptTypeData.Find(p => p.Code == item.DicDataValue)?.CountNum ?? 0,
-					CompletedAging = enterpriseAcceptTypeData.Find(p => p.Code == item.DicDataValue)?.CompletedAging ?? 0
-				});
-			}
-
-			if (listPurOld != null && listPurOld.Rows.Count > 0 && enterpriseAcceptType != null)
-			{
-				foreach (var item in enterpriseAcceptType)
-				{
-					if (item.Code == "10")
-						item.CountNum = item.CountNum + Convert.ToInt32(listPurOld.Rows[0]["Consult"]);            // 咨询
-					else if (item.Code == "15")
-						item.CountNum = item.CountNum + Convert.ToInt32(listPurOld.Rows[0]["Suggest"]);            // 建议
-					else if (item.Code == "20")
-						item.CountNum = item.CountNum + Convert.ToInt32(listPurOld.Rows[0]["SeekHelp"]);           // 求助
-					else if (item.Code == "25")
-						item.CountNum = item.CountNum + Convert.ToInt32(listPurOld.Rows[0]["Praise"]);             // 表扬
-					else if (item.Code == "30")
-						item.CountNum = item.CountNum + Convert.ToInt32(listPurOld.Rows[0]["Report"]);             // 举报
-					else if (item.Code == "35")
-						item.CountNum = item.CountNum + Convert.ToInt32(listPurOld.Rows[0]["Complaint"]);          // 投诉
-				}
-			}
-
-			centerReportStatisticsDto.EnterpriseCenterReportOrderAcceptTypes = enterpriseAcceptType;
-			#endregion
-
-			return centerReportStatisticsDto;
+            #endregion
+
+            #region 企业信件分类
+            //信件来源
+            var enterpriseAcceptTypeData = await _orderRepository.Queryable(false, false, false)
+                .Where(p => p.CreationTime >= StartTime && p.CreationTime <= EndTime && p.IdentityType == EIdentityType.Enterprise)
+                .Select(it => new
+                {
+                    AcceptTypeCode = SqlFunc.IIF(SqlFunc.IsNullOrEmpty(it.AcceptTypeCode), "40", it.AcceptTypeCode),
+                    FileOrgIsCenter = it.FileOrgIsCenter.HasValue ? it.FileOrgIsCenter : true,
+                    CreationTimeHandleDurationWorkday = it.CreationTimeHandleDurationWorkday.HasValue ? it.CenterToOrgHandleDurationWorkday : 0,
+                    CenterToOrgHandleDurationWorkday = it.CenterToOrgHandleDurationWorkday.HasValue ? it.CenterToOrgHandleDurationWorkday : 0,
+                })
+                .MergeTable()//将查询出来的结果合并成一个新表
+                 .GroupBy(temp => new { temp.AcceptTypeCode })//对新表进行分组
+                 .Select(temp => new CenterReportOrderSourceChannelDto
+                 {
+                     Code = temp.AcceptTypeCode,
+                     CountNum = SqlFunc.AggregateCount(temp.AcceptTypeCode),
+                     CompletedAging = SqlFunc.AggregateSum(SqlFunc.IIF(temp.FileOrgIsCenter == true, temp.CreationTimeHandleDurationWorkday, temp.CenterToOrgHandleDurationWorkday))
+                 })
+                 .ToListAsync();
+            List<CenterReportOrderSourceChannelDto> enterpriseAcceptType = new();
+            var enterpriseAcceptTypeDic = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType);
+            foreach (var item in enterpriseAcceptTypeDic)
+            {
+                enterpriseAcceptType.Add(new CenterReportOrderSourceChannelDto
+                {
+                    AllCountNum = sourceChannelCount,
+                    Name = item.DicDataName,
+                    Code = item.DicTypeCode,
+                    CountNum = enterpriseAcceptTypeData.Find(p => p.Code == item.DicDataValue)?.CountNum ?? 0,
+                    CompletedAging = enterpriseAcceptTypeData.Find(p => p.Code == item.DicDataValue)?.CompletedAging ?? 0
+                });
+            }
+
+            if (listPurOld != null && listPurOld.Rows.Count > 0 && enterpriseAcceptType != null)
+            {
+                foreach (var item in enterpriseAcceptType)
+                {
+                    if (item.Code == "10")
+                        item.CountNum = item.CountNum + Convert.ToInt32(listPurOld.Rows[0]["Consult"]);            // 咨询
+                    else if (item.Code == "15")
+                        item.CountNum = item.CountNum + Convert.ToInt32(listPurOld.Rows[0]["Suggest"]);            // 建议
+                    else if (item.Code == "20")
+                        item.CountNum = item.CountNum + Convert.ToInt32(listPurOld.Rows[0]["SeekHelp"]);           // 求助
+                    else if (item.Code == "25")
+                        item.CountNum = item.CountNum + Convert.ToInt32(listPurOld.Rows[0]["Praise"]);             // 表扬
+                    else if (item.Code == "30")
+                        item.CountNum = item.CountNum + Convert.ToInt32(listPurOld.Rows[0]["Report"]);             // 举报
+                    else if (item.Code == "35")
+                        item.CountNum = item.CountNum + Convert.ToInt32(listPurOld.Rows[0]["Complaint"]);          // 投诉
+                }
+            }
+
+            centerReportStatisticsDto.EnterpriseCenterReportOrderAcceptTypes = enterpriseAcceptType;
+            #endregion
+
+            return centerReportStatisticsDto;
         }
 
 
@@ -5597,16 +5597,16 @@ namespace Hotline.Api.Controllers.Bi
         public async Task<List<OrderTsDetails>> GetQueryOrderTsDetailslOrderList(string KeyWord)
         {
             return await _orderTsDetailsRepository.Queryable()
-                .LeftJoin<Order>((ot,o)=>ot.OrderId==o.Id)
+                .LeftJoin<Order>((ot, o) => ot.OrderId == o.Id)
                    .Where((ot, o) => ot.Terms == KeyWord)
-                   .Select((ot, o)=>new OrderTsDetails
+                   .Select((ot, o) => new OrderTsDetails
                    {
-                       Id=ot.Id,
-                       Terms=ot.Terms,
-                       OrderId=o.Id,
-                       Title=o.Title,
-                       No=ot.No
-                   } )
+                       Id = ot.Id,
+                       Terms = ot.Terms,
+                       OrderId = o.Id,
+                       Title = o.Title,
+                       No = ot.No
+                   })
                    .ToListAsync(HttpContext.RequestAborted);
         }
 
@@ -5662,21 +5662,21 @@ namespace Hotline.Api.Controllers.Bi
         /// <summary>
         /// 根据知识库引用查询工单
         /// </summary>
-        /// <param name="KeyWord"></param>
+        /// <param name="dto"></param>
         /// <returns></returns>
         [HttpGet("get_query_knowledge_quote_order_list")]
-        public async Task<List<KnowledgeQuote>> GetQueryKnowledgeQuoteOrderList(string KeyWord)
+        public async Task<List<KnowledgeQuote>> GetQueryKnowledgeQuoteOrderList([FromQuery] PagedKeywordRequest dto)
         {
             return await _knowledgeQuoteRepository.Queryable()
                    .LeftJoin<Order>((kn, o) => kn.OrderId == o.Id)
-                   .Where((kn, o) => kn.KnowledgeId == KeyWord)
-                   .Select((kn, o)=>new KnowledgeQuote
+                   .Where((kn, o) => kn.KnowledgeId == dto.Keyword && kn.CreationTime >= dto.StartTime && kn.CreationTime <= dto.EndTime)
+                   .Select((kn, o) => new KnowledgeQuote
                    {
-                       KnowledgeId=kn.Id,
-                       KnowledgeTitle=o.Title,
-                       OrderId=o.Id,
-                       Title=o.Title,
-                       No=o.No,
+                       KnowledgeId = kn.Id,
+                       KnowledgeTitle = o.Title,
+                       OrderId = o.Id,
+                       Title = o.Title,
+                       No = o.No,
                    })
                    .ToListAsync(HttpContext.RequestAborted);
         }

+ 9 - 5
src/Hotline.Api/Controllers/Bigscreen/DataScreenController.cs

@@ -15,6 +15,7 @@ using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
 using SqlSugar;
+using System;
 using XF.Domain.Repository;
 
 namespace Hotline.Api.Controllers.Bigscreen
@@ -606,6 +607,7 @@ namespace Hotline.Api.Controllers.Bigscreen
         [HttpGet("order-secondary-statistics")]
         public async Task<SecondaryProcessingOrderStatisticsDto> OrderSecondaryStatistics(DateTime StartTime, DateTime EndTime)
         {
+            DateTime? dateTime = DateTime.Now;
             EndTime = EndTime.AddDays(1).AddSeconds(-1);
             var data = new SecondaryProcessingOrderStatisticsDto
             {
@@ -622,15 +624,17 @@ namespace Hotline.Api.Controllers.Bigscreen
 
                 OrderSoonOverdueCount = await _orderSecondaryHandlingRepository.Queryable()
                 .Includes(x => x.Order)
-                 .Where(x => x.Order.ExpiredStatus == EExpiredStatus.GoingToExpired && x.AuditTime >= StartTime && x.AuditTime <= EndTime
+                 .Where(x => x.Order.Status < EOrderStatus.Filed && dateTime > x.Order.NearlyExpiredTime && dateTime < x.Order.ExpiredTime)
+                 .Where(x => x.AuditTime >= StartTime && x.AuditTime <= EndTime
                  && x.State != ESecondaryHandlingState.NotApply
                  && x.State != ESecondaryHandlingState.Apply && x.State != ESecondaryHandlingState.Refuse)
                  .CountAsync()
             };
             var da = await _orderSecondaryHandlingRepository.Queryable()
-                .LeftJoin<OrderVisit>((os, ov) => os.VisitId == ov.Id)
-                    .LeftJoin<OrderVisitDetail>((os, ov, od) => os.VisitDetailId == od.Id)
-                    .Where((os, ov, od) => ov.VisitTime >= StartTime && ov.VisitTime <= EndTime && os.State != ESecondaryHandlingState.NotApply
+                .LeftJoin<OrderVisit>((os, ov) => os.OrderId == ov.OrderId)
+                    .LeftJoin<OrderVisitDetail>((os, ov, od) => ov.Id == od.VisitId)
+                    .Where((os, ov, od) => ov.VisitState == EVisitState.Visited && od.VisitTarget == EVisitTarget.Org && ov.VisitTime >= StartTime && ov.VisitTime <= EndTime
+                    && os.State != ESecondaryHandlingState.NotApply
                     && os.State != ESecondaryHandlingState.Apply && os.State != ESecondaryHandlingState.Refuse)
                     .Select((os, ov, od) => new SecondarySatisfactionDto()
                     {
@@ -652,7 +656,7 @@ namespace Hotline.Api.Controllers.Bigscreen
         public async Task<List<OrderSecondaryHandlingDto>> OrderSecondaryHandlingDetailQuery()
         {
             var quer = await _orderSecondaryHandlingRepository.Queryable()
-                 .Includes(x=>x.Order)
+                 .Includes(x => x.Order)
                   .Where(x => x.CreationTime.Date == DateTime.Now.Date)
                   .OrderByDescending(x => x.CreationTime)
                   .Take(50)

+ 4 - 2
src/Hotline.Api/Controllers/OrderController.cs

@@ -1985,11 +1985,11 @@ public class OrderController : BaseController
         if (int.Parse(setting?.SettingValue[0]) != 0 && !_sessionContext.OrgIsCenter)
         {
             int count = await _orderDelayRepository.CountAsync(x =>
-                x.OrderId == delaydto.OrderId && x.ApplyOrgCode == _sessionContext.RequiredOrgId && x.DelayState == EDelayState.Pass);
+                x.OrderId == delaydto.OrderId && x.ApplyOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")) == _sessionContext.RequiredOrgId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")) && x.DelayState == EDelayState.Pass);
             if (_appOptions.Value.IsZiGong)
             {
                 count = await _orderDelayRepository.CountAsync(x =>
-                    x.OrderId == delaydto.OrderId && x.ApplyOrgCode == _sessionContext.RequiredOrgId &&
+                    x.OrderId == delaydto.OrderId &&  x.ApplyOrgCode == _sessionContext.RequiredOrgId &&
                     (x.DelayState == EDelayState.Pass || x.DelayState == EDelayState.NoPass));
             }
 
@@ -4036,6 +4036,7 @@ public class OrderController : BaseController
         if (orderId.NotNullOrEmpty())
         {
             outDto.Opinion = await _typeCache.GetAsync($"tmp_opinion_{orderId}{_sessionContext.UserId}", HttpContext.RequestAborted);
+            outDto.Content = (await _orderRepository.GetAsync(orderId, HttpContext.RequestAborted))?.Content;
         }
 
         //随手拍
@@ -4365,6 +4366,7 @@ public class OrderController : BaseController
             throw UserFriendlyException.SameMessage("该工单未开启流程");
         var dto = await _workflowApplication.GetNextStepsAsync(order.WorkflowId, HttpContext.RequestAborted);
         dto.ExpiredTime = order.ExpiredTime;
+        dto.Content = order.Content;
         var rsp = _mapper.Map<NextStepsWithOpinionDto<RecommendStepOption>>(dto);
         foreach (var step in rsp.Steps)
         {

+ 1 - 0
src/Hotline.Api/Controllers/PlanController.cs

@@ -29,6 +29,7 @@ namespace Hotline.Api.Controllers
     public class PlanController : BaseController
     {
 
+
         #region 注入
 
         private readonly IMapper _mapper;

+ 56 - 0
src/Hotline.Api/Controllers/Snapshot/InviteCodeController.cs

@@ -0,0 +1,56 @@
+using Hotline.Application.Snapshot;
+using Hotline.Repository.SqlSugar.Extensions;
+using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.Snapshot;
+using Hotline.Share.Tools;
+using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
+using Microsoft.AspNetCore.Mvc;
+using System.ComponentModel;
+
+namespace Hotline.Api.Controllers.Snapshot;
+
+/// <summary>
+/// 邀请码管理
+/// </summary>
+[Description("邀请码管理")]
+public class InviteCodeController : BaseController
+{
+    private readonly IInviteCodeApplication _inviteCodeApplication;
+
+    public InviteCodeController(IInviteCodeApplication inviteCodeApplication)
+    {
+        _inviteCodeApplication = inviteCodeApplication;
+    }
+
+    /// <summary>
+    /// 获取添加邀请码基础数据
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("basedata")]
+    public async Task<Dictionary<string, object>> GetBasedataAsync()
+    {
+        return new Dictionary<string, object>
+        {
+            { "OrgName", await _inviteCodeApplication.GetInviteCodeItemsAsync().Where(m => m.ParentOrgId == null)
+            .Select(m => new Kv{ Key = m.Id, Value = m.OrgName}).ToListAsync() }
+        };
+    }
+
+    /// <summary>
+    /// 获取邀请码集合
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet]
+    public async Task<PagedDto<InviteCode>> GetInviteCodeItemsAsync([FromQuery] GetInviteCodeItemsInDto dto)
+        => (await _inviteCodeApplication.GetInviteCodeItemsAsync().ToPagedListAsync(dto)).ToPaged();
+
+    /// <summary>
+    /// 添加部门邀请码
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpPost]
+    public async Task AddInviteCodeAsync([FromBody] AddInviteCodeInDto dto)
+        => await _inviteCodeApplication.AddInviteCodeAsync(dto);
+}

+ 17 - 0
src/Hotline.Api/Controllers/Snapshot/RedPackController.cs

@@ -188,6 +188,23 @@ public class RedPackController : BaseController
     public async Task<PagedDto<SnapshotRedPackRecordItemsGuiderOutDto>> GetRedPackRecordGuiderItemsAsync([FromQuery] SnapshotRedPackRecordItemsGuiderInDto dto)
         => (await _redPackApplication.GetRedPackRecordGuiderItemsAsync(dto).ToPagedListAsync(dto)).ToPaged();
 
+    /// <summary>
+    /// 红包发放明细基础数据
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("record/send/database")]
+    public async Task<Dictionary<string, object>> GetRedPackRecordSendBaseDataAsync()
+    {
+        return new Dictionary<string, object>()
+        {
+            { "industry", await _industryRepository.Queryable()
+            .Select(m => new { m.Id, m.Name })
+            .ToListAsync()},
+            { "sendStatus", EnumExts.GetDescriptions<EReadPackSendStatus>().Where(m => m.Key != 2).ToList() },
+            { "userType", EnumExts.GetDescriptions<EReadPackUserType>() }
+        };
+    }
+
     /// <summary>
     /// 红包发放明细
     /// </summary>

+ 4 - 3
src/Hotline.Api/Controllers/Snapshot/SnapshotOrderController.cs

@@ -138,10 +138,11 @@ public class SnapshotOrderController : BaseController
     public async Task<SignOrderSnapshotDetailOutDto> GetSignOrderSnapshotDetailAsync(string id)
     { 
         var order = await _orderRepository.Queryable()
-            .LeftJoin<OrderSnapshot>((order, snapshot) => order.Id == snapshot.Id)
-            .Where((order, snapshot) => order.Id == id)
-            .Select((order, snapshot) => new SignOrderSnapshotDetailOutDto { Id = order.Id, Title = order.Title, Lables =snapshot.Labels })
+            .Where(order => order.Id == id)
+            .Select(order => new SignOrderSnapshotDetailOutDto(), true)
             .FirstAsync();
+        var snapshot = await _orderSnapshotRepository.GetAsync(id, HttpContext.RequestAborted);
+        order.Lables = snapshot.Labels;
         order.LabelsBaseData = _systemDicDataCacheManager.SnapshotOrderLabel;
         return order;
     }

+ 43 - 0
src/Hotline.Application.Tests/Application/InviteCodeApplicationTest.cs

@@ -0,0 +1,43 @@
+using Hotline.Api.Controllers;
+using Hotline.Application.Snapshot;
+using Hotline.Identity.Accounts;
+using Hotline.Identity.Roles;
+using Hotline.Share.Dtos.Snapshot;
+using Hotline.Snapshot.Interfaces;
+using Hotline.Users;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+
+namespace Hotline.Application.Tests.Application;
+public class InviteCodeApplicationTest : TestBase
+{
+    private readonly IInviteCodeApplication _inviteCodeApplication;
+
+    public InviteCodeApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, IInviteCodeApplication inviteCodeApplication) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository)
+    {
+        _inviteCodeApplication = inviteCodeApplication;
+    }
+
+    [Fact]
+    public async Task InviteCode_Test()
+    {
+        var inDto = new AddInviteCodeInDto
+        {
+            OrgName = "测试部门",
+            BeginCode = 1000,
+            EndCode = 2000,
+        };
+
+        await _inviteCodeApplication.AddInviteCodeAsync(inDto);
+
+        var items = _inviteCodeApplication.GetInviteCodeItemsAsync().ToList();
+        items.Count.ShouldNotBe(0);
+    }
+}

+ 13 - 0
src/Hotline.Application.Tests/Application/RedPackApplicationTest.cs

@@ -60,5 +60,18 @@ public class RedPackApplicationTest : TestBase
         record.ShouldNotBeNull();
         var recordItems = await _redPackApplication.GetRedPackRecordItemsAsync(new SnapshotRedPackRecordItemsInDto { Status =2}).ToListAsync();
         recordItems.Count.ShouldNotBe(0);
+
+        var redPackRecord = recordItems.First();
+        var redPackRecordEntity = await _redPackRecordRepository.GetAsync(redPackRecord.Id);
+        redPackRecordEntity.PickupStatus = ERedPackPickupStatus.Received;
+        redPackRecordEntity.DistributionState = EReadPackSendStatus.Successful;
+        redPackRecordEntity.ReceiveTime = DateTime.Now;
+        await _redPackRecordRepository.UpdateAsync(redPackRecordEntity);
+
+        var sendRecordItems = await _redPackApplication.GetRedPackRecordDetailAsync(new SnapshotRedPackRecordSendInDto
+        {
+            IsReceive = true,
+        }).ToListAsync();
+        sendRecordItems.Count.ShouldNotBe(0);
     }
 }

+ 2 - 1
src/Hotline.Application.Tests/appsettings.Development.json

@@ -68,7 +68,8 @@
         }
     },
     "ConnectionStrings": {
-        "Hotline": "PORT=5432;DATABASE=hotline_dev;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;",
+         "Hotline": "PORT=5432;DATABASE=hotline_dev;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;",
+        //"Hotline": "PORT=5432;DATABASE=hotline;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;",
         "CAP": "PORT=5432;DATABASE=fwmq;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;Search Path=cap"
         //"Hotline": "PORT=5432;DATABASE=hotline;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;"
     },

+ 12 - 3
src/Hotline.Application/Orders/Handles/SnapshotHandler/GuiderSystemTimeoutHandler.cs

@@ -13,6 +13,7 @@ using Hotline.Orders;
 using Hotline.Settings;
 using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Enums.FlowEngine;
+using Hotline.Share.Tools;
 using Hotline.Snapshot.Notifications;
 using MediatR;
 using XF.Domain.Exceptions;
@@ -44,11 +45,19 @@ namespace Hotline.Application.Orders.Handles.Snapshot
         /// <param name="cancellationToken">Cancellation token</param>
         public async Task Handle(GuiderSystemTimeOutBackNotification notification, CancellationToken cancellationToken)
         {
-            _systemLogRepository.Add("网格员超时未回复", notification.OrderId, "收到事件", "", 1);
-            if (_systemSettingCacheManager.Snapshot)
+            try
+            {
+                if (_systemSettingCacheManager.Snapshot)
+                {
+                    await _orderApplication.HandleFromWanggeyuanToMaskAsync(notification.OrderId, cancellationToken);
+                }
+            }
+            catch (Exception e)
             {
-                await _orderApplication.HandleFromWanggeyuanToMaskAsync(notification.OrderId, cancellationToken);
+                _systemLogRepository.Add("网格员超时未回复", notification.OrderId, "方法异常", status: 0, executeResult: e.ToJson());
+                throw;
             }
+            _systemLogRepository.Add("网格员超时未回复", notification.OrderId, "收到事件", "", 1);
         }
     }
 }

+ 1 - 1
src/Hotline.Application/Orders/OrderApplication.cs

@@ -3250,7 +3250,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         query = query.WhereIF(dto.VisitStateQuery == EVisitStateQuery.Visited, d => d.VisitState == EVisitState.Visited)
             .WhereIF(dto.VisitStateQuery == EVisitStateQuery.SMSUnsatisfied, d => d.VisitState == EVisitState.SMSUnsatisfied)
             .WhereIF(dto.VisitStateQuery == EVisitStateQuery.SMSVisiting, d => d.VisitState == EVisitState.SMSVisiting)
-            .WhereIF(dto.VisitStateQuery == EVisitStateQuery.NoPutThrough, d => d.IsPutThrough == false && d.VisitState != EVisitState.Visited)
+            .WhereIF(dto.VisitStateQuery == EVisitStateQuery.NoPutThrough, d => d.IsPutThrough == false && d.VisitState != EVisitState.Visited && d.VisitState != EVisitState.None)
             .WhereIF(dto.VisitStateQuery == EVisitStateQuery.ChipVoiceVisiting, d => d.VisitState == EVisitState.AiVisiting)//任务 162:回访状态快捷查询条件
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Order.Title.Contains(dto.Keyword!))
             .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No)

+ 15 - 0
src/Hotline.Application/Snapshot/IInviteCodeApplication.cs

@@ -0,0 +1,15 @@
+using Hotline.Share.Dtos.Snapshot;
+using Hotline.Snapshot;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Application.Snapshot;
+public interface IInviteCodeApplication
+{
+    Task AddInviteCodeAsync(AddInviteCodeInDto dto);
+    ISugarQueryable<InviteCode> GetInviteCodeItemsAsync();
+}

+ 42 - 0
src/Hotline.Application/Snapshot/InviteCodeApplication.cs

@@ -0,0 +1,42 @@
+using Hotline.Share.Dtos.Snapshot;
+using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
+using Mapster;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Dependency;
+using XF.Domain.Exceptions;
+
+namespace Hotline.Application.Snapshot;
+public class InviteCodeApplication : IInviteCodeApplication, IScopeDependency
+{
+    private readonly IInviteCodeRepository _inviteCodeRepository;
+
+    public InviteCodeApplication(IInviteCodeRepository inviteCodeRepository)
+    {
+        _inviteCodeRepository = inviteCodeRepository;
+    }
+
+    public async Task AddInviteCodeAsync(AddInviteCodeInDto dto)
+    {
+        if (_inviteCodeRepository.Queryable().Where(m => m.OrgName == dto.OrgName).Any())
+        {
+            throw UserFriendlyException.SameMessage("部门名称已存在");
+        }
+        var entity = dto.Adapt<InviteCode>();
+        if (dto.BeginCode >= dto.EndCode)
+        {
+            throw UserFriendlyException.SameMessage("开始邀请码不能大于结束邀请码");
+        }
+        await _inviteCodeRepository.AddAsync(entity);
+    }
+
+    public ISugarQueryable<InviteCode> GetInviteCodeItemsAsync()
+    {
+        return _inviteCodeRepository.Queryable();
+    }
+}

+ 22 - 1
src/Hotline.Application/Snapshot/RedPackApplication.cs

@@ -466,7 +466,28 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
 
     public ISugarQueryable<SnapshotRedPackRecordSendOutDto> GetRedPackRecordDetailAsync(SnapshotRedPackRecordSendInDto dto)
     {
-        throw new NotImplementedException();
+        var query = _redPackRecordRepository.Queryable()
+            .LeftJoin<OrderSnapshot>((m , snapshot) => m.OrderId == snapshot.Id)
+            .LeftJoin<Order>((m , snapshot, order) => m.OrderId == order.Id)
+            .Where(m => m.DistributionState != EReadPackSendStatus.Unsend)
+            .WhereIF(dto.Status == 1, m => m.PickupStatus == ERedPackPickupStatus.Received)
+            .WhereIF(dto.Status == 2, m => m.PickupStatus == ERedPackPickupStatus.Back)
+            .WhereIF(dto.Status == 3, m => m.DistributionState == EReadPackSendStatus.Fail)
+            .WhereIF(dto.Status == 4, m => m.PickupStatus == ERedPackPickupStatus.Unreceived)
+            .WhereIF(dto.IndustryId.NotNullOrEmpty(), (m, snapshot) => snapshot.IndustryId == dto.IndustryId)
+            .WhereIF(dto.No.NotNullOrEmpty(), order => order.No.Contains(dto.No))
+            .WhereIF(dto.UserType.HasValue, m => m.PeopleType == dto.UserType)
+            .WhereIF(dto.OpenId.NotNullOrEmpty(), m => m.WXOpenId == dto.OpenId)
+            .WhereIF(dto.SendStatus.HasValue, m => m.DistributionState == dto.SendStatus)
+            .WhereIF(dto.IsReceive.HasValue && dto.IsReceive == true, m => m.PickupStatus == ERedPackPickupStatus.Received)
+            .WhereIF(dto.IsReceive.HasValue && dto.IsReceive == false, m => m.PickupStatus == ERedPackPickupStatus.Unreceived)
+            .WhereIF(dto.BeginCreationTime.HasValue && dto.EndCreationTime.HasValue, m => m.CreationTime >= dto.BeginCreationTime && m.CreationTime <= dto.EndCreationTime)
+            .Select(m => new SnapshotRedPackRecordSendOutDto
+            { 
+                OrderId = m.OrderId,
+                UserType = m.PeopleType
+            }, true);
+        return query;
     }
 
 

+ 2 - 1
src/Hotline.Application/Snapshot/SnapshotApplicationBase.cs

@@ -564,7 +564,8 @@ public abstract class SnapshotApplicationBase
         _systemLog.Add(LogName, $"OrderNo: {order.No}", status: 1);
         if (result.Code == 0)
         {
-            int intervalTime = await _industryRepository.GetIntervalTimeAsync(orderSnapshot.IndustryId, _sysSetting.OvertimeBack, cancellationToken);
+            double intervalTime = await _industryRepository.GetIntervalTimeAsync(orderSnapshot.IndustryId, _sysSetting.OvertimeBack, cancellationToken);
+            _systemLog.Add(LogName, $"OrderNo: {order.No}", $"intervalTime: {intervalTime} overtimeBack: {_sysSetting.OvertimeBack}");
             await _capPublisher.PublishDelayAsync(TimeSpan.FromHours(intervalTime), EventNames.GuiderSystemReplyDelay, new PostGuiderSystemDelayed(order.Id), cancellationToken: cancellationToken);
         }
     }

+ 3 - 2
src/Hotline.Application/StatisticalReport/OrderReportApplication.cs

@@ -1654,7 +1654,7 @@ namespace Hotline.Application.StatisticalReport
 
             var centerOrgName = _systemSettingCacheManager.GetSetting(SettingConstants.CenterOrgName)?.SettingValue[0];
             var orderData = _orderRepository.Queryable()
-              .Where(it => it.CreationTime >= dto.StartTime && it.CreationTime <= dto.EndTime && it.Status >= EOrderStatus.Filed)
+              .Where(it => it.FiledTime >= dto.StartTime && it.FiledTime <= dto.EndTime && it.Status >= EOrderStatus.Filed)
             .WhereIF(dto.TypeId != null && dto.TypeId == 1, it => it.IdentityType == EIdentityType.Citizen)
             .WhereIF(dto.TypeId != null && dto.TypeId == 2, it => it.IdentityType == EIdentityType.Enterprise)
               .Select(it => new
@@ -1717,6 +1717,7 @@ namespace Hotline.Application.StatisticalReport
                     YjAllTimes = SqlFunc.AggregateSum(SqlFunc.IIF(it.AcceptTypeCode == "1" && it.AllTime != null, it.AllTime, 0)),
                     YjAcceptanceTypeCode = "1"
                 }).MergeTable();
+            Console.Write(orderData.ToSqlString());
             return orderData;
         }
 
@@ -1728,7 +1729,7 @@ namespace Hotline.Application.StatisticalReport
         public ISugarQueryable<Order> DepartmentAcceptanceTypeOrderList(DepartmentKeyWordRequest dto)
         {
             return _orderRepository.Queryable()
-                 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime && p.Status >= EOrderStatus.Filed)
+                 .Where(p => p.FiledTime >= dto.StartTime && p.FiledTime <= dto.EndTime && p.Status >= EOrderStatus.Filed)
                  .WhereIF(!string.IsNullOrEmpty(dto.OrgCode) && dto.OrgCode == "001", p => p.ActualHandleOrgCode == dto.OrgCode)
                  .WhereIF(dto.TypeId != null && dto.TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
                  .WhereIF(dto.TypeId != null && dto.TypeId == 2, p => p.IdentityType == EIdentityType.Enterprise)

+ 1 - 1
src/Hotline.Repository.SqlSugar/Snapshot/IndustryRepository.cs

@@ -17,7 +17,7 @@ public class IndustryRepository : BaseRepository<Industry>, IIndustryRepository,
     {
     }
 
-    public async Task<int> GetIntervalTimeAsync(string industryId, int defaultValue,  CancellationToken cancellationToken)
+    public async Task<double> GetIntervalTimeAsync(string industryId, double defaultValue,  CancellationToken cancellationToken)
     {
         var time = await Queryable().Where(m => m.Id == industryId).Select(m => m.IntervalTime).FirstAsync(cancellationToken);
         if (time <= 0)

+ 18 - 0
src/Hotline.Repository.SqlSugar/Snapshot/InviteCodeRepository.cs

@@ -0,0 +1,18 @@
+using Hotline.Snapshot.Interfaces;
+using Hotline.Snapshot;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Dependency;
+using SqlSugar;
+using Hotline.Repository.SqlSugar.DataPermissions;
+
+namespace Hotline.Repository.SqlSugar.Snapshot;
+public class InviteCodeRepository : BaseRepository<InviteCode>, IInviteCodeRepository, IScopeDependency
+{
+    public InviteCodeRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder) : base(uow, dataPermissionFilterBuilder)
+    {
+    }
+}

+ 2 - 1
src/Hotline.Repository.SqlSugar/System/SystemLogRepository.cs

@@ -18,7 +18,7 @@ public class SystemLogRepository : BaseRepository<SystemLog>, ISystemLogReposito
     {
     }
 
-    public void Add(string name, string executeParam = "", string remark = "", [CallerMemberName]string executeUrl = "", int status = 0, string ipUrl = "")
+    public void Add(string name, string executeParam = "", string remark = "", [CallerMemberName]string executeUrl = "", int status = 0, string ipUrl = "", string executeResult = "")
     {
         try
         {
@@ -26,6 +26,7 @@ public class SystemLogRepository : BaseRepository<SystemLog>, ISystemLogReposito
             {
                 Name = name,
                 ExecuteParam = executeParam,
+                ExecuteResult = executeResult,
                 ExecuteUrl = executeUrl,
                 Remark = remark,
                 Status = status,

+ 1 - 1
src/Hotline.Share/Dtos/Bigscreen/BigscreenDto.cs

@@ -263,7 +263,7 @@ namespace Hotline.Share.Dtos.Bigscreen
 
         public string CalcSatisfiedRate()
         {
-            if (Count == 0 || NoSatisfiedCount == 0)
+            if (Count == 0)
             {
                 return "0.000%";
             }

+ 5 - 0
src/Hotline.Share/Dtos/FlowEngine/NextStepsDto.cs

@@ -63,6 +63,11 @@ public class NextStepsDto
     /// 临时保存的办理意见
     /// </summary>
     public string? Opinion { get; set; }
+
+    /// <summary>
+    /// 受理类容
+    /// </summary>
+    public string? Content { get; set; }
 }
 
 public class NextStepsDto<TSteps> : NextStepsDto

+ 47 - 0
src/Hotline.Share/Dtos/Snapshot/InviteCodeDto.cs

@@ -0,0 +1,47 @@
+using Hotline.Share.Requests;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.Snapshot;
+public class InviteCodeDto
+{
+}
+
+public record GetInviteCodeItemsInDto : PagedRequest;
+
+public class AddInviteCodeInDto
+{
+    /// <summary>
+    /// 邀请码开始
+    /// 邀请码开始 -> 结束 范围内的邀请码都有效
+    /// </summary>
+    [Required]
+    public int BeginCode { get; set; }
+
+    /// <summary>
+    /// 邀请码结束
+    /// 邀请码开始 -> 结束 范围内的邀请码都有效
+    /// </summary>
+    [Required]
+    public int EndCode { get; set; }
+
+    /// <summary>
+    /// 部门名称
+    /// </summary>
+    [Required]
+    public string OrgName { get; set; }
+
+    /// <summary>
+    /// 上级部门ID
+    /// </summary>
+    public string ParentOrgId { get; set; }
+
+    /// <summary>
+    /// 邀请码Url
+    /// </summary>
+    public string QRCodeUrl { get; set; }
+}

+ 91 - 1
src/Hotline.Share/Dtos/Snapshot/RedPackRecordDto.cs

@@ -13,7 +13,87 @@ internal class RedPackRecordDto
 }
 
 public class SnapshotRedPackRecordSendOutDto
-{ }
+{
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// 工单Id
+    /// </summary>
+    public string OrderId { get; set; }
+
+    /// <summary>
+    /// No
+    /// </summary>
+    public string No { get; set; }
+
+    /// <summary>
+    /// 用户类型
+    /// </summary>
+    public EReadPackUserType UserType { get; set; }
+
+    /// <summary>
+    /// 用户类型
+    /// </summary>
+    public string UserTypeTxt => UserType.GetDescription();
+
+    /// <summary>
+    /// 行业
+    /// </summary>
+    public string IndustryName { get; set; }
+
+    /// <summary>
+    /// OpenId
+    /// </summary>
+    public string WXOpenId { get; set; }
+
+    /// <summary>
+    /// 商户订单号
+    /// </summary>
+    public string MerchantCode { get; set; }
+
+    /// <summary>
+    /// 金额
+    /// </summary>
+    public double Amount { get; set; }
+
+    /// <summary>
+    /// 发放时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 发放状态
+    /// </summary>
+    public EReadPackSendStatus DistributionState { get; set; }
+
+    /// <summary>
+    /// 发放状态
+    /// </summary>
+    public string DistributionStateTxt => DistributionState.GetDescription();
+
+    /// <summary>
+    /// 领取状态
+    /// </summary>
+    public ERedPackPickupStatus PickupStatus { get; set; }
+
+    /// <summary>
+    /// 领取状态
+    /// </summary>
+    public string PickupStatusTxt => PickupStatus.GetDescription();
+
+    /// <summary>
+    /// 领取操作时间
+    /// </summary>
+    public DateTime? ReceiveTime { get; set; }
+
+    /// <summary>
+    /// 备注
+    /// </summary>
+    public string? Remark { get; set; }
+}
 
 public record SnapshotRedPackRecordSendInDto : PagedRequest
 {
@@ -61,6 +141,16 @@ public record SnapshotRedPackRecordSendInDto : PagedRequest
     /// 是否补领
     /// </summary>
     public bool? IsReplace { get; set; }
+
+    /// <summary>
+    /// 发放时间开始
+    /// </summary>
+    public DateTime? BeginCreationTime { get; set; }
+
+    /// <summary>
+    /// 发放时间结束
+    /// </summary>
+    public DateTime? EndCreationTime { get; set; }
 }
 
 public record SnapshotRedPackRecordItemsGuiderInDto : SnapshotRedPackRecordItemsInDto

+ 1 - 1
src/Hotline/Caching/Interfaces/ISystemSettingCacheManager.cs

@@ -87,7 +87,7 @@ namespace Hotline.Caching.Interfaces
         /// 网格员回复等待时间(单位:小时)
         /// 超过该时间自动退回工单
         /// </summary>
-        int OvertimeBack { get; }
+        double OvertimeBack { get; }
 
         /// <summary>
         /// 天阙服务AppKey|AppSecret

+ 2 - 2
src/Hotline/Caching/Services/SystemSettingCacheManager.cs

@@ -179,8 +179,8 @@ namespace Hotline.Caching.Services
         /// 网格员回复等待时间(单位:小时)
         /// 超过该时间自动退回工单
         /// </summary>
-        public int OvertimeBack =>
-            GetOrDefault("08dd18e0-1c9e-4aa5-8dc6-f639e8d1b3ea", SettingConstants.OvertimeBack, "网格员回复等待时间(单元小时)", 4, "网格员回复等待时间(单位:小时), 超过该时间自动退回工单");
+        public double OvertimeBack =>
+            GetOrDefault("08dd18e0-1c9e-4aa5-8dc6-f639e8d1b3ea", SettingConstants.OvertimeBack, "网格员回复等待时间(单元小时)", 4d, "网格员回复等待时间(单位:小时), 超过该时间自动退回工单");
 
         /// <summary>
         /// 天阙服务AppKey|AppSecret

+ 1 - 1
src/Hotline/Settings/ISystemLogRepository.cs

@@ -18,5 +18,5 @@ public interface ISystemLogRepository : IRepository<SystemLog>
     /// <param name="remark">备注</param>
     /// <param name="status">状态(0失败 1成功)</param>
     /// <returns></returns>
-    void Add(string name, string executeParam = "", string remark = "", [CallerMemberName]string executeUrl = "", int status = 0, string ipUrl = "");
+    void Add(string name, string executeParam = "", string remark = "", [CallerMemberName]string executeUrl = "", int status = 0, string ipUrl = "", string executeResult = "");
 }

+ 1 - 1
src/Hotline/Snapshot/Interfaces/IIndustryRepository.cs

@@ -9,5 +9,5 @@ using XF.Domain.Repository;
 namespace Hotline.Snapshot.Interfaces;
 public interface IIndustryRepository : IRepository<Industry>
 {
-    Task<int> GetIntervalTimeAsync(string industryId, int defaultValue, CancellationToken cancellationToken);
+    Task<double> GetIntervalTimeAsync(string industryId, double defaultValue, CancellationToken cancellationToken);
 }

+ 13 - 0
src/Hotline/Snapshot/Interfaces/IInviteCodeRepository.cs

@@ -0,0 +1,13 @@
+using Microsoft.EntityFrameworkCore.Metadata;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+
+namespace Hotline.Snapshot.Interfaces;
+public interface IInviteCodeRepository : IRepository<InviteCode>
+{
+}

+ 31 - 31
src/Hotline/Snapshot/InviteCode.cs

@@ -12,38 +12,38 @@ namespace Hotline.Snapshot;
 /// <summary>
 /// 邀请码
 /// </summary>
-//[Description("邀请码")]
-//public class InviteCode : CreationSoftDeleteEntity
-//{
-//    /// <summary>
-//    /// 邀请码开始
-//    /// 邀请码开始 -> 结束 范围内的邀请码都有效
-//    /// </summary>
-//    [SugarColumn(ColumnDescription = "邀请码开始")]
-//    public string BeginCode { get; set; }
+[Description("邀请码")]
+public class InviteCode : CreationSoftDeleteEntity
+{
+    /// <summary>
+    /// 邀请码开始
+    /// 邀请码开始 -> 结束 范围内的邀请码都有效
+    /// </summary>
+    [SugarColumn(ColumnDescription = "邀请码开始")]
+    public int BeginCode { get; set; }
 
-//    /// <summary>
-//    /// 邀请码结束
-//    /// 邀请码开始 -> 结束 范围内的邀请码都有效
-//    /// </summary>
-//    [SugarColumn(ColumnDescription = "邀请码结束")]
-//    public string EndCode { get; set; }
+    /// <summary>
+    /// 邀请码结束
+    /// 邀请码开始 -> 结束 范围内的邀请码都有效
+    /// </summary>
+    [SugarColumn(ColumnDescription = "邀请码结束")]
+    public int EndCode { get; set; }
 
-//    /// <summary>
-//    /// 部门名称
-//    /// </summary>
-//    [SugarColumn(ColumnDescription = "部门名称")]
-//    public string OrgName { get; set; }
+    /// <summary>
+    /// 部门名称
+    /// </summary>
+    [SugarColumn(ColumnDescription = "部门名称")]
+    public string OrgName { get; set; }
 
-//    /// <summary>
-//    /// 上级部门ID
-//    /// </summary>
-//    [SugarColumn(ColumnDescription = "上级部门ID")]
-//    public string ParentOrgId { get; set; }
+    /// <summary>
+    /// 上级部门ID
+    /// </summary>
+    [SugarColumn(ColumnDescription = "上级部门ID")]
+    public string ParentOrgId { get; set; }
 
-//    /// <summary>
-//    /// 邀请码Url
-//    /// </summary>
-//    [SugarColumn(ColumnDescription = "邀请码Url")]
-//    public string QRCodeUrl { get; set; }
-//}
+    /// <summary>
+    /// 邀请码Url
+    /// </summary>
+    [SugarColumn(ColumnDescription = "邀请码Url")]
+    public string QRCodeUrl { get; set; }
+}

+ 31 - 0
src/Hotline/dataview.md

@@ -518,3 +518,34 @@ group by "OrderId") and "VisitState" not in(50,30)) and "VisitTarget"=20
 
 
 
+### 部门受理类型统计周期
+select 
+部门名称,部门类别,
+总件数,总时长, CAST(总时长/总件数/3600 as NUMERIC(10,2)) as 总平均,
+咨询件数,咨询时长,CASE 咨询件数 WHEN 0 THEN	0	ELSE CAST(咨询时长/咨询件数/3600 as NUMERIC(10,2)) END as 咨询平均,
+建议件数,建议时长,CASE 建议件数 WHEN 0 THEN 0 ELSE CAST(建议时长/建议件数/3600 as NUMERIC(10,2)) END as 建议平均,
+求助件数,求助时长,CASE 求助件数 WHEN 0 THEN 0 ELSE CAST(求助时长/求助件数/3600 as NUMERIC(10,2)) END as 求助平均,
+表扬件数,表扬时长,CASE 表扬件数 WHEN 0 THEN 0 ELSE CAST(表扬时长/表扬件数/3600 as NUMERIC(10,2)) END as 表扬平均,
+举报件数,举报时长,CASE 举报件数 WHEN 0 THEN 0 ELSE CAST(举报时长/举报件数/3600 as NUMERIC(10,2)) END as 举报平均,
+投诉件数,投诉时长,CASE 投诉件数 WHEN 0 THEN 0 ELSE CAST(投诉时长/投诉件数/3600 as NUMERIC(10,2)) END as 投诉平均,
+其他件数,其他时长,CASE 其他件数 WHEN 0 THEN 0 ELSE CAST(其他时长/其他件数/3600 as NUMERIC(10,2)) END as 其他平均 from (
+select "OrgName" as 部门名称,"OrgType" as  部门类别,("ZxAllCount" + "JyAllCount" + "QzAllCount" + "ByAllCount" + "JbAllCount" + "TsAllCount" + "QtAllCount")as 总件数,
+("ZxAllTimes" + "JyAllTimes" + "QzAllTimes" + "ByAllTimes" + "JbAllTimes" + "TsAllTimes" + "QtAllTimes") as 总时长,"ZxAllCount" as 咨询件数,"ZxAllTimes" as 咨询时长,"JyAllCount" as 建议件数,
+"JyAllTimes" as 建议时长,"QzAllCount" as 求助件数,"QzAllTimes" as 求助时长,"ByAllCount" as 表扬件数,"ByAllTimes" as 表扬时长,"JbAllCount" as 举报件数,"JbAllTimes" as 举报时长,"TsAllCount" as 投诉件数,
+"TsAllTimes" as 投诉时长,"QtAllCount" as 其他件数,"QtAllTimes" as 其他时长  from (
+SELECT * FROM  (SELECT  ( CASE  WHEN ( "it"."OrgCode" = N'001' ) THEN N'热线中心'  ELSE "o"."Name" END ) AS "OrgName" , "it"."OrgCode" AS "OrgCode" , ( CASE  WHEN ( "o"."OrgType" = 2 ) THEN N'区县部门'  ELSE N'市直部门' END ) AS "OrgType" ,
+SUM(( CASE  WHEN ( "it"."AcceptTypeCode" = N'10' ) THEN 1  ELSE 0 END )) AS "ZxAllCount" , SUM(( CASE  WHEN (( "it"."AcceptTypeCode" = N'10' ) AND ( "it"."AllTime" IS NOT NULL )) THEN "it"."AllTime"  ELSE 0 END )) AS "ZxAllTimes" ,
+N'10' AS "ZxAcceptanceTypeCode" , SUM(( CASE  WHEN ( "it"."AcceptTypeCode" = N'15' ) THEN 1  ELSE 0 END )) AS "JyAllCount" ,
+SUM(( CASE  WHEN (( "it"."AcceptTypeCode" = N'15' ) AND ( "it"."AllTime" IS NOT NULL )) THEN "it"."AllTime"  ELSE 0 END )) AS "JyAllTimes" , N'15' AS "JyAcceptanceTypeCode" , 
+SUM(( CASE  WHEN ( "it"."AcceptTypeCode" = N'20' ) THEN 1  ELSE 0 END )) AS "QzAllCount" , SUM(( CASE  WHEN (( "it"."AcceptTypeCode" = N'20' ) AND ( "it"."AllTime" IS NOT NULL )) THEN "it"."AllTime"  ELSE 0 END )) AS "QzAllTimes" ,
+N'20' AS "QzAcceptanceTypeCode" , SUM(( CASE  WHEN ( "it"."AcceptTypeCode" = N'25' ) THEN 1  ELSE 0 END )) AS "ByAllCount" , SUM(( CASE  WHEN (( "it"."AcceptTypeCode" = N'25' ) AND ( "it"."AllTime" IS NOT NULL )) THEN "it"."AllTime"  ELSE 0 END ))
+AS "ByAllTimes" , N'25' AS "ByAcceptanceTypeCode" , SUM(( CASE  WHEN ( "it"."AcceptTypeCode" = N'30' ) THEN 1  ELSE 0 END )) AS "JbAllCount" , SUM(( CASE  WHEN (( "it"."AcceptTypeCode" = N'30' ) AND 
+( "it"."AllTime" IS NOT NULL )) THEN "it"."AllTime"  ELSE 0 END )) AS "JbAllTimes" , N'30' AS "JbAcceptanceTypeCode" , SUM(( CASE  WHEN ( "it"."AcceptTypeCode" = N'35' ) THEN 1  ELSE 0 END )) AS "TsAllCount" , 
+SUM(( CASE  WHEN (( "it"."AcceptTypeCode" = N'35' ) AND ( "it"."AllTime" IS NOT NULL )) THEN "it"."AllTime"  ELSE 0 END )) AS "TsAllTimes" , N'35' AS "TsAcceptanceTypeCode" , 
+SUM(( CASE  WHEN ( "it"."AcceptTypeCode" = N'40' ) THEN 1  ELSE 0 END )) AS "QtAllCount" , SUM(( CASE  WHEN (( "it"."AcceptTypeCode" = N'40' ) AND ( "it"."AllTime" IS NOT NULL )) THEN "it"."AllTime"  ELSE 0 END )) AS "QtAllTimes" ,
+N'40' AS "QtAcceptanceTypeCode" , SUM(( CASE  WHEN ( "it"."AcceptTypeCode" = N'1' ) THEN 1  ELSE 0 END )) AS "YjAllCount" , 
+SUM(( CASE  WHEN (( "it"."AcceptTypeCode" = N'1' ) AND ( "it"."AllTime" IS NOT NULL )) THEN "it"."AllTime"  ELSE 0 END )) AS "YjAllTimes" , N'1' AS "YjAcceptanceTypeCode"  FROM  
+(SELECT * FROM  (SELECT  ( CASE  WHEN ( true = true ) THEN SUBSTRING("ActualHandleOrgCode",1 + 0,6)  ELSE SUBSTRING("ActualHandleOrgCode",1 + 0,(LENGTH(N'001')+ 3 )) END ) AS "OrgCode" , "AcceptTypeCode" AS "AcceptTypeCode" ,
+( CASE  WHEN ( "FileOrgIsCenter" = true ) THEN 10  ELSE 20 END ) AS "ProcessType" , ( CASE  WHEN ( "FileOrgIsCenter" = true ) THEN "CreationTimeHandleDurationWorkday"  ELSE "CenterToOrgHandleDurationWorkday" END ) AS "AllTime" ,
+"FileOrgIsCenter" AS "FileOrgIsCenter"  FROM "order"  WHERE ((( "FiledTime" >= '2024-12-01 00:00:00.000' ) AND ( "FiledTime" <= '2024-12-31 23:59:59.000' )) AND ( "Status" >= 300 ))  AND ( "IsDeleted" = false ) ) MergeTable ) "it"
+Left JOIN "system_organize" "o" ON ( "it"."OrgCode" = "o"."Id" )   WHERE ( "o"."IsDeleted" = false )GROUP BY "it"."OrgCode","o"."Name","o"."OrgType"  )))