Эх сурвалжийг харах

Merge branch 'master' of http://git.12345lm.cn/Fengwo/hotline

TANG JIANG 1 жил өмнө
parent
commit
ea51e22130

+ 192 - 61
src/Hotline.Api/Controllers/Bi/BiOrderController.cs

@@ -1,8 +1,11 @@
 using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.Calls;
+using Hotline.FlowEngine.WorkflowModules;
 using Hotline.FlowEngine.Workflows;
 using Hotline.Orders;
 using Hotline.Repository.SqlSugar.Extensions;
+using Hotline.Schedulings;
+using Hotline.Repository.SqlSugar.System;
 using Hotline.Settings;
 using Hotline.Settings.Hotspots;
 using Hotline.Share.Dtos;
@@ -46,6 +49,7 @@ namespace Hotline.Api.Controllers.Bi
         private readonly ISessionContext _sessionContext;
         private readonly ISystemSettingCacheManager _systemSettingCacheManager;
         private readonly IRepository<OrderSpecialDetail> _orderSpecialDetailRepository;
+        private readonly IRepository<WorkflowStepHandler> _workflowStepHandler;
         private readonly IRepository<WorkflowTrace> _workflowTraceRepository;
 
         public BiOrderController(
@@ -65,6 +69,7 @@ namespace Hotline.Api.Controllers.Bi
             ISessionContext sessionContext,
             ISystemSettingCacheManager systemSettingCacheManager,
             IRepository<OrderSpecialDetail> orderSpecialDetailRepository,
+            IRepository<WorkflowStepHandler> workflowStepHandler,
             IRepository<WorkflowTrace> workflowTraceRepository
             )
         {
@@ -84,22 +89,41 @@ namespace Hotline.Api.Controllers.Bi
             _sessionContext = sessionContext;
             _systemSettingCacheManager = systemSettingCacheManager;
             _orderSpecialDetailRepository = orderSpecialDetailRepository;
+            _workflowStepHandler = workflowStepHandler;
             _workflowTraceRepository = workflowTraceRepository;
 
         }
 
         //public async Task OrgDataListDetail([FromQuery] OrgDataListDetailRequest dto)
         //{
-        //    dto.EndDate = dto.EndDate.AddDays(1).AddSeconds(-1);
+        //    dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
 
-        //    await _orderRepository.Queryable()
-        //    .Where(x => x.CreationTime >= dto.StartDate && x.CreationTime <= dto.EndDate)
+        //    var queryOrder = _orderRepository.Queryable()
+        //    .Where(x => x.CreationTime >= dto.StartTime && x.CreationTime <= dto.EndTime)
         //    .WhereIF(dto.QueryType == 1, x => x.Status >= EOrderStatus.Filed && x.ExpiredTime < x.FiledTime) //业务已办超期
         //    //.WhereIF(dto.QueryType== 2,) //会签已办超期
         //    .WhereIF(dto.QueryType == 3, x => x.Status < EOrderStatus.Filed && x.ExpiredTime < SqlFunc.GetDate()) //业务待办超期
         //    //.WhereIF(dto.QueryType ==4,) //会签待办超期
-        //    .ToPageListAsync(dto.PageIndex, dto.PageSize);
-
+        //    .MergeTable();
+        //    //.ToPageListAsync(dto.PageIndex, dto.PageSize);
+
+          
+        //    var queryCountersign = _workflowCountersignRepository.Queryable()
+        //    .LeftJoin<WorkflowCountersignMember>((x, o) => x.Id == o.WorkflowCountersignId)
+        //    .Where( x => x.CreationTime >= dto.StartTime)
+        //    .Where( x => x.CreationTime <= dto.EndTime)
+        //    .MergeTable();
+
+        //    var query = queryOrder.LeftJoin(queryCountersign, (or, co) => or.Id == co.w)
+        //        .Select((or, co) => new OrderBiOrgDataListVo
+        //        {
+        //            OrgName = or.OrgName,
+        //            OrgId = or.OrgId,
+        //            HandlerExtendedNum = or.HandlerExtendedNum,
+        //            NoHandlerExtendedNum = or.NoHandlerExtendedNum,
+        //            CounterHandlerExtendedNum = co.CounterHandlerExtendedNum,
+        //            CounterNoHandlerExtendedNum = co.CounterNoHandlerExtendedNum
+        //        }).MergeTable();
         //}
 
 
@@ -117,19 +141,37 @@ namespace Hotline.Api.Controllers.Bi
 
             var IsCenter = _sessionContext.OrgIsCenter;
 
