diff --git a/Entity/Api/Req/ChargeCountReq.cs b/Entity/Api/Req/ChargeCountReq.cs new file mode 100644 index 0000000..eddf3ad --- /dev/null +++ b/Entity/Api/Req/ChargeCountReq.cs @@ -0,0 +1,33 @@ +namespace Entity.Api.Req; + +/// +/// 用电量统计 +/// +public class ChargeCountReq +{ + /// + /// 时间类型 1:天 2:月 3:年 + /// + public int TimeType { get; set; } + + /// + /// 充电机编号 + /// + public string? ChargerNo { get; set; } + + /// + /// 开始时间 + /// + public DateTime? StartTime { get; set; } + + /// + /// 结束时间 + /// + public DateTime? EndTime { get; set; } + + /// 页码 + public int PageNum { get; set; } = 1; + + /// 页数 + public int PageSize { get; set; } = 10; +} \ No newline at end of file diff --git a/Entity/Api/Resp/ChargeCountResp.cs b/Entity/Api/Resp/ChargeCountResp.cs new file mode 100644 index 0000000..38f4c0b --- /dev/null +++ b/Entity/Api/Resp/ChargeCountResp.cs @@ -0,0 +1,20 @@ +namespace Entity.Api.Resp; +/// +/// 用电量统计结果返回 +/// +public class ChargeCountResp +{ + /// + /// 时间 + /// + public string? Time { get; set; } + /// + /// 充电度数 + /// + public decimal? ChargeCount { get; set; } + /// + /// 充电机编号 + /// + public string? ChargerNo { get; set; } + +} \ No newline at end of file diff --git a/Entity/Api/Resp/SwapMonitorScreenResp.cs b/Entity/Api/Resp/SwapMonitorScreenResp.cs index 5fa6714..e43c864 100644 --- a/Entity/Api/Resp/SwapMonitorScreenResp.cs +++ b/Entity/Api/Resp/SwapMonitorScreenResp.cs @@ -1,3 +1,4 @@ +using Entity.DbModel.Station; using Microsoft.AspNetCore.Mvc; namespace Entity.Api.Resp; @@ -26,4 +27,7 @@ public class SwapMonitorScreenResp /// 电池数据 /// public BinBatteryResp? BatteryInfo { get; set; } + + + } \ No newline at end of file diff --git a/Entity/Api/Resp/SwapOrderCountMonthResp.cs b/Entity/Api/Resp/SwapOrderCountMonthResp.cs new file mode 100644 index 0000000..989326c --- /dev/null +++ b/Entity/Api/Resp/SwapOrderCountMonthResp.cs @@ -0,0 +1,38 @@ +namespace Entity.Api.Resp; + +/// +/// 首页换电次数统计 +/// +public class SwapOrderCountMonthResp +{ + /// + /// 月换电总量 + /// + public int SwapCount { get; set; } + + /// + /// 月服务车辆 + /// + public int VehicleCount { get; set; } + + /// + /// 月充电次数 + /// + public int ChargeFrequency { get; set; } + + /// + /// 月充电量 + /// + public decimal? ChargeCount { get; set; } + + /// + /// 今日换电次数 + /// + public int DaySwapCount { get; set; } + + + /// + /// 今日充电量 + /// + public decimal? DayChargeCount { get; set; } +} \ No newline at end of file diff --git a/Entity/Api/Resp/SwapOrderCountResp.cs b/Entity/Api/Resp/SwapOrderCountResp.cs new file mode 100644 index 0000000..e15659b --- /dev/null +++ b/Entity/Api/Resp/SwapOrderCountResp.cs @@ -0,0 +1,20 @@ +namespace Entity.Api.Resp; + +/// +/// 每日换电订单统计 +/// +public class SwapOrderCountResp +{ + /// + /// 天 + /// + public int Day { get; set; } + /// + /// 换电数量 + /// + public int Count { get; set; } + /// + /// 充电度数 + /// + public decimal? ChargeCount { get; set; } +} \ No newline at end of file diff --git a/Entity/Api/Resp/SwapVehicleResp.cs b/Entity/Api/Resp/SwapVehicleResp.cs index cb6bd07..21b617b 100644 --- a/Entity/Api/Resp/SwapVehicleResp.cs +++ b/Entity/Api/Resp/SwapVehicleResp.cs @@ -1,3 +1,5 @@ +using Entity.DbModel.Station; + namespace Entity.Api.Resp; /// @@ -51,4 +53,25 @@ public class SwapVehicleResp /// 刹车状态 "0:未拉手刹1:已拉手刹 其它值无效" /// public byte? Break { get; set; } + + + /// + /// Desc:放电池仓位号 亏电包仓号 + /// Default: + /// Nullable:True + /// + public int? DownBatteryBinNo { get; set; } + + /// + /// Desc:取电池仓位号 满电包仓号 + /// Default: + /// Nullable:True + /// + public int? UpBatteryBinNo { get; set; } + + /// + /// 取放电池 + /// + public List? Battery { get; set; } + } \ No newline at end of file diff --git a/Entity/Dto/ChargeCountDto.cs b/Entity/Dto/ChargeCountDto.cs new file mode 100644 index 0000000..2f5a53d --- /dev/null +++ b/Entity/Dto/ChargeCountDto.cs @@ -0,0 +1,23 @@ +using Magicodes.ExporterAndImporter.Core; +using Magicodes.ExporterAndImporter.Excel; + +namespace Entity.Dto; + +/// +/// 充电量统计导出 +/// +[ExcelExporter(Name = "充电量统计", TableStyle = OfficeOpenXml.Table.TableStyles.None, AutoFitAllColumn = true)] +public class ChargeCountDto +{ + /// + /// 时间 + /// + [ExporterHeader(DisplayName = "时间", IsBold = true)] + public string? Time { get; set; } + + /// + /// 充电度数 + /// + [ExporterHeader(DisplayName = "用电量/kWh", IsBold = true)] + public decimal? ChargeCount { get; set; } +} \ No newline at end of file diff --git a/Service/Station/ChargeOrderService.cs b/Service/Station/ChargeOrderService.cs index 0483e0c..6d206d5 100644 --- a/Service/Station/ChargeOrderService.cs +++ b/Service/Station/ChargeOrderService.cs @@ -202,4 +202,336 @@ public class ChargeOrderService : BaseServices return QueryListByClause(predicate); } + + + public async Task> GetElectricityConsumptionByTime(ChargeCountReq req) + { + List list = await GetElectricityConsumption(req, false); + + list = list.OrderBy(x => x.Time).ToList(); + + return list; + } + + public async Task> GetElectricityConsumptionByChargerNo(ChargeCountReq req) + { + List resp = await GetElectricityConsumption(req, true); + resp = resp.OrderBy(x => x.Time).ToList(); + + int skip = (req.PageNum - 1) * req.PageSize; + int take = req.PageSize; + + List respList = resp.Skip(skip).Take(take).ToList(); + PageResult result = new PageResult(); + result.PageNum = req.PageNum; + result.PageSize = req.PageSize; + result.Rows = respList; + result.ToTal = resp.Count; + return result; + } + + + public async Task ExportElectricityChargerNoConsumption(ChargeCountReq req,string language) + { + // 查询订单 + List resp = await GetElectricityConsumptionExport(req, false); + if (resp.Count>0) + { + resp = resp.OrderBy(x => x.Time).ToList(); + } + var config = new MapperConfiguration(cfg => + { + cfg.CreateMap().ReverseMap(); + }); + IMapper mapper = config.CreateMapper(); + + if (language == "en") + { + List list2 = mapper.Map>(resp); + IExcelExporter excelExporter = new ExcelExporter(); + var res = await excelExporter.ExportAsByteArray(list2); + return new FileStreamResult(new MemoryStream(res), "application/octet-stream") + { FileDownloadName = DateTime.Now.ToString("yyyyMMddHHmm") + "_chargeCount.xlsx" }; + } + else + { + List list = mapper.Map>(resp); + IExcelExporter excelExporter = new ExcelExporter(); + var res = await excelExporter.ExportAsByteArray(list); + return new FileStreamResult(new MemoryStream(res), "application/octet-stream") + { FileDownloadName = DateTime.Now.ToString("yyyyMMddHHmm") + "充电量统计.xlsx" }; + } + } + + + public async Task> GetElectricityConsumption(ChargeCountReq req, + bool groupByChargerNo = false) + { + // 设置时间范围 + SetTime(req); + + Expression> predicate = x => x.EndTime >= req.StartTime && x.EndTime <= req.EndTime; + + if (!string.IsNullOrEmpty(req.ChargerNo)) + { + Expression> condition2Expr = u => u.ChargerNo == req.ChargerNo; + predicate = Expression.Lambda>( + Expression.AndAlso(predicate.Body, condition2Expr.Body), + predicate.Parameters[0]); + } + + List chargeOrders = await QueryListByClauseAsync(predicate); + + List result = new List(); + + if (req.TimeType == 1) + { + // 按小时分组统计 + if (groupByChargerNo) + { + // 按 ChargerNo 和小时分组 + result = chargeOrders + .Where(order => order.EndTime.HasValue && !string.IsNullOrEmpty(order.ChargerNo)) + .GroupBy(order => new { order.ChargerNo, Hour = order.EndTime.Value.Hour }) + .Select(group => new ChargeCountResp + { + ChargerNo = group.Key.ChargerNo, + Time = group.Key.Hour.ToString("00") + ":00", + ChargeCount = group.Sum(order => order.ElecCount ?? 0) + }) + .ToList(); + } + else + { + // 仅按小时分组 + result = chargeOrders + .Where(order => order.EndTime.HasValue) + .GroupBy(order => order.EndTime.Value.Hour) + .Select(group => new ChargeCountResp + { + Time = group.Key.ToString("00") + ":00", + ChargeCount = group.Sum(order => order.ElecCount ?? 0) + }) + .ToList(); + } + } + else if (req.TimeType == 2) + { + // 按天分组统计 + if (groupByChargerNo) + { + // 按 ChargerNo 和日期分组 + result = chargeOrders + .Where(order => order.EndTime.HasValue && !string.IsNullOrEmpty(order.ChargerNo)) + .GroupBy(order => new { order.ChargerNo, Date = order.EndTime.Value.Date }) + .Select(group => new ChargeCountResp + { + ChargerNo = group.Key.ChargerNo, + Time = group.Key.Date.ToString("yyyy-MM-dd"), + ChargeCount = group.Sum(order => order.ElecCount ?? 0) + }) + .ToList(); + } + else + { + // 仅按日期分组 + result = chargeOrders + .Where(order => order.EndTime.HasValue) + .GroupBy(order => order.EndTime.Value.Date) + .Select(group => new ChargeCountResp + { + Time = group.Key.ToString("yyyy-MM-dd"), + ChargeCount = group.Sum(order => order.ElecCount ?? 0) + }) + .ToList(); + } + } + else if (req.TimeType == 3) + { + // 按月分组统计 + if (groupByChargerNo) + { + // 按 ChargerNo、年和月分组 + result = chargeOrders + .Where(order => order.EndTime.HasValue && !string.IsNullOrEmpty(order.ChargerNo)) + .GroupBy(order => new { order.ChargerNo, order.EndTime.Value.Year, order.EndTime.Value.Month }) + .Select(group => new ChargeCountResp + { + ChargerNo = group.Key.ChargerNo, + Time = group.Key.Year + "-" + group.Key.Month.ToString("00"), + ChargeCount = group.Sum(order => order.ElecCount ?? 0) + }) + .ToList(); + } + else + { + // 仅按年和月分组 + result = chargeOrders + .Where(order => order.EndTime.HasValue) + .GroupBy(order => new { order.EndTime.Value.Year, order.EndTime.Value.Month }) + .Select(group => new ChargeCountResp + { + Time = group.Key.Year + "-" + group.Key.Month.ToString("00"), + ChargeCount = group.Sum(order => order.ElecCount ?? 0) + }) + .ToList(); + } + } + + return result; + } + + + public async Task> GetElectricityConsumptionExport(ChargeCountReq req, + bool groupByChargerNo = false) + { + // 设置时间范围 + SetTime(req); + + Expression> predicate = x => x.EndTime >= req.StartTime && x.EndTime <= req.EndTime; + + if (!string.IsNullOrEmpty(req.ChargerNo)) + { + Expression> condition2Expr = u => u.ChargerNo == req.ChargerNo; + predicate = Expression.Lambda>( + Expression.AndAlso(predicate.Body, condition2Expr.Body), + predicate.Parameters[0]); + } + + List chargeOrders = await QueryListByClauseAsync(predicate); + + List result = new List(); + + if (req.TimeType == 1) + { + // 按小时分组统计 + if (groupByChargerNo) + { + // 按 ChargerNo 和小时分组 + result = chargeOrders + .Where(order => order.EndTime.HasValue && !string.IsNullOrEmpty(order.ChargerNo)) + .GroupBy(order => new { order.ChargerNo, DateHour = order.EndTime.Value.ToString("yyyy-MM-dd HH") }) + .Select(group => new ChargeCountResp + { + ChargerNo = group.Key.ChargerNo, + Time = group.Key.DateHour + ":00", // 保留年月日和小时 + ChargeCount = group.Sum(order => order.ElecCount ?? 0) + }) + .ToList(); + } + else + { + // 仅按小时分组 + result = chargeOrders + .Where(order => order.EndTime.HasValue) + .GroupBy(order => order.EndTime.Value.ToString("yyyy-MM-dd HH")) + .Select(group => new ChargeCountResp + { + Time = group.Key + ":00", // 保留年月日和小时 + ChargeCount = group.Sum(order => order.ElecCount ?? 0) + }) + .ToList(); + } + } + else if (req.TimeType == 2) + { + // 按天分组统计 + if (groupByChargerNo) + { + // 按 ChargerNo 和日期分组 + result = chargeOrders + .Where(order => order.EndTime.HasValue && !string.IsNullOrEmpty(order.ChargerNo)) + .GroupBy(order => new { order.ChargerNo, Date = order.EndTime.Value.Date }) + .Select(group => new ChargeCountResp + { + ChargerNo = group.Key.ChargerNo, + Time = group.Key.Date.ToString("yyyy-MM-dd"), + ChargeCount = group.Sum(order => order.ElecCount ?? 0) + }) + .ToList(); + } + else + { + // 仅按日期分组 + result = chargeOrders + .Where(order => order.EndTime.HasValue) + .GroupBy(order => order.EndTime.Value.Date) + .Select(group => new ChargeCountResp + { + Time = group.Key.ToString("yyyy-MM-dd"), + ChargeCount = group.Sum(order => order.ElecCount ?? 0) + }) + .ToList(); + } + } + else if (req.TimeType == 3) + { + // 按月分组统计 + if (groupByChargerNo) + { + // 按 ChargerNo、年和月分组 + result = chargeOrders + .Where(order => order.EndTime.HasValue && !string.IsNullOrEmpty(order.ChargerNo)) + .GroupBy(order => new { order.ChargerNo, order.EndTime.Value.Year, order.EndTime.Value.Month }) + .Select(group => new ChargeCountResp + { + ChargerNo = group.Key.ChargerNo, + Time = group.Key.Year + "-" + group.Key.Month.ToString("00"), + ChargeCount = group.Sum(order => order.ElecCount ?? 0) + }) + .ToList(); + } + else + { + // 仅按年和月分组 + result = chargeOrders + .Where(order => order.EndTime.HasValue) + .GroupBy(order => new { order.EndTime.Value.Year, order.EndTime.Value.Month }) + .Select(group => new ChargeCountResp + { + Time = group.Key.Year + "-" + group.Key.Month.ToString("00"), + ChargeCount = group.Sum(order => order.ElecCount ?? 0) + }) + .ToList(); + } + } + + return result; + } + + + private static void SetTime(ChargeCountReq req) + { + if (req.StartTime.HasValue && req.EndTime.HasValue) + { + return ; + } + + if (req.TimeType < 1 || req.TimeType > 3) + { + // 时间类型传值错误 + throw new ArgumentException("时间类型传值错误"); + } + if (req.TimeType == 1) + { + // 今天的开始时间 + req.StartTime = DateTime.Today; + // 今天的结束时间 + req.EndTime = DateTime.Today.AddDays(1).AddSeconds(-1); + } + else if (req.TimeType == 2) + { + // 本月的开始时间 + req.StartTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1); + // 本月的结束时间 下个月减1秒 + req.EndTime = req.StartTime.Value.AddMonths(1).AddSeconds(-1); + } + else if (req.TimeType == 3) + { + // 今年的开始时间 + req.StartTime = new DateTime(DateTime.Now.Year, 1, 1); + // 今年的结束时间 明年减1秒 + req.EndTime = req.StartTime.Value.AddYears(1).AddSeconds(-1); + } + } } diff --git a/Service/Station/SwapOrderService.cs b/Service/Station/SwapOrderService.cs index a264f59..ce09724 100644 --- a/Service/Station/SwapOrderService.cs +++ b/Service/Station/SwapOrderService.cs @@ -23,6 +23,8 @@ public class SwapOrderService : BaseServices public SwapOrderRepository swapOrderRepository { get; set; } public SwapOrderReportCloudRepository SwapOrderReportCloudRepository { get; set; } + public ChargeOrderRepository ChargeOrderRepository { get; set; } + public SwapOrderMgr SwapOrderMgr { get; set; } public SwapOrderService(SwapOrderRepository dal) @@ -191,4 +193,138 @@ public class SwapOrderService : BaseServices return QueryListByClause(predicate); } + + + /// + /// 获取当前月份每一天的换电订单数量统计 + /// + /// 返回包含日期和对应订单数量的列表 + public async Task> GetDaySwapOrderCount() + { + DateTime now = DateTime.Now; + int year = now.Year; + int month = now.Month; + // 这个月的开始时间 + DateTime firstDayOfMonth = new DateTime(year, month, 1); + // 这个月的最后一秒 + DateTime lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddSeconds(-1); + + // 查询换电订单 + List swapOrders = await BaseDal.Queryable() + .Where(order => order.SwapEndTime >= firstDayOfMonth && order.SwapEndTime <= lastDayOfMonth) + .ToListAsync(); + + // 查询充电订单 + List chargeOrders = await ChargeOrderRepository.Queryable() + .Where(order => order.EndTime >= firstDayOfMonth && order.EndTime <= lastDayOfMonth) + .ToListAsync(); + + // 获取这个月的天数 + int daysInMonth = DateTime.DaysInMonth(year, month); + + // 生成天数的列表 + List dayList = Enumerable.Range(1, daysInMonth).ToList(); + + // 根据天分组、统计分组数量 + var swapOrderCounts = swapOrders + .Where(order => order.SwapEndTime.HasValue) + .GroupBy(order => order.SwapEndTime.Value.Day) + .Select(group => new + { + Day = group.Key, + Count = group.Count() + }) + .ToList(); + + // 根据天分组、统计充电量 + var chargeOrderCounts = chargeOrders + .Where(order => order.EndTime.HasValue) + .GroupBy(order => order.EndTime.Value.Day) + .Select(group => new + { + Day = group.Key, + ChargeCount = group.Sum(order => order.ElecCount ?? 0) + }) + .ToList(); + + List dailyOrderCounts = dayList.Select(day => new SwapOrderCountResp + { + Day = day, + Count = swapOrderCounts.FirstOrDefault(oc => oc.Day == day)?.Count ?? 0, + ChargeCount = chargeOrderCounts.FirstOrDefault(cc => cc.Day == day)?.ChargeCount ?? 0 + }).ToList(); + + return dailyOrderCounts; + } + + /// + /// 查询月换电次数、换电车辆、充电统计 + /// + /// + public async Task GetMonthSwapOrderCount() + { + DateTime now = DateTime.Now; + int year = now.Year; + int month = now.Month; + + // 本月的开始时间 (00:00:00) 和最后一秒 (23:59:59) + DateTime firstDayOfMonth = new DateTime(year, month, 1); + DateTime lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddSeconds(-1); + + // 查询本月换电订单 + List swapOrders = await GetSwapOrdersInRange(firstDayOfMonth, lastDayOfMonth); + + // 查询本月充电订单 + List chargeOrders = await GetChargeOrdersInRange(firstDayOfMonth, lastDayOfMonth); + + SwapOrderCountMonthResp resp = new SwapOrderCountMonthResp + { + // 本月换电订单总数 + SwapCount = swapOrders.Count, + + VehicleCount = swapOrders + .Where(order => !string.IsNullOrEmpty(order.VehicleNo)) + .Select(order => order.VehicleNo) + .Distinct() + .Count(), + // 本月充电订单总数 + ChargeFrequency = chargeOrders.Count, + + // 本月充电电量总和 + ChargeCount = chargeOrders + .Where(order => order.ElecCount.HasValue) + .Sum(order => order.ElecCount ?? 0) + }; + + // 获取今天的开始时间和最后一秒 + DateTime todayStart = DateTime.Today; + DateTime todayEnd = todayStart.AddDays(1).AddSeconds(-1); + + // 查询当天换电订单 + List daySwapOrder = await GetSwapOrdersInRange(todayStart, todayEnd); + + // 查询当天充电订单 + List dayChargeOrder = await GetChargeOrdersInRange(todayStart, todayEnd); + + resp.DaySwapCount = daySwapOrder.Count; + resp.DayChargeCount = dayChargeOrder + .Where(order => order.ElecCount.HasValue) + .Sum(order => order.ElecCount ?? 0); + + return resp; + } + + private async Task> GetSwapOrdersInRange(DateTime startTime, DateTime endTime) + { + return await BaseDal.Queryable() + .Where(order => order.SwapEndTime >= startTime && order.SwapEndTime <= endTime) + .ToListAsync(); + } + + private async Task> GetChargeOrdersInRange(DateTime startTime, DateTime endTime) + { + return await ChargeOrderRepository.Queryable() + .Where(order => order.EndTime >= startTime && order.EndTime <= endTime) + .ToListAsync(); + } } \ No newline at end of file diff --git a/WebStarter/Controllers/HomeController.cs b/WebStarter/Controllers/HomeController.cs new file mode 100644 index 0000000..c18b71e --- /dev/null +++ b/WebStarter/Controllers/HomeController.cs @@ -0,0 +1,87 @@ +using Entity.Api.Req; +using Entity.Api.Resp; +using HybirdFrameworkCore.Entity; +using Microsoft.AspNetCore.Mvc; +using Service.Station; + +namespace WebStarter.Controllers; + +/// +/// 首页统计 +/// +[ApiController] +[Route("api/[controller]")] +public class HomeController : ControllerBase +{ + private readonly SwapOrderService _swapOrderService; + private readonly ChargeOrderService _chargeOrderService; + + /// + /// 注入 + /// + /// + /// + public HomeController(SwapOrderService swapOrderService + ,ChargeOrderService chargeOrderService + ) + { + _swapOrderService = swapOrderService; + _chargeOrderService = chargeOrderService; + } + + /// + /// 统计当月的每一天换电数量、充电量 + /// + /// + [HttpGet("GetDaySwapOrderCount")] + public async Task>> GetDaySwapOrderCount() + { + return Result>.Success(await _swapOrderService.GetDaySwapOrderCount(), "成功"); + } + + /// + /// 查询月换电次数、换电车辆、充电统计 + /// + /// + [HttpGet("GetMonthSwapOrderCount")] + public async Task> GetMonthSwapOrderCount() + { + return Result.Success(await _swapOrderService.GetMonthSwapOrderCount(), "成功"); + } + + /// + /// 用电量查询 + /// + /// + /// + [HttpPost("GetElectricityConsumption")] + public async Task>> GetElectricityConsumption([FromBody] ChargeCountReq req) + { + return Result>.Success(await _chargeOrderService.GetElectricityConsumptionByTime(req), "成功"); + } + + /// + /// 用电量查询、根据充电机分组 + /// + /// + /// + [HttpPost("GetElectricityChargerNoConsumption")] + public async Task>> GetElectricityChargerNoConsumption([FromBody] ChargeCountReq req) + { + return Result>.Success(await _chargeOrderService.GetElectricityConsumptionByChargerNo(req), "成功"); + } + + /// + /// 充电量导出 + /// + /// + /// + [HttpPost] + [Route("export")] + public async Task ExportSwapOrder([FromBody] ChargeCountReq req) + { + // 获取请求头中的语言信息 + var language = Request.Headers["Accept-Language"].ToString().ToLower(); + return await _chargeOrderService.ExportElectricityChargerNoConsumption(req,language); + } +} \ No newline at end of file