Jelajahi Sumber

信件来源统计列表 及明细

田爽 10 bulan lalu
induk
melakukan
4e9fe2dae8

+ 70 - 0
src/Hotline.Api/Controllers/Bi/BiOrderController.cs

@@ -29,6 +29,7 @@ using XF.Domain.Authentications;
 using XF.Domain.Constants;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
+using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
 
 namespace Hotline.Api.Controllers.Bi
 {
@@ -3293,7 +3294,76 @@ namespace Hotline.Api.Controllers.Bi
 				.Cast<object>()
 				.ToList();
 			var stream = ExcelHelper.CreateStream(dtos);
+			return ExcelStreamResult(stream, "信件来源统计数据");
+		}
+
+
+		/// <summary>
+		/// 信件来源统计列表
+		/// </summary>
+		/// <param name="dto"></param>
+		/// <returns></returns>
+		[HttpGet("order_source_report_list")]
+		public async Task<Object> QueryOrderSourceReportList([FromQuery] QueryOrderSourceRequest dto)
+		{
+			var data = await _orderApplication.QueryOrderSourceList(dto);
+            var header = await _orderApplication.QueryOrderSourceHeaderList(dto);
+			return new {Data =data, Header =header };
+		}
+		/// <summary>
+		/// 信件来源统计导出
+		/// </summary>
+		/// <returns></returns>
+		[HttpPost("order_source_list/_export")]
+		public async Task<FileStreamResult> QueryOrderSourceReportList([FromBody] ExportExcelDto<QueryOrderSourceRequest> dto)
+		{
+			var data = await _orderApplication.QueryOrderSourceList(dto.QueryDto);
+			dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+			var dtos = data
+				.Select(stu => _mapper.Map(stu, typeof(OrderSourceTimeVo), dynamicClass))
+				.Cast<object>()
+				.ToList();
+			var stream = ExcelHelper.CreateStream(dtos);
 			return ExcelStreamResult(stream, "信件来源统计列表数据");
 		}
+
+		/// <summary>
+		/// 信件来源统计明细
+		/// </summary>
+		/// <param name="dto"></param>
+		/// <returns></returns>
+		[HttpGet("order_source_report")]
+		public async Task<PagedDto<OrderDto>> QueryOrderSourceDetailReport([FromQuery] QueryOrderSourceDetailRequest dto)
+		{
+			var (total, items) = await _orderApplication.QueryOrderSourceDetail(dto).ToPagedListAsync(dto, HttpContext.RequestAborted);
+			return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
+		}
+		/// <summary>
+		/// 信件来源统计明细导出
+		/// </summary>
+		/// <returns></returns>
+		[HttpPost("order_source/_export")]
+		public async Task<FileStreamResult> QueryOrderSourceDetailReport([FromBody] ExportExcelDto<QueryOrderSourceDetailRequest> dto)
+		{
+			var query = _orderApplication.QueryOrderSourceDetail(dto.QueryDto);
+			List<Order> orders;
+			if (dto.IsExportAll)
+			{
+				orders = await query.ToListAsync(HttpContext.RequestAborted);
+			}
+			else
+			{
+				var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
+				orders = items;
+			}
+			var ordersDtos = _mapper.Map<ICollection<OrderDto>>(orders);
+			dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+			var dtos = ordersDtos
+				.Select(stu => _mapper.Map(stu, typeof(OrderDto), dynamicClass))
+				.Cast<object>()
+				.ToList();
+			var stream = ExcelHelper.CreateStream(dtos);
+			return ExcelStreamResult(stream, "信件来源统计明细数据");
+		}
 	}
 }

+ 20 - 0
src/Hotline.Application/Orders/IOrderApplication.cs

@@ -82,5 +82,25 @@ namespace Hotline.Application.Orders
         /// <returns></returns>
         ISugarQueryable<Order> QueryOrderSource(QueryOrderSourceRequest dto);
 