-            var queryOrder = _orderRepository.Queryable(false, false, false)
-                .LeftJoin<SystemOrganize>((x, o) => x.ActualHandleOrgCode == o.Id)
-                .WhereIF(dto.StartTime.HasValue, (x, o) => x.CreationTime >= dto.StartTime)
-                .WhereIF(dto.EndTime.HasValue, (x, o) => x.CreationTime <= dto.EndTime)
-                .WhereIF(IsCenter == false, (x, o) => x.ActualHandleOrgCode == _sessionContext.RequiredOrgId)
-                .GroupBy((x, o) => new { x.ActualHandleOrgCode, o.Name })
+
+            var queryOrder = _systemOrganizeRepository.Queryable()
+                .LeftJoin<Order>((x,o)=> x.Id == o.ActualHandleOrgCode)
+                .WhereIF(dto.StartTime.HasValue, (x, o) => o.CreationTime >= dto.StartTime)
+                .WhereIF(dto.EndTime.HasValue, (x, o) => o.CreationTime <= dto.EndTime)
+                .WhereIF(IsCenter == false, (x, o) => o.ActualHandleOrgCode == _sessionContext.RequiredOrgId)
+                .GroupBy((x,o) => new { x.Id, x.Name })
                 .Select((x, o) => new OrderBiOrgDataListVo
                 {
-                    OrgName = o.Name,
-                    OrgId = x.ActualHandleOrgCode,
-                    HandlerExtendedNum = SqlFunc.AggregateSum(SqlFunc.IIF(x.Status >= EOrderStatus.Filed && x.ExpiredTime < x.FiledTime, 1, 0)),
-                    NoHandlerExtendedNum = SqlFunc.AggregateSum(SqlFunc.IIF(x.Status < EOrderStatus.Filed && x.ExpiredTime < SqlFunc.GetDate(), 1, 0)),
+                    OrgName = x.Name,
+                    OrgId = x.Id,
+                    HandlerExtendedNum = SqlFunc.AggregateSum(SqlFunc.IIF(o.Status >= EOrderStatus.Filed && o.ExpiredTime < o.FiledTime, 1, 0)),
+                    NoHandlerExtendedNum = SqlFunc.AggregateSum(SqlFunc.IIF(o.Status < EOrderStatus.Filed && o.ExpiredTime < SqlFunc.GetDate(), 1, 0)),
                 }).MergeTable();
+
+
+
+            //var queryOrder = _orderRepository.Queryable(false, false, false)
+            //    .LeftJoin<SystemOrganize>((x, o) => x.ActualHandleOrgCode == o.Id)
+            //    .WhereIF(dto.StartTime.HasValue, (x, o) => x.CreationTime >= dto.StartTime)
+            //    .WhereIF(dto.EndTime.HasValue, (x, o) => x.CreationTime <= dto.EndTime)
+            //    .WhereIF(IsCenter == false, (x, o) => x.ActualHandleOrgCode == _sessionContext.RequiredOrgId)
+            //    .GroupBy((x, o) => new { x.ActualHandleOrgCode, o.Name })
+            //    .Select((x, o) => new OrderBiOrgDataListVo
+            //    {
+            //        OrgName = o.Name,
+            //        OrgId = x.ActualHandleOrgCode,
+            //        HandlerExtendedNum = SqlFunc.AggregateSum(SqlFunc.IIF(x.Status >= EOrderStatus.Filed && x.ExpiredTime < x.FiledTime, 1, 0)),
+            //        NoHandlerExtendedNum = SqlFunc.AggregateSum(SqlFunc.IIF(x.Status < EOrderStatus.Filed && x.ExpiredTime < SqlFunc.GetDate(), 1, 0)),
+            //    }).MergeTable();
+
             var queryCountersign = _workflowCountersignRepository.Queryable()
                 .LeftJoin<WorkflowCountersignMember>((x, o) => x.Id == o.WorkflowCountersignId)
                 .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
@@ -759,22 +801,59 @@ namespace Hotline.Api.Controllers.Bi
 
             bool IsCenter = _sessionContext.OrgIsCenter;
 
-            var list = await _orderVisitDetailRepository.Queryable()
+            var list = _orderVisitDetailRepository.Queryable()
                 .Where(x => x.OrderVisit.VisitTime >= StartDate && x.OrderVisit.VisitTime <= EndDate && x.VisitTarget == EVisitTarget.Org && x.OrderVisit.VisitState == EVisitState.Visited && !string.IsNullOrEmpty(x.VisitOrgCode))
                 .WhereIF(string.IsNullOrEmpty(OrgName) == false, x => x.VisitOrgName.Contains(OrgName))
                 .WhereIF(string.IsNullOrEmpty(LineNum) == false, x => x.OrderVisit.Order.CallRecord.Gateway.Contains(LineNum))
-                .WhereIF(IsCenter == false, x => x.VisitOrgCode.StartsWith(_sessionContext.OrgId))
-                .GroupByIF(IsCenter, x => new
+                .WhereIF(IsCenter == false, x => x.VisitOrgCode.StartsWith(_sessionContext.OrgId));
+
+            var data = new List<VisitAndOrgSatisfactionStatisticsDto>();
+
+            if (IsCenter && list != null)
+            {
+                data = await list.GroupBy(x => new
+                 {
+                     VisitOrgCode = x.VisitOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6"))
+                 })
+                .Select(x => new VisitAndOrgSatisfactionStatisticsDto()
                 {
-                    VisitOrgCode = x.VisitOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6"))
+                    OrgCode = x.VisitOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
+                    TotalSumCount = SqlFunc.AggregateCount(x.VisitOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6"))),
+                    VerySatisfiedCount = SqlFunc.IIF(TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "5", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "5", 1, 0))),//非常满意数
+                    SatisfiedCount = SqlFunc.IIF(TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "4", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "4", 1, 0))), //满意数
+                    RegardedAsSatisfiedCount = SqlFunc.IIF(TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "-1", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "-1", 1, 0))),//视为满意
+                    DefaultSatisfiedCount = SqlFunc.IIF(TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "0", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "0", 1, 0))),//默认满意
+                    NoSatisfiedCount = SqlFunc.IIF(TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2", 1, 0))),//不满意
+                    NoEvaluateCount = SqlFunc.IIF(TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "7", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "7", 1, 0))),//未做评价
+                    NoPutThroughCount = SqlFunc.IIF(TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "6", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "6", 1, 0))),//未接通
                 })
-                .GroupByIF(IsCenter == false, x => new
+                .MergeTable()
+                .LeftJoin<SystemOrganize>((it, o) => it.OrgCode == o.Id)
+                .Select((it, o) => new VisitAndOrgSatisfactionStatisticsDto()
                 {
-                    VisitOrgCode = x.VisitOrgCode
+                    OrgName = o.Name,
+                    OrgCode = it.OrgCode,
+                    OrgType = o.OrgType,
+                    TotalSumCount = it.TotalSumCount,
+                    VerySatisfiedCount = it.VerySatisfiedCount,//非常满意数
+                    SatisfiedCount = it.SatisfiedCount, //满意数
+                    RegardedAsSatisfiedCount = it.RegardedAsSatisfiedCount,//视为满意
+                    DefaultSatisfiedCount = it.DefaultSatisfiedCount,//默认满意
+                    NoSatisfiedCount = it.NoSatisfiedCount,//不满意
+                    NoEvaluateCount = it.NoEvaluateCount,//未做评价
+                    NoPutThroughCount = it.NoPutThroughCount,//未接通
                 })
+                .ToListAsync();
+            }
+            else
+            {
+                data = await list.GroupBy(x => new
+                 {
+                     x.VisitOrgCode
+                 })
                 .Select(x => new VisitAndOrgSatisfactionStatisticsDto()
                 {
-                    OrgCode = SqlFunc.IIF(IsCenter, x.VisitOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")), x.VisitOrgCode),
+                    OrgCode = x.VisitOrgCode,
                     TotalSumCount = SqlFunc.AggregateCount(x.VisitOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6"))),
                     VerySatisfiedCount = SqlFunc.IIF(TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "5", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "5", 1, 0))),//非常满意数
                     SatisfiedCount = SqlFunc.IIF(TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "4", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "4", 1, 0))), //满意数
@@ -801,48 +880,50 @@ namespace Hotline.Api.Controllers.Bi
                     NoPutThroughCount = it.NoPutThroughCount,//未接通
                 })
                 .ToListAsync();
+            }
+                
 
             var countySumModel = new VisitAndOrgSatisfactionStatisticsDto()
             {
                 OrgName = "区县合计",
-                TotalSumCount = list.Where(x => x.OrgType == EOrgType.County).Sum(x => x.TotalSumCount),
-                VerySatisfiedCount = list.Where(x => x.OrgType == EOrgType.County).Sum(x => x.VerySatisfiedCount),
-                SatisfiedCount = list.Where(x => x.OrgType == EOrgType.County).Sum(x => x.SatisfiedCount),
-                RegardedAsSatisfiedCount = list.Where(x => x.OrgType == EOrgType.County).Sum(x => x.RegardedAsSatisfiedCount),
-                DefaultSatisfiedCount = list.Where(x => x.OrgType == EOrgType.County).Sum(x => x.DefaultSatisfiedCount),
-                NoSatisfiedCount = list.Where(x => x.OrgType == EOrgType.County).Sum(x => x.NoSatisfiedCount),
-                NoEvaluateCount = list.Where(x => x.OrgType == EOrgType.County).Sum(x => x.NoEvaluateCount),
-                NoPutThroughCount = list.Where(x => x.OrgType == EOrgType.County).Sum(x => x.NoPutThroughCount),
+                TotalSumCount = data.Where(x => x.OrgType == EOrgType.County).Sum(x => x.TotalSumCount),
+                VerySatisfiedCount = data.Where(x => x.OrgType == EOrgType.County).Sum(x => x.VerySatisfiedCount),
+                SatisfiedCount = data.Where(x => x.OrgType == EOrgType.County).Sum(x => x.SatisfiedCount),
+                RegardedAsSatisfiedCount = data.Where(x => x.OrgType == EOrgType.County).Sum(x => x.RegardedAsSatisfiedCount),
+                DefaultSatisfiedCount = data.Where(x => x.OrgType == EOrgType.County).Sum(x => x.DefaultSatisfiedCount),
+                NoSatisfiedCount = data.Where(x => x.OrgType == EOrgType.County).Sum(x => x.NoSatisfiedCount),
+                NoEvaluateCount = data.Where(x => x.OrgType == EOrgType.County).Sum(x => x.NoEvaluateCount),
+                NoPutThroughCount = data.Where(x => x.OrgType == EOrgType.County).Sum(x => x.NoPutThroughCount),
             };
 
             var citySumModel = new VisitAndOrgSatisfactionStatisticsDto()
             {
                 OrgName = "市直合计",
-                TotalSumCount = list.Where(x => x.OrgType == EOrgType.City).Sum(x => x.TotalSumCount),
-                VerySatisfiedCount = list.Where(x => x.OrgType == EOrgType.City).Sum(x => x.VerySatisfiedCount),
-                SatisfiedCount = list.Where(x => x.OrgType == EOrgType.City).Sum(x => x.SatisfiedCount),
-                RegardedAsSatisfiedCount = list.Where(x => x.OrgType == EOrgType.City).Sum(x => x.RegardedAsSatisfiedCount),
-                DefaultSatisfiedCount = list.Where(x => x.OrgType == EOrgType.City).Sum(x => x.DefaultSatisfiedCount),
-                NoSatisfiedCount = list.Where(x => x.OrgType == EOrgType.City).Sum(x => x.NoSatisfiedCount),
-                NoEvaluateCount = list.Where(x => x.OrgType == EOrgType.City).Sum(x => x.NoEvaluateCount),
-                NoPutThroughCount = list.Where(x => x.OrgType == EOrgType.City).Sum(x => x.NoPutThroughCount),
+                TotalSumCount = data.Where(x => x.OrgType == EOrgType.City).Sum(x => x.TotalSumCount),
+                VerySatisfiedCount = data.Where(x => x.OrgType == EOrgType.City).Sum(x => x.VerySatisfiedCount),
+                SatisfiedCount = data.Where(x => x.OrgType == EOrgType.City).Sum(x => x.SatisfiedCount),
+                RegardedAsSatisfiedCount = data.Where(x => x.OrgType == EOrgType.City).Sum(x => x.RegardedAsSatisfiedCount),
+                DefaultSatisfiedCount = data.Where(x => x.OrgType == EOrgType.City).Sum(x => x.DefaultSatisfiedCount),
+                NoSatisfiedCount = data.Where(x => x.OrgType == EOrgType.City).Sum(x => x.NoSatisfiedCount),
+                NoEvaluateCount = data.Where(x => x.OrgType == EOrgType.City).Sum(x => x.NoEvaluateCount),
+                NoPutThroughCount = data.Where(x => x.OrgType == EOrgType.City).Sum(x => x.NoPutThroughCount),
             };
 
             var sumModel = new VisitAndOrgSatisfactionStatisticsDto()
             {
                 OrgName = "总计",
-                TotalSumCount = list.Sum(x => x.TotalSumCount),
-                VerySatisfiedCount = list.Sum(x => x.VerySatisfiedCount),
-                SatisfiedCount = list.Sum(x => x.SatisfiedCount),
-                RegardedAsSatisfiedCount = list.Sum(x => x.RegardedAsSatisfiedCount),
-                DefaultSatisfiedCount = list.Sum(x => x.DefaultSatisfiedCount),
-                NoSatisfiedCount = list.Sum(x => x.NoSatisfiedCount),
-                NoEvaluateCount = list.Sum(x => x.NoEvaluateCount),
-                NoPutThroughCount = list.Sum(x => x.NoPutThroughCount),
+                TotalSumCount = data.Sum(x => x.TotalSumCount),
+                VerySatisfiedCount = data.Sum(x => x.VerySatisfiedCount),
+                SatisfiedCount = data.Sum(x => x.SatisfiedCount),
+                RegardedAsSatisfiedCount = data.Sum(x => x.RegardedAsSatisfiedCount),
+                DefaultSatisfiedCount = data.Sum(x => x.DefaultSatisfiedCount),
+                NoSatisfiedCount = data.Sum(x => x.NoSatisfiedCount),
+                NoEvaluateCount = data.Sum(x => x.NoEvaluateCount),
+                NoPutThroughCount = data.Sum(x => x.NoPutThroughCount),
             };
 
 
-            return new VisitAndOrgSatisfactionStatisticsResultDto { DataList = list, CountySumModel = countySumModel, CitySumModel = citySumModel, SumModel = sumModel };
+            return new VisitAndOrgSatisfactionStatisticsResultDto { DataList = data, CountySumModel = countySumModel, CitySumModel = citySumModel, SumModel = sumModel };
         }
 
 
@@ -1771,20 +1852,70 @@ namespace Hotline.Api.Controllers.Bi
             return rsp;
         }
 
-        //      /// <summary>
-        //      /// 派单量统计// TODO
-        //      /// </summary>
-        //      /// <param name="dto"></param>
-        //      /// <returns></returns>
-        //      public async Task<PagedDto<BiOrderSendVo>> SendOrderReport([FromQuery] QuerySendOrderRequest dto) 
-        //      {
-        //       if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
-        //        throw UserFriendlyException.SameMessage("请选择时间!");
-        //       var (total, items) = await _workflowTraceRepository.Queryable()
-        //              .LeftJoin<Workflow>((x,w)=>x.)
-
-        //	return new PagedDto<BiOrderSendVo>(total, _mapper.Map<IReadOnlyList<BiOrderSendVo>>(items)); ;
-        //}
+		/// <summary>
+		/// 派单量统计
+		/// </summary>
+		/// <param name="dto"></param>
+		/// <returns></returns>
+		[HttpGet("send_order_report")]
+		public async Task<object> SendOrderReport([FromQuery] QuerySendOrderRequest dto)
+        {
+            if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
+                throw UserFriendlyException.SameMessage("请选择时间!");
+            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+			var items = await _workflowTraceRepository.Queryable()
+                .LeftJoin<Workflow>((x, w) => x.WorkflowId == w.Id)
+                .LeftJoin<WorkflowStepHandler>((x, w, wsh) => x.StepId == wsh.WorkflowStepId)
+                .InnerJoin<SchedulingUser>((x, w, wsh, su) => wsh.UserId == su.UserId)
+                .Where((x, w, wsh, su) => w.ModuleCode == "OrderHandle" && x.BusinessType == EBusinessType.Send)
+                .Where((x, w, wsh, su) =>x.CreationTime >= dto.StartTime.Value)
+                .Where((x, w, wsh, su) => x.CreationTime <= dto.EndTime.Value)
+                .WhereIF(!string.IsNullOrEmpty(dto.UserName),(x, w, wsh, su) => su.UserName == dto.UserName)
+				.GroupBy((x, w, wsh, su) => new { su.UserId, su.UserName})
+                .Having((x, w, wsh, su) => SqlFunc.AggregateCount(x.WorkflowId) == 1)
+                .Select((x, w, wsh, su) => new BiOrderSendVo
+                {
+                    UserId = su.UserId,
+                    UserName = su.UserName,
+                    SendOrderNum = SqlFunc.AggregateSum(SqlFunc.IIF(true, 1, 0)),
+                    NoSendOrderNum = SqlFunc.AggregateSum(SqlFunc.IIF(x.HandlerId == null || x.HandlerId == "", 1, 0)),
+                    ReSendOrderNum = 0,
+                }).ToListAsync();
+            var items2 =  await _workflowTraceRepository.Queryable()
+	            .LeftJoin<Workflow>((x, w) => x.WorkflowId == w.Id)
+	            .LeftJoin<WorkflowStepHandler>((x, w, wsh) => x.StepId == wsh.WorkflowStepId)
+	            .InnerJoin<SchedulingUser>((x, w, wsh, su) => wsh.UserId == su.UserId)
+	            .Where((x, w, wsh, su) => w.ModuleCode == "OrderHandle" && x.BusinessType == EBusinessType.Send)
+	            .Where((x, w, wsh, su) => x.CreationTime >= dto.StartTime.Value)
+	            .Where((x, w, wsh, su) => x.CreationTime <= dto.EndTime.Value)
+	            .WhereIF(!string.IsNullOrEmpty(dto.UserName), (x, w, wsh, su) => su.UserName == dto.UserName)
+				.GroupBy((x, w, wsh, su) => new { su.UserId, su.UserName })
+	            .Having((x, w, wsh, su) => SqlFunc.AggregateCount(x.WorkflowId) > 1)
+	            .Select((x, w, wsh, su) => new BiOrderSendVo
+	            {
+		            UserId = su.UserId,
+		            UserName = su.UserName,
+		            SendOrderNum = 0,
+		            NoSendOrderNum = 0,
+		            ReSendOrderNum = SqlFunc.AggregateSum(SqlFunc.IIF(true, 1, 0)),
+				}).ToListAsync();
+
+            var res = (from t1 in items
+	            join t2 in items2 on t1.UserId equals t2.UserId into t1_t2
+	            from item in t1_t2.DefaultIfEmpty()
+	            select new
+	            {
+		            UserId = t1.UserId,
+		            UserName = t1.UserName,
+		            SendOrderNum = t1.SendOrderNum,
+		            NoSendOrderNum = t1.NoSendOrderNum,
+                    ReSendOrderNum = t1_t2.Select(x => x.NoSendOrderNum).FirstOrDefault(),
+                    ChainRate = t1_t2.Select(x => x.NoSendOrderNum).FirstOrDefault() > 0 ?
+                              ((double.Parse(t1.SendOrderNum.ToString()) - double.Parse(t1_t2.Select(x => x.NoSendOrderNum).FirstOrDefault().ToString())) / double.Parse(t1.SendOrderNum.ToString()) * 100).ToString("F2") + "%" : "100.00%",
+                }).ToList();
+
+			return res; 
+        }
 
 
     }

+ 1 - 1
src/Hotline.Api/config/appsettings.Development.json

@@ -60,7 +60,7 @@
     }
   },
   "DatabaseConfiguration": {
-    "ApplyDbMigrations": true,
+    "ApplyDbMigrations": false,
     "ApplySeed": false
   },
   "MqConfiguration": {

+ 1 - 0
src/Hotline.Share/Dtos/Order/OrderBiDto.cs

@@ -454,6 +454,7 @@ namespace Hotline.Share.Dtos.Order
 
 	public class BiOrderSendVo
 	{
+		public string UserId { get; set; }
 		public string UserName { get; set; }
 
 		public int SendOrderNum { get; set; }

+ 14 - 3
src/Hotline.Share/Requests/PagedKeywordRequest.cs

@@ -35,11 +35,11 @@ public record OrgDataListDetailRequest:PagedRequest
 	/// <summary>
 	/// 开始时间
 	/// </summary>
-	public DateTime StartDate { get; set; }
+	public DateTime StartTime { get; set; }
 	/// <summary>
 	/// 结束时间
 	/// </summary>
-	public DateTime EndDate { get; set; }
+	public DateTime EndTime { get; set; }
 	/// <summary>
 	/// 部门Code
 	/// </summary>
@@ -152,8 +152,19 @@ public record QueryOrderReTransactDetailRequest : ReportPagedRequest
 
 }
 
-public record QuerySendOrderRequest : ReportPagedRequest
+public record QuerySendOrderRequest
 {
 	public string? UserName { get; set; }
 
+
+	/// <summary>
+	/// 开始时间
+	/// </summary>
+	public DateTime? StartTime { get; set; }
+
+	/// <summary>
+	/// 结束时间
+	/// </summary>
+	public DateTime? EndTime { get; set; }
+
 }

+ 5 - 0
src/Hotline/FlowEngine/Workflows/StepBasicEntity.cs

@@ -50,6 +50,11 @@ public abstract class StepBasicEntity : CreationEntity
     /// </summary>
     public EExpiredStatus? ExpiredStatus { get; set; }
 
+    /// <summary>
+    /// 节点办理状态
+    /// </summary>
+    public EWorkflowStepStatus Status { get; set; }
+
     #region 接办
 
     /// <summary>

+ 26 - 40
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -434,7 +434,7 @@ namespace Hotline.FlowEngine.Workflows
                     _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName,
                     _sessionContext.OrgLevel);
             }
-            
+
             //检查是否流转到流程终点
             if (nextStepDefine.StepType is EStepType.End)
             {
@@ -550,10 +550,10 @@ namespace Hotline.FlowEngine.Workflows
                 await DuplicateStepWithTraceAsync(workflow, prevStep, EWorkflowTraceStatus.Previous, cancellationToken);
 
             //remove workflow.steps
-            //await _workflowStepRepository.RemoveRangeAsync(removeSteps, cancellationToken);
-            await _workflowStepRepository.RemoveNav(removeSteps)
-                .Include(d => d.StepHandlers)
-                .ExecuteCommandAsync();
+            await _workflowStepRepository.RemoveRangeAsync(removeSteps, cancellationToken);
+            //await _workflowStepRepository.RemoveNav(removeSteps)
+            //    .Include(d => d.StepHandlers)
+            //    .ExecuteCommandAsync();
 
             if (workflow.Status is EWorkflowStatus.Completed)
                 workflow.SetStatusRunnable();
@@ -680,7 +680,7 @@ namespace Hotline.FlowEngine.Workflows
             await _workflowStepRepository.UpdateNav(steps)
                 .Include(d => d.WorkflowTrace)
                 .Include(d => d.Workflow)
-                .Include(d=>d.StepHandlers)
+                .Include(d => d.StepHandlers)
                 .ExecuteCommandAsync();
 
             return steps.Select(d => d.WorkflowId).ToList();
@@ -697,7 +697,7 @@ namespace Hotline.FlowEngine.Workflows
                                              d.StepHandlers.Any(d =>
                                                  !string.IsNullOrEmpty(d.OrgId) && d.OrgId.CheckIfOrgLevelIs(1)))
                 .Select(d => new Kv(d.StepHandlers.First().OrgId, d.StepHandlers.First().OrgName))
-				.ToList();
+                .ToList();
             return list.Where((x, i) => list.FindIndex(z => z.Key == x.Key) == i).ToList();
         }
 
@@ -1052,21 +1052,6 @@ namespace Hotline.FlowEngine.Workflows
             await _mediator.Publish(new CancelWorkflowNotify(workflow), cancellationToken);
         }
 
-        ///// <summary>
-        ///// 更新期满时间
-        ///// </summary>
-        //public async Task UpdateExpiredTimeAsync(Workflow workflow, DateTime expiredTime, string timelimit,
-        //    int? timelimiteCount,
-        //    ETimeType? timelimitUnit, DateTime nearlyExpiredTime, CancellationToken cancellationToken)
-        //{
-        //    workflow.ExpiredTime = expiredTime;
-        //    workflow.NearlyExpiredTime = nearlyExpiredTime;
-        //    workflow.TimeLimit = timelimit;
-        //    workflow.TimeLimitUnit = timelimitUnit;
-        //    workflow.TimeLimitCount = timelimiteCount;
-        //    await _workflowRepository.UpdateAsync(workflow, cancellationToken);
-        //}
-
         /// <summary>
         /// 新增流程流转记录
         /// </summary>
@@ -1297,8 +1282,7 @@ namespace Hotline.FlowEngine.Workflows
                     else
                     {
                         // csStartStep.prev
-                        var csStartStep =
-                            workflow.Steps.FirstOrDefault(d => d.Id == currentStep.CountersignStartStepId);
+                        var csStartStep = workflow.Steps.FirstOrDefault(d => d.Id == currentStep.CountersignStartStepId);
                         if (csStartStep is null)
                             throw new UserFriendlyException("未查询到会签节点");
 
@@ -1364,7 +1348,7 @@ namespace Hotline.FlowEngine.Workflows
                 _ => throw new ArgumentOutOfRangeException()
             };
 
-            return await CreateStepsAsync(workflow, nextStepDefine, prevStep, dto,
+            return await CreateStepsAsync(workflow, nextStepDefine, prevStep, dto, dto.IsStartCountersign,
                 flowAssignInfo.FlowAssignType, dto.NextHandlers, stepHandlers, null, EWorkflowStepStatus.WaitForAccept,
                 ECountersignPosition.None, false, EWorkflowTraceStatus.Normal, handlerType, expiredTime,
                 cancellationToken: cancellationToken);
@@ -1393,8 +1377,8 @@ namespace Hotline.FlowEngine.Workflows
                 _ => throw new ArgumentOutOfRangeException()
             };
 
-            return CreateStepsAsync(workflow, stepDefine, prevStep, dto, flowAssignType, dto.NextHandlers, stepHandlers,
-                countersignId, EWorkflowStepStatus.WaitForAccept, prevStep.GetNextStepCountersignPosition(),
+            return CreateStepsAsync(workflow, stepDefine, prevStep, dto, true, flowAssignType, dto.NextHandlers,
+                stepHandlers, countersignId, EWorkflowStepStatus.WaitForAccept, prevStep.GetNextStepCountersignPosition(),
                 false, EWorkflowTraceStatus.Normal, handlerType, expiredTime, cancellationToken: cancellationToken);
         }
 
@@ -1775,10 +1759,10 @@ namespace Hotline.FlowEngine.Workflows
             var removeSteps = GetStepsBehindTargetStep(workflow.Steps, targetStep);
             if (removeSteps.Any())
             {
-                //await _workflowStepRepository.RemoveRangeAsync(removeSteps, cancellationToken);
-                await _workflowStepRepository.RemoveNav(removeSteps)
-                    .Include(d => d.StepHandlers)
-                    .ExecuteCommandAsync();
+                await _workflowStepRepository.RemoveRangeAsync(removeSteps, cancellationToken);
+                //await _workflowStepRepository.RemoveNav(removeSteps)
+                //    .Include(d => d.StepHandlers)
+                //    .ExecuteCommandAsync();
                 workflow.Steps.RemoveAll(d => removeSteps.Contains(d));
             }
 
@@ -1790,7 +1774,7 @@ namespace Hotline.FlowEngine.Workflows
             var targetStepNew = targetIsStartStep
                 ? await CreateStartStepAsync(workflow, targetStepDefine, dto, dto.NextHandlers, stepHandlers, traceStatus, expiredTime,
                     cancellationToken)
-                : (await CreateStepsAsync(workflow, targetStepDefine, targetPrevStep, dto,
+                : (await CreateStepsAsync(workflow, targetStepDefine, targetPrevStep, dto, false,
                     flowAssignInfo.FlowAssignType, dto.NextHandlers, stepHandlers,
                     null, EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None, true, traceStatus,
                     null, expiredTime, cancellationToken: cancellationToken)).First();
@@ -1801,7 +1785,7 @@ namespace Hotline.FlowEngine.Workflows
 
             //calc workflow expired time
             var isOrgToCenter = CheckIfFlowFromOrgToCenter(workflow, targetStep);
-           
+
             return isOrgToCenter;
         }
 
@@ -1898,8 +1882,9 @@ namespace Hotline.FlowEngine.Workflows
                 }
             }
 
-            return await CreateStepsAsync(workflow, stepDefine, prevStep, dto, flowAssignInfo.FlowAssignType, handlers,
-                stepHandlers, null, EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None,
+            return await CreateStepsAsync(workflow, stepDefine, prevStep, dto, dto.IsStartCountersign,
+                flowAssignInfo.FlowAssignType, handlers, stepHandlers, null, 
+                EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None,
                 true, traceStatus, null, expiredTime, cancellationToken);
         }
 
@@ -1908,6 +1893,7 @@ namespace Hotline.FlowEngine.Workflows
             StepDefine stepDefine,
             WorkflowStep prevStep,
             BasicWorkflowDto dto,
+            bool isStartCountersign,
             EFlowAssignType? flowAssignType,
             List<Kv> handlers,
             List<WorkflowStepHandler> stepHandlers,
@@ -1922,7 +1908,7 @@ namespace Hotline.FlowEngine.Workflows
         )
         {
             List<WorkflowStep> steps = new();
-            if (dto.IsStartCountersign)
+            if (isStartCountersign)
             {
                 foreach (var handler in handlers)
                 {
@@ -2055,10 +2041,10 @@ namespace Hotline.FlowEngine.Workflows
 
                 HandleStepsByTerminalCs(startCountersignStep, workflow.Steps, workflow.Traces, ref updateSteps, ref updateTraces);
                 if (updateSteps.Any())
-                    //await _workflowStepRepository.RemoveRangeAsync(updateSteps, cancellationToken);
-                    await _workflowStepRepository.RemoveNav(updateSteps)
-                        .Include(d => d.StepHandlers)
-                        .ExecuteCommandAsync();
+                    await _workflowStepRepository.RemoveRangeAsync(updateSteps, cancellationToken);
+                //await _workflowStepRepository.RemoveNav(updateSteps)
+                //    .Include(d => d.StepHandlers)
+                //    .ExecuteCommandAsync();
                 if (updateTraces.Any())
                     await _workflowTraceRepository.UpdateRangeAsync(updateTraces, cancellationToken);
 

+ 5 - 10
src/Hotline/FlowEngine/Workflows/WorkflowStep.cs

@@ -28,11 +28,6 @@ public class WorkflowStep : StepBasicEntity
     /// </summary>
     public bool IsMain { get; set; }
 
-    /// <summary>
-    /// 节点办理状态
-    /// </summary>
-    public EWorkflowStepStatus Status { get; set; }
-
     /// <summary>
     /// 原生节点(区别动态生成)
     /// </summary>
@@ -52,11 +47,11 @@ public class WorkflowStep : StepBasicEntity
     /// </summary>
     public ECountersignPosition CountersignPosition { get; set; }
 
-    ///// <summary>
-    ///// 会签直属办理节点
-    ///// </summary>
-    //[SugarColumn(ColumnDataType = "json", IsJson = true)]
-    //public List<CountersignStep> CountersignSteps { get; set; } = new();
+    /// <summary>
+    /// 会签直属办理节点
+    /// </summary>
+    [SugarColumn(ColumnDataType = "json", IsJson = true)]
+    public List<CountersignStep>? CountersignSteps { get; set; } = new();
 
     /// <summary>
     /// 发起的会签是否汇总