using SJZY.Expand.AliyunOSS; using SJZY.Track.Application.Contract.Dtos.ProvideServices; using SJZY.Track.Application.Contract.Dtos.TrackOrder; using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.TrackContentAggregate; using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; using SJZY.Track.Domain.Aggregates.TrackPushAggregate; using SJZY.Track.Domain.Aggregates.TrackStatusAggregate; using SJZY.Track.Domain.Dtos.Order; namespace SJZY.Track.Application.Services.TrackOrders; /// /// 轨迹订单服务 /// [ApiExplorerSettings(GroupName = "轨迹订单")] [Route("/Track/Order")] public class TrackOrderService : ApplicationService { private readonly IOrderOperationRecordEsRepository _orderOperationRecordEsRepository; private readonly IOrderRepository _orderRepository; private readonly ITrackContentRepository _trackContentRepository; private readonly ITrackStatusRepository _trackStatusRepository; private readonly ITrackDetailsEsRepository _trackDetailsEsRepository; private readonly ITrackPushRecordEsRepository _trackPushRecordEsRepository; public TrackOrderService( IOrderRepository orderRepository, ITrackDetailsEsRepository trackDetailsEsRepository, ITrackContentRepository trackContentRepository, ITrackPushRecordEsRepository trackPushRecordEsRepository, IOrderOperationRecordEsRepository orderOperationRecordEsRepository, ITrackStatusRepository trackStatusRepository) { _orderRepository = orderRepository; _trackDetailsEsRepository = trackDetailsEsRepository; _trackContentRepository = trackContentRepository; _trackPushRecordEsRepository = trackPushRecordEsRepository; _orderOperationRecordEsRepository = orderOperationRecordEsRepository; _trackStatusRepository = trackStatusRepository; } #region 轨迹订单列表 /// /// 获取分页的轨迹订单 /// /// /// [HttpPost("GetTrackOrderList")] public async Task> GetTrackOrderPagedList(GetPageTrackOrderInput input) { var vo = ObjectMapper.Map(input); var pageList = await _orderRepository.GetTrackOrderPagedList(vo); var pageResultDto = ObjectMapper.Map, UnifyPageResultDto>(pageList); return pageResultDto; } #endregion /// /// 更新订单状态 /// /// /// /// [HttpPost("UpdateOrderStatus")] public async Task UpdateOrderStatus(UpdateOrderStatusInput input) { var order = await _orderRepository.GetFirstAsync(x => x.Id == input.OrderId); if (order == default) throw new BusinessException(message: "订单不存在"); order.IsCompleted = input.IsCompleted; return await _orderRepository.UpdateColumnAsync(order, x => new { x.IsCompleted }); } /// /// 获取轨迹推送记录 /// /// /// 订单id [HttpGet("GetTrackPushRecords")] public async Task> GetTrackPushRecordsAsync(int orderId) { var records = await _trackPushRecordEsRepository.GetTrackPushRecordsAsync(orderId); var res = ObjectMapper.Map, List>(records); res.ForEach(x => { int hours = (int) x.TrackTimeZone; // 提取整数部分作为小时 int minutes = (int) ((x.TrackTimeZone - hours) * 60); // 将小数部分乘以 60 转换为分钟 x.TrackGTMTimeZone = $"GTM {(x.TrackTimeZone >= 0 ? "+" : "-")}{new TimeSpan(hours, minutes, 0).ToString().RemovePostFix(":00")}"; }); return res; } /// /// 根据订单id获取轨迹明细列表 /// /// /// [HttpPost("GetDetails")] public async Task> GetTracksAsync(int orderId) { var subSystemId = await _orderRepository.GetFirstAsync(x => x.Id == orderId, x => x.SubSystemId); if (subSystemId == default) { throw new BusinessException(message: "订单不存在"); } var trackDetails = await _trackDetailsEsRepository.GetListAsync(orderId); if (trackDetails.IsNullOrEmpty()) { return new List(); } var list = ObjectMapper.Map, List>(trackDetails); var trackCodes = list.Select(x => x.Code) .Where(x => x != GlobalConst.EmptyString) .Distinct() .ToList(); // 是否对外 if (!trackCodes.IsNullOrEmpty()) { var trackContents = await _trackContentRepository.GetListAsync(x => x.SubSystemId == subSystemId && trackCodes.Contains(x.Code), x => new { x.Code, x.IsExternal }); list.ForEach(x => x.IsExternal = trackContents.FirstOrDefault(y => y.Code == x.Code)?.IsExternal ?? false); } // 计算时区 list.ForEach(a => { if (a.TrackTimeZoneValue == 0f) { a.TrackTimeZone = "GTM +00:00"; } else if (Math.Abs(a.TrackTimeZoneValue - GlobalConst.NoneTrackTimeZone) < 1) { a.TrackTimeZone = "--"; } else { // 将小数形式的小时转换为时区偏移量 var hours = (int) a.TrackTimeZoneValue; // 提取整数部分作为小时 var minutes = (int) ((a.TrackTimeZoneValue - hours) * 60); // 将小数部分乘以 60 转换为分钟 var offset = new TimeSpan(hours, minutes, 0); var timeZoneStr = offset.ToString(); var flag = a.TrackTimeZoneValue > 0f ? "+" : ""; a.TrackTimeZone = $"GTM {flag}{timeZoneStr.RemovePostFix(":00")}"; } }); return list; } /// /// 按时间轴获取轨迹内容 /// /// /// [HttpPost("GetDetailTimeline")] public async Task>> GetDetailTimeline(GetDetailTimelineInput input) { var res = new UnifyResultDto>(true); var order = await _orderRepository.GetFirstAsync(m => m.OrderNo == input.OrderNumber); if (order == null) return new UnifyResultDto>(false, "订单不存在"); if (input.SystemId <= 0) return new UnifyResultDto>(false, "子系统id不合法"); if (input.CurrenUserSystemId <= 0) return new UnifyResultDto>(false, "当前登陆用户子系统id不合法"); var system = await _orderRepository.GetSystemInfoById(input.CurrenUserSystemId); if (system == null) return new UnifyResultDto>(false, "未找到制定id的子系统"); var trackStatus = await _trackStatusRepository.GetListAsync(m => m.SubSystemId == input.SystemId); var trackDetails = await _trackDetailsEsRepository.GetListAsync(order.Id); res.Data = new List(); var isCompleted = false; foreach (var item in trackDetails) { var currentTrackStatus = trackStatus.FirstOrDefault(m => m.Code == item.TrackStatusCode); //是否完结 if (!isCompleted) isCompleted = currentTrackStatus is { IsCompleted: true }; //如果是内部系统,且轨迹内容不对外则跳过这条轨迹内容 if (system.SystemProperty == 1 && item.IsVisibility) continue; res.Data.Add(new GetDetailTimelineOutput() { IsHighlight = true, IsShowHover = true, Remark = item.Remarks == null || item.Remarks == "--" ? "" : item.Remarks, TrackTimeZone = $"GMT{(item.TrackTimeZone >= 0 ? "+" : "-")}{GetTimeZoneStr(item.TrackTimeZone)}", TrackTime = ToUnixTimestamp(item.TrackTime), TrackPlace = item.TrackPlace, EnContent = item.TrackEnContent, Files = item.Files == null ? new List() : item.Files!.Select(m => new TrackFileItem() { OssKey = m.OssKey, FileName = m.FileName, Url = m.OssKey.GetUrlByKey(), }).ToList(), Content = item.TrackContent, TrackCode = item.TrackCode, TrackPlaceNation = item.TrackPlaceNation, TrackPlaceProvince = item.TrackPlaceProvince, TrackPlaceCity = item.TrackPlaceCity, }); } //如果轨迹状态没完结则追加最后一个默认节点 if (!isCompleted) { res.Data.Add(new GetDetailTimelineOutput() { Content = "签收", IsHighlight = false, TrackTimeZone = order.EstimatedDeliveryDate.HasValue ? $"GMT{(order.DestinationTimeZone >= 0 ? "+" : "-")}{order.DestinationTimeZone}" : "", TrackTime = order.EstimatedDeliveryDate.HasValue ? ToUnixTimestamp(DateTime.Parse(order.EstimatedDeliveryDate.ToString()!)) : 0, TrackTimePrefix = order.EstimatedDeliveryDate.HasValue ? "预计签收时间:" : "", }); } return res; } public static long ToUnixTimestamp(DateTime time) { var sTime = TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1), TimeZoneInfo.Utc, TimeZoneInfo.Local); return (long) (time - sTime).TotalMilliseconds; } private string GetTimeZoneStr(float timeZone) { var time = timeZone.ToString().Split('.'); if (time.Length > 1 && time[1] != "0") //如果时区有小数点 { return time[0] + ":30"; } else { return time[0] + ":00"; } } /// /// 根据轨迹id删除单条轨迹 /// /// 轨迹id /// [HttpPost("DeleteTrackById")] public async Task DeleteTrackByIdAsync(string trackId) { var track = await _trackDetailsEsRepository.GetByIdAsync(trackId); // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract if (track == null) { throw new BusinessException(message: "轨迹不存在!"); } await _trackDetailsEsRepository.DeleteTrackByIdAsync(trackId, track.IndexName); return true; } /// /// 根据订单id查询订单操作记录 /// /// 订单id /// [HttpGet("GetOrderOperationsById")] public async Task> GetOrderOperationsByIdAsync(int orderId) { return await _orderOperationRecordEsRepository.GetOrderOperationsByIdAsync(orderId); } }