+		/// <summary>
+		/// 信件来源统计列表
+        /// </summary>
+		/// <param name="dto"></param>
+		/// <returns></returns>
+		Task<List<OrderSourceTimeVo>> QueryOrderSourceList(QueryOrderSourceRequest dto);
+
+        /// <summary>
+        /// 信件来源统计列表表头
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<List<OrderSourceHeaderVo>> QueryOrderSourceHeaderList(QueryOrderSourceRequest dto);
+
+        /// <summary>
+        /// 信件来源统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        ISugarQueryable<Order> QueryOrderSourceDetail(QueryOrderSourceDetailRequest dto);
 	}
 }

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

@@ -20,6 +20,7 @@ using Hotline.Share.Enums.Settings;
 using Hotline.Share.Requests;
 using Hotline.Tools;
 using MapsterMapper;
+using Novacode;
 using SqlSugar;
 using XF.Domain.Authentications;
 using XF.Domain.Constants;
@@ -466,7 +467,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             .WhereIF(dto.Level == 2, (x, ws) => ws.AcceptorOrgId.StartsWith(_sessionContext.OrgId))
             .WhereIF(dto.Signed == 0 ,(x,ws)=>ws.Status == Share.Enums.FlowEngine.EWorkflowStepStatus.WaitForAccept)
             .WhereIF(dto.Signed == 1, (x, ws) => ws.Status == Share.Enums.FlowEngine.EWorkflowStepStatus.WaitForHandle)
-            .Where((x,ws)=>ws.CountersignPosition ==  Share.Enums.FlowEngine.ECountersignPosition.None)
+            .Where((x,ws)=>ws.CountersignPosition ==  Share.Enums.FlowEngine.ECountersignPosition.None && x.Status > EOrderStatus.WaitForAccept)
 			.OrderByDescending((x,ws) => ws.CreationTime);
 	}
 
@@ -486,6 +487,75 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             .Where(d=> d.SourceChannel != null &&  d.SourceChannel !="");
 	}
 
+	/// <summary>
+	/// 信件来源统计列表
+	/// </summary>
+	/// <param name="dto"></param>
+	/// <returns></returns>
+	public async Task<List<OrderSourceTimeVo>> QueryOrderSourceList(QueryOrderSourceRequest dto)
+    {
+	    if (dto.EndTime.HasValue)
+		    dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+        var Time = await _orderRepository.Queryable()
+            .WhereIF(dto.StartTime.HasValue, d => d.CreationTime >= dto.StartTime)
+            .WhereIF(dto.EndTime.HasValue, d => d.CreationTime <= dto.EndTime)
+            .WhereIF(dto.IdentityType.HasValue, d => d.IdentityType == dto.IdentityType)
+            .Where(d => d.SourceChannel != null && d.SourceChannel != "")
+            .GroupBy(d=>  d.CreationTime.ToString("yyyy-MM-dd"))
+            .Select(d => new OrderSourceTimeVo { Time = d.CreationTime.ToString("yyyy-MM-dd") }).ToListAsync();
+        var data = await _orderRepository.Queryable()
+            .WhereIF(dto.StartTime.HasValue, d => d.CreationTime >= dto.StartTime)
+            .WhereIF(dto.EndTime.HasValue, d => d.CreationTime <= dto.EndTime)
+            .WhereIF(dto.IdentityType.HasValue, d => d.IdentityType == dto.IdentityType)
+            .Where(d => d.SourceChannel != null && d.SourceChannel != "")
+            .GroupBy(d => new { Time = d.CreationTime.ToString("yyyy-MM-dd"), d.SourceChannel })
+            .Select(d => new OrderSourceTimeListVo
+            {
+                Time = d.CreationTime.ToString("yyyy-MM-dd"),
+                Source = d.SourceChannel,
+                Num = SqlFunc.AggregateCount(d.Id)
+            }).ToListAsync() ;
+        foreach (var item in Time)
+        {
+	        List<OrderSourceTimeListVo> list = data.Where(x=>x.Time == item.Time).ToList();
+            item.Lists.AddRange(list);
+		}
+        return Time;
+	}
+
+	/// <summary>
+	/// 信件来源统计列表表头
+	/// </summary>
+	/// <param name="dto"></param>
+	/// <returns></returns>
+	public async Task<List<OrderSourceHeaderVo>> QueryOrderSourceHeaderList(QueryOrderSourceRequest dto) 
+    {
+		if (dto.EndTime.HasValue)
+			dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+		var list =  await _orderRepository.Queryable()
+			.WhereIF(dto.StartTime.HasValue, d => d.CreationTime >= dto.StartTime)
+			.WhereIF(dto.EndTime.HasValue, d => d.CreationTime <= dto.EndTime)
+			.WhereIF(dto.IdentityType.HasValue, d => d.IdentityType == dto.IdentityType)
+			.Where(d => d.SourceChannel != null && d.SourceChannel != "")
+			.GroupBy(d => d.SourceChannel)
+			.Select(d => new OrderSourceHeaderVo { Header = d.SourceChannel,Code = d.SourceChannel }).ToListAsync();
+		if (list.Count > 0)
+		{
+            list.Insert(0, new OrderSourceHeaderVo { Header = "小计",Code = "Subtotal" });
+            list.Insert(0, new OrderSourceHeaderVo { Header = "日期",Code = "Time" });
+		}
+        return list;
+	}
+
+    public ISugarQueryable<Order> QueryOrderSourceDetail(QueryOrderSourceDetailRequest dto) {
+		
+		return _orderRepository.Queryable()
+            .WhereIF(string.IsNullOrEmpty(dto.SourceChannel),d=>d.SourceChannel == dto.SourceChannel)
+            .WhereIF(dto.Time.HasValue,d=>d.CreationTime.ToString("yyyy-MM-dd") == dto.Time.Value.ToString("yyyy-MM-dd"))
+			.WhereIF(dto.IdentityType.HasValue, d => d.IdentityType == dto.IdentityType)
+			.Where(d => d.SourceChannel != null && d.SourceChannel != "");
+	}
+
 	#region private
 
 	/// <summary>

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

@@ -755,4 +755,54 @@ namespace Hotline.Share.Dtos.Order
 
 		public string RateText => GetRate() + "%";
 	}
+
+	public class OrderSourceHeaderVo {
+		/// <summary>
+		/// 来源渠道(电话、网站、APP等)
+		/// </summary>
+		public string? Header { get; set; }
+
+		public string? Code { get; set; }
+	}
+
+	public class OrderSourceTimeVo
+	{
+
+		/// <summary>
+		/// 日期
+		/// </summary>
+		public string Time { get; set; }
+
+		/// <summary>
+		/// 信件来源
+		/// </summary>
+		public string Source { get; set; }
+
+		/// <summary>
+		/// 小计
+		/// </summary>
+		public int Subtotal { get; set; }
+
+		public List<OrderSourceTimeListVo> Lists { get; set; }
+
+	}
+
+	public class OrderSourceTimeListVo
+	{
+		/// <summary>
+		/// 日期
+		/// </summary>
+		public string Time { get; set; }
+
+		/// <summary>
+		/// 信件来源
+		/// </summary>
+		public string Source { get; set; }
+
+		/// <summary>
+		/// 小计
+		/// </summary>
+		public int Num { get; set; }
+
+	}
 }

+ 19 - 1
src/Hotline.Share/Requests/PagedKeywordRequest.cs

@@ -225,4 +225,22 @@ public record QueryOrderSourceRequest : ReportPagedRequest
 	/// 来电/信人身份
 	/// </summary>
 	public EIdentityType? IdentityType { get; set; }
-}
+}
+
+public record QueryOrderSourceDetailRequest : QueryOrderSourceRequest
+{
+	/// <summary>
+	/// 来电/信人身份
+	/// </summary>
+	public EIdentityType? IdentityType { get; set; }
+
+	/// <summary>
+	/// 点击时间
+	/// </summary>
+	public DateTime? Time { get; set; }
+
+	/// <summary>
+	/// 来源渠道(电话、网站、APP等)
+	/// </summary>
+	public string? SourceChannel { get; set; }
+}