diff --git a/src/SJZY.Track.Application.Contract/Dtos/TrackPull/EditTrackPullContentInput.cs b/src/SJZY.Track.Application.Contract/Dtos/TrackPull/EditTrackPullContentInput.cs index 1342b38b..24882e20 100644 --- a/src/SJZY.Track.Application.Contract/Dtos/TrackPull/EditTrackPullContentInput.cs +++ b/src/SJZY.Track.Application.Contract/Dtos/TrackPull/EditTrackPullContentInput.cs @@ -52,8 +52,14 @@ public class EditTrackPullContentInput /// /// 轨迹时区GMT /// + [Obsolete] public double? TrackTimeZone { get; set; } + /// + /// 兜底轨迹时区发生地 + /// + public int? TrackTimePlaceValue { get; set; } + /// /// 是否完结 /// diff --git a/src/SJZY.Track.Application.Contract/Dtos/TrackPull/TrackPullContentConfigDto.cs b/src/SJZY.Track.Application.Contract/Dtos/TrackPull/TrackPullContentConfigDto.cs index 771b328c..a7f2c500 100644 --- a/src/SJZY.Track.Application.Contract/Dtos/TrackPull/TrackPullContentConfigDto.cs +++ b/src/SJZY.Track.Application.Contract/Dtos/TrackPull/TrackPullContentConfigDto.cs @@ -37,13 +37,13 @@ public class TrackPullContentConfigDto /// public int? TrackPlaceValue { get; set; } - /// - /// 轨迹时区GMT值 - /// - public float? TrackTimeZoneValue { get; set; } - /// /// 订单是否完成(由轨迹刷新配置决定) /// public bool IsCompleted { get; set; } + + /// + /// 轨迹时区发生地参数值 + /// + public int? TrackZonePlaceValue { get; set; } } \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Events/PullChangeBottomLineUpdateOrderEvent.cs b/src/SJZY.Track.Application.Contract/Events/PullChangeBottomLineUpdateOrderEvent.cs new file mode 100644 index 00000000..ed59fce6 --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Events/PullChangeBottomLineUpdateOrderEvent.cs @@ -0,0 +1,11 @@ +namespace SJZY.Track.Application.Contract.Events; + +public class PullChangeBottomLineUpdateOrderEvent +{ + public List OrderIds { get; set; } = null!; + + /// + /// 时区缺失和发生地缺失标记,1表示时区,2表示发生地,3表示两种 + /// + public int DeficiencyTagValue { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/CAP/EventHandlers/PullChangeBottomLineUpdateOrderEventHandler.cs b/src/SJZY.Track.Application/CAP/EventHandlers/PullChangeBottomLineUpdateOrderEventHandler.cs new file mode 100644 index 00000000..0365727d --- /dev/null +++ b/src/SJZY.Track.Application/CAP/EventHandlers/PullChangeBottomLineUpdateOrderEventHandler.cs @@ -0,0 +1,23 @@ +using DotNetCore.CAP; +using SJZY.Track.Application.Contract.Events; +using SJZY.Track.Domain.Aggregates.OrderAggregate; +using SJZY.Track.Domain.Consts; +using Volo.Abp.DependencyInjection; + +namespace SJZY.Track.Application.CAP.EventHandlers; + +public class PullChangeBottomLineUpdateOrderEventHandler :ITransientDependency, ICapSubscribe +{ + private readonly IOrderRepository _orderRepository; + + public PullChangeBottomLineUpdateOrderEventHandler(IOrderRepository orderRepository) + { + _orderRepository = orderRepository; + } + + [CapSubscribe(GlobalConst.PullChangeBottomLineUpdateOrderSubscribe)] + public async Task ConsumerAsync(PullChangeBottomLineUpdateOrderEvent @event) + { + await _orderRepository.UpdateBatchIdsAsync(@event.OrderIds, @event.DeficiencyTagValue); + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/CAP/EventHandlers/TrackRefreshEventHandler.cs b/src/SJZY.Track.Application/CAP/EventHandlers/TrackRefreshEventHandler.cs index f982343e..26380b66 100644 --- a/src/SJZY.Track.Application/CAP/EventHandlers/TrackRefreshEventHandler.cs +++ b/src/SJZY.Track.Application/CAP/EventHandlers/TrackRefreshEventHandler.cs @@ -12,6 +12,7 @@ using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; using SJZY.Track.Domain.Consts; using SJZY.Track.Domain.Enums; +using SJZY.Track.Domain.Queries; using Volo.Abp.DependencyInjection; namespace SJZY.Track.Application.CAP.EventHandlers; @@ -22,15 +23,17 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe private readonly ICapPublisher _capPublisher; private readonly ITrackPullCacheService _trackPullCacheService; private readonly ITrackDetailsRepository _trackDetailsRepository; + private readonly ITimezoneQueries _timezoneQueries; public TrackRefreshEventHandler(IOrderRepository orderRepository, ICapPublisher capPublisher, ITrackPullCacheService trackPullCacheService, - ITrackDetailsRepository trackDetailsRepository) + ITrackDetailsRepository trackDetailsRepository, ITimezoneQueries timezoneQueries) { _orderRepository = orderRepository; _capPublisher = capPublisher; _trackPullCacheService = trackPullCacheService; _trackDetailsRepository = trackDetailsRepository; + _timezoneQueries = timezoneQueries; } [CapSubscribe(GlobalConst.TrackRefreshSubscribe, Group = GlobalConst.TrackRefreshSubscribe)] @@ -172,21 +175,12 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe var trackPlace = paramConfig.TrackPlaceName == null ? null : trackToken[paramConfig.TrackPlaceName]?.Value(); - if (trackPlace.IsNullOrWhiteSpace()) + var hasPlaceBottomLine = false; //执行了兜底但是没有兜底住,需要记录 + if (trackPlace.IsNullOrWhiteSpace() && matchedContentConfig?.TrackPlaceValue != null && matchedContentConfig.TrackPlaceValue.HasValue) { - Expression> resultExpression = - (TrackLocationValue?)matchedContentConfig?.TrackPlaceValue switch - { - TrackLocationValue.ArrivalPort => x => x.ArrivalPort, - TrackLocationValue.ArriveCity => x => x.ArrivalCity, - TrackLocationValue.ArrivalCountry => x => x.ArrivalCountry, - TrackLocationValue.LeavePort => x => x.LeavePort, - TrackLocationValue.LeaveCity => x => x.LeaveCity, - TrackLocationValue.LeaveCountry => x => x.LeaveCountry, - _ => x => x.LeaveCountry - }; - trackPlace = await _orderRepository.GetFirstAsync(x => - x.Id == context.OrderId, resultExpression); + //兜底没配置的就不需要兜底,拉取的发生地没就没 + trackPlace = await GetPlaceByOrder(matchedContentConfig!.TrackPlaceValue.Value,context.OrderId); + hasPlaceBottomLine = string.IsNullOrWhiteSpace(trackPlace); } // 轨迹发生时间 @@ -198,6 +192,17 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe ? null : trackToken[paramConfig.TrackTimeZoneName]?.Value(); + //兜底时区 + var hasTimezoneBottomLine = false; //执行了兜底但是没有兜底住,需要记录 + if (!trackTimeZone.HasValue && matchedContentConfig?.TrackZonePlaceValue != null && matchedContentConfig.TrackZonePlaceValue.HasValue) + { + //兜底没配置的就不需要兜底,拉取的发生地没就没 + var timezone= await GetTimezone(matchedContentConfig,context.OrderId); + + trackTimeZone = timezone; + hasTimezoneBottomLine = !timezone.HasValue; + } + if (matchedContentConfig is null) { var notMappedEvent = new TrackInsertForNotMappedEvent @@ -209,7 +214,7 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe OriginTrackData = JsonConvert.SerializeObject(trackToken), TrackPlace = trackPlace ?? GlobalConst.EmptyString, TrackTime = trackTime ?? DateTime.Now, - TrackTimeZone = trackTimeZone ?? matchedContentConfig?.TrackTimeZoneValue ?? 8 + TrackTimeZone = trackTimeZone ?? 8 }; if (paramConfig.TrackContentName != null) { @@ -246,11 +251,74 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe TrackCode = matchedContentConfig.TrackContentCode, TrackPlace = trackPlace ?? GlobalConst.EmptyString, TrackTime = trackTime ?? DateTime.Now, - TrackTimeZone = trackTimeZone ?? matchedContentConfig.TrackTimeZoneValue ?? 8 + TrackTimeZone = trackTimeZone ?? 8 }; trackUpsertEvent.IsAdd = !await _trackDetailsRepository.AnyByCodeAsync(context.OrderId, matchedContentConfig.TrackContentCode); await _capPublisher.PublishAsync(GlobalConst.TrackUpsertForRefreshSubscribe, trackUpsertEvent); + + // 触发了兜底,但是没有兜底住,对订单进行标记 + if (hasPlaceBottomLine || hasTimezoneBottomLine) + { + //1表示时区,2表示发生地,3表示两种 + var placeTagValue = hasPlaceBottomLine ? 2 : 0; + var timezoneTagValue = hasTimezoneBottomLine ? 1 : 0; + PullChangeBottomLineUpdateOrderEvent deficiencyTagEvent = new PullChangeBottomLineUpdateOrderEvent + { + OrderIds = new List(){context.OrderId}, + DeficiencyTagValue = placeTagValue+timezoneTagValue + }; + await _capPublisher.PublishAsync(GlobalConst.PullChangeBottomLineUpdateOrderSubscribe, deficiencyTagEvent); + } + } + + /// + /// 根据订单id获取兜底位置 + /// + /// + /// + /// + private Task GetPlaceByOrder(int trackValue,int orderId) + { + Expression> resultExpression = + (TrackLocationValue)trackValue switch + { + TrackLocationValue.ArrivalPort => x => x.ArrivalPort, + TrackLocationValue.ArriveCity => x => x.ArrivalCity, + TrackLocationValue.ArrivalCountry => x => x.ArrivalCountry, + TrackLocationValue.LeavePort => x => x.LeavePort, + TrackLocationValue.LeaveCity => x => x.LeaveCity, + TrackLocationValue.LeaveCountry => x => x.LeaveCountry, + _ => x => x.LeaveCountry + }; + return _orderRepository.GetFirstAsync(x => x.Id == orderId, resultExpression); + } + + /// + /// 获取时区 + /// + /// + /// + /// + private async Task GetTimezone(TrackPullContentConfigDto matchedContentConfig,int orderId ) + { + var placeOrCode = await GetPlaceByOrder(matchedContentConfig!.TrackZonePlaceValue.Value,orderId); + string timezone = null; + if (!string.IsNullOrEmpty(placeOrCode)) + { + + if (matchedContentConfig!.TrackZonePlaceValue.Value == (int)TrackLocationValue.ArrivalPort + || matchedContentConfig!.TrackZonePlaceValue.Value == (int)TrackLocationValue.LeavePort) + { + timezone = await _timezoneQueries.GetPortTimezone(placeOrCode); + return DateTimeHelper.ConvertTimeZoneToFloat(timezone); + } + + timezone = await _timezoneQueries.GetCityTimezone(placeOrCode); + return DateTimeHelper.ConvertTimeZoneToFloat(timezone); + } + + return null; } } \ No newline at end of file diff --git a/src/SJZY.Track.Application/Helpers/DateTimeHelper.cs b/src/SJZY.Track.Application/Helpers/DateTimeHelper.cs index 907cab70..afc41d27 100644 --- a/src/SJZY.Track.Application/Helpers/DateTimeHelper.cs +++ b/src/SJZY.Track.Application/Helpers/DateTimeHelper.cs @@ -36,4 +36,25 @@ public static class DateTimeHelper //时区是整数丢掉浮点数部分 return format.Replace("hh", ((int)timezone).ToString()); } + + /// + /// 转换主数据中心类似GMT-09:00这种的时区为浮点数 + /// + /// 分区 + /// + /// + public static float? ConvertTimeZoneToFloat(string timeZone) + { + if (string.IsNullOrEmpty(timeZone)|| !timeZone.StartsWith("GMT")) + { + return null; + } + + var sign = timeZone[3] == '+' ? 1 : -1; + var parts = timeZone.Substring(4).Split(':'); + var hours = int.Parse(parts[0]); + var minutes = int.Parse(parts[1]); + + return sign * (hours + minutes / 60f); + } } \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Aggregates/OrderAggregate/IOrderRepository.cs b/src/SJZY.Track.Domain/Aggregates/OrderAggregate/IOrderRepository.cs index 78cdd5df..ff7ab6f7 100644 --- a/src/SJZY.Track.Domain/Aggregates/OrderAggregate/IOrderRepository.cs +++ b/src/SJZY.Track.Domain/Aggregates/OrderAggregate/IOrderRepository.cs @@ -31,6 +31,14 @@ public interface IOrderRepository : IBasicRepository /// Task PushWarnOrdersAsync(); + /// + /// 更新缺失标记,时区缺失和发生地缺失标记,1表示时区,2表示发生地,3表示两种 + /// + /// 订单id + /// 值 + /// + Task UpdateBatchIdsAsync(List ids, int newValue); + #region 订单关联 /// diff --git a/src/SJZY.Track.Domain/Aggregates/OrderAggregate/OrderEntity.cs b/src/SJZY.Track.Domain/Aggregates/OrderAggregate/OrderEntity.cs index 9a7c4597..b04aa76a 100644 --- a/src/SJZY.Track.Domain/Aggregates/OrderAggregate/OrderEntity.cs +++ b/src/SJZY.Track.Domain/Aggregates/OrderAggregate/OrderEntity.cs @@ -149,6 +149,12 @@ public class OrderEntity : IFullAuditedBasicEntitys, IAggregateRoot /// [SugarColumn(ColumnName = "ProductCode")] public string? ProductCode { get; set; } + + /// + /// 时区缺失和发生地缺失标记,1表示时区,2表示发生地,3表示两种 + /// + [SugarColumn(ColumnName = "DeficiencyTag")] + public int? DeficiencyTag { get; set; } [SugarColumn(IsIgnore = true)] public List OrderFlights { get; set; } [SugarColumn(IsIgnore = true)] public List OrderTemplates { get; set; } diff --git a/src/SJZY.Track.Domain/Aggregates/TrackPullAggregate/TrackPullContentConfigEntity.cs b/src/SJZY.Track.Domain/Aggregates/TrackPullAggregate/TrackPullContentConfigEntity.cs index 5afef0fb..6e717032 100644 --- a/src/SJZY.Track.Domain/Aggregates/TrackPullAggregate/TrackPullContentConfigEntity.cs +++ b/src/SJZY.Track.Domain/Aggregates/TrackPullAggregate/TrackPullContentConfigEntity.cs @@ -71,4 +71,10 @@ public class TrackPullContentConfigEntity : IFullAuditedBasicEntitys, IEntity /// [SugarColumn(ColumnName = "IsCompleted")] public bool IsCompleted { get; set; } + + /// + /// 轨迹时区发生地参数值 + /// + [SugarColumn(ColumnName = "TrackZonePlaceValue")] + public int? TrackZonePlaceValue { get; set; } } \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Consts/GlobalConst.MQ.cs b/src/SJZY.Track.Domain/Consts/GlobalConst.MQ.cs index 378f0b89..1b853ffe 100644 --- a/src/SJZY.Track.Domain/Consts/GlobalConst.MQ.cs +++ b/src/SJZY.Track.Domain/Consts/GlobalConst.MQ.cs @@ -56,4 +56,9 @@ public partial class GlobalConst /// 关联订单后补轨迹 /// public const string OrderLinkAfterFillTrack = "SJZY.Track.OrderLinkAfterFillTrack"; + + /// + /// 拉取轨迹触发兜底后更新订单 + /// + public const string PullChangeBottomLineUpdateOrderSubscribe = "SJZY.Track.PullChangeBottomLineUpdateOrder"; } \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Consts/GlobalConst.Redis.cs b/src/SJZY.Track.Domain/Consts/GlobalConst.Redis.cs index dcaf7a35..6f49c80d 100644 --- a/src/SJZY.Track.Domain/Consts/GlobalConst.Redis.cs +++ b/src/SJZY.Track.Domain/Consts/GlobalConst.Redis.cs @@ -36,4 +36,14 @@ public partial class GlobalConst /// kpi区域redis key前缀 /// public const string KpiAreaKeyPrefix = "KpiArea"; + + /// + /// 城市时区redis key前缀 + /// + public const string CityTimezoneKeyPrefix = "CityTimezone"; + + /// + /// 港口时区redis key前缀 + /// + public const string PortTimezoneKeyPrefix = "PortTimezone"; } \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Common/CityTimezoneDto.cs b/src/SJZY.Track.Domain/Dtos/Common/CityTimezoneDto.cs new file mode 100644 index 00000000..63cd5dad --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Common/CityTimezoneDto.cs @@ -0,0 +1,14 @@ +namespace SJZY.Track.Domain.Dtos.Common; + +public class CityTimezoneDto +{ + /// + /// 城市英文名称 + /// + public string? CityEnName { get; set; } + + /// + /// 时区 + /// + public string Timezone { get; set; } +} diff --git a/src/SJZY.Track.Domain/Dtos/Common/PortTimezoneDto.cs b/src/SJZY.Track.Domain/Dtos/Common/PortTimezoneDto.cs new file mode 100644 index 00000000..896981cb --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Common/PortTimezoneDto.cs @@ -0,0 +1,14 @@ +namespace SJZY.Track.Domain.Dtos.Common; + +public class PortTimezoneDto +{ + /// + /// 城市英文名称 + /// + public string? PortCode { get; set; } + + /// + /// 时区 + /// + public string Timezone { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/TrackPull/GetTrackPullContentListCacheVO.cs b/src/SJZY.Track.Domain/Dtos/TrackPull/GetTrackPullContentListCacheVO.cs index 047431d9..8fad0074 100644 --- a/src/SJZY.Track.Domain/Dtos/TrackPull/GetTrackPullContentListCacheVO.cs +++ b/src/SJZY.Track.Domain/Dtos/TrackPull/GetTrackPullContentListCacheVO.cs @@ -36,6 +36,11 @@ public class GetTrackPullContentListCacheVO /// 轨迹发生地参数值(主数据枚举) /// public int? TrackPlaceValue { get; set; } + + /// + /// 兜底时区轨迹发生地参数值(TrackLocationValue) + /// + public int? TrackTimePlaceValue { get; set; } /// /// 轨迹时区GMT @@ -46,4 +51,9 @@ public class GetTrackPullContentListCacheVO /// 订单是否完成(由轨迹刷新配置决定) /// public bool IsCompleted { get; set; } + + /// + /// 轨迹时区发生地参数值 + /// + public int? TrackZonePlaceValue { get; set; } } \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Queries/ITimezoneQueries.cs b/src/SJZY.Track.Domain/Queries/ITimezoneQueries.cs new file mode 100644 index 00000000..14e33748 --- /dev/null +++ b/src/SJZY.Track.Domain/Queries/ITimezoneQueries.cs @@ -0,0 +1,20 @@ +using SJZY.Track.Domain.Dtos.Common; + +namespace SJZY.Track.Domain.Queries; + +public interface ITimezoneQueries +{ + /// + /// 通过城市英文名称获取时区 + /// + /// + /// + Task GetCityTimezone(string cityEnName); + + /// + /// 通过港口三字码获取时区 + /// + /// + /// + Task GetPortTimezone(string airCode); +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/VEntities/VAirportEntity.cs b/src/SJZY.Track.Domain/VEntities/VAirportEntity.cs new file mode 100644 index 00000000..ba69e854 --- /dev/null +++ b/src/SJZY.Track.Domain/VEntities/VAirportEntity.cs @@ -0,0 +1,121 @@ +using SqlSugar; + +namespace SJZY.Track.Domain.VEntities; + +/// +/// 空港 +/// +[SugarTable("t_airport", "空港")] +public class VAirportEntity : IFullAuditedBasicEntitys +{ + [SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true)] + public int Id { get; set; } + + /// + /// 空运航线id + /// + [SugarColumn(ColumnName = "AirRouteId")] + public int AirRouteId { get; set; } + + /// + /// 城市id + /// + [SugarColumn(ColumnName = "CityId")] + public int CityId { get; set; } + + /// + /// 主港口,空港id + /// + [SugarColumn(ColumnName = "MId", IsNullable = true)] + public int? MId { get; set; } + + /// + /// 中文名 + /// + [SugarColumn(ColumnName = "CnName")] + public string CnName { get; set; } + + /// + /// 英文名 + /// + [SugarColumn(ColumnName = "EnName")] + public string EnName { get; set; } + + /// + /// 代码 + /// + [SugarColumn(ColumnName = "Code", IsNullable = true)] + public string Code { get; set; } + + /// + /// 海关代码 + /// + [SugarColumn(ColumnName = "CustomsCode", IsNullable = true)] + public string CustomsCode { get; set; } + + /// + /// 海关名称 + /// + [SugarColumn(ColumnName = "CustomsName", IsNullable = true)] + public string CustomsName { get; set; } + + /// + /// 离境口岸代码 + /// + [SugarColumn(ColumnName = "DeparturePortCode", IsNullable = true)] + public string DeparturePortCode { get; set; } + + /// + /// 离境口岸名称 + /// + [SugarColumn(ColumnName = "DeparturePortName", IsNullable = true)] + public string DeparturePortName { get; set; } + + /// + /// 国内排序 + /// + [SugarColumn(ColumnName = "DomcSort")] + public int DomcSort { get; set; } + + /// + /// 国外排序 + /// + [SugarColumn(ColumnName = "OverSort")] + public int OverSort { get; set; } + + /// + /// 备注 + /// + [SugarColumn(ColumnName = "Remark", IsNullable = true)] + public string Remark { get; set; } + + /// + /// 创建人 + /// + [SugarColumn(ColumnName = "CreateUserId", IsNullable = true)] + public int? CreateUserId { get; set; } + + /// + /// 创建时间 + /// + [SugarColumn(ColumnName = "CreateTime", IsNullable = false, DefaultValue = "CURRENT_TIMESTAMP")] + public DateTime CreateTime { get; set; } + + /// + /// 更新人 + /// + [SugarColumn(ColumnName = "UpdateUserId", IsNullable = true)] + public int? UpdateUserId { get; set; } + + /// + /// 更新时间 + /// + [SugarColumn(ColumnName = "UpdateTime", IsNullable = true)] + public DateTime? UpdateTime { get; set; } + + /// + /// 是否删除 + /// + [SugarColumn(ColumnName = "IsDeleted")] + public bool IsDeleted { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/VEntities/VCityEntity.cs b/src/SJZY.Track.Domain/VEntities/VCityEntity.cs new file mode 100644 index 00000000..ad914504 --- /dev/null +++ b/src/SJZY.Track.Domain/VEntities/VCityEntity.cs @@ -0,0 +1,140 @@ +using SqlSugar; +using System; + +namespace SJZY.Track.Domain.VEntities; + +[SugarTable("t_city")] +public class VCityEntity : IFullAuditedBasicEntitys +{ + /// + /// 主键 + /// + [SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true)] + public int Id { get; set; } + + /// + /// 国家id + /// + [SugarColumn(ColumnName = "CountryId")] + public int CountryId { get; set; } + + /// + /// 省份id + /// + [SugarColumn(ColumnName = "ProvinceId", IsNullable = true)] + public int? ProvinceId { get; set; } + + /// + /// 中文名 + /// + [SugarColumn(ColumnName = "CnName")] + public string CnName { get; set; } + + /// + /// 英文名 + /// + [SugarColumn(ColumnName = "EnName")] + public string EnName { get; set; } + + /// + /// 联合国code + /// + [SugarColumn(ColumnName = "UnCode", IsNullable = true)] + public string UnCode { get; set; } + + /// + /// 所区分组(1华南,2华东,3华北,4 西南,5华中) + /// + [SugarColumn(ColumnName = "CityType", IsNullable = true)] + public int? CityType { get; set; } + + /// + /// 时区 + /// + [SugarColumn(ColumnName = "TimeZone", IsNullable = true)] + public string TimeZone { get; set; } + + /// + /// 排序 + /// + [SugarColumn(ColumnName = "Sort")] + public int Sort { get; set; } + + /// + /// 备注 + /// + [SugarColumn(ColumnName = "Remark", IsNullable = true)] + public string Remark { get; set; } + + /// + /// 国家统计局统计用区划代码 + /// + [SugarColumn(ColumnName = "StatisticalZoningCode", IsNullable = true)] + public string StatisticalZoningCode { get; set; } + + /// + /// 创建人 + /// + [SugarColumn(ColumnName = "CreateUserId", IsNullable = true)] + public int? CreateUserId { get; set; } + + /// + /// 创建时间 + /// + [SugarColumn(ColumnName = "CreateTime", IsNullable = false, DefaultValue = "CURRENT_TIMESTAMP")] + public DateTime CreateTime { get; set; } + + /// + /// 更新人 + /// + [SugarColumn(ColumnName = "UpdateUserId", IsNullable = true)] + public int? UpdateUserId { get; set; } + + /// + /// 更新时间 + /// + [SugarColumn(ColumnName = "UpdateTime", IsNullable = true)] + public DateTime? UpdateTime { get; set; } + + /// + /// 是否删 + /// + [SugarColumn(ColumnName = "IsDeleted")] + public bool IsDeleted { get; set; } + + /// + /// 维护时区 + /// + [SugarColumn(ColumnName = "MaintainTimeZone", IsNullable = true)] + public decimal? MaintainTimeZone { get; set; } + + /// + /// 经度 + /// + [SugarColumn(ColumnName = "Longitude", IsNullable = true)] + public string Longitude { get; set; } + + /// + /// 纬度 + /// + [SugarColumn(ColumnName = "Latitude", IsNullable = true)] + public string Latitude { get; set; } + + /// + /// 海拔 + /// + [SugarColumn(ColumnName = "Elevation", IsNullable = true)] + public string Elevation { get; set; } + + /// + /// 语言 + /// + [SugarColumn(ColumnName = "Language", IsNullable = true)] + public string Language { get; set; } + + /// + /// timezoneURL + /// + [SugarColumn(ColumnName = "TimezoneURL", IsNullable = true)] + public string TimezoneURL { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Repository/Queries/TimezoneQueries.cs b/src/SJZY.Track.Repository/Queries/TimezoneQueries.cs new file mode 100644 index 00000000..cd2a0569 --- /dev/null +++ b/src/SJZY.Track.Repository/Queries/TimezoneQueries.cs @@ -0,0 +1,101 @@ +using System.Reflection.Metadata; +using SJZY.Track.Domain.Consts; +using SJZY.Track.Domain.Dtos.Common; +using SJZY.Track.Domain.Queries; +using SJZY.Track.Domain.VEntities; + +namespace SJZY.Track.Repository.Queries; + +public class TimezoneQueries:ITimezoneQueries, ISugarRepository, ITransientDependency +{ + public ISqlSugarClient Context { get; set; } + + public TimezoneQueries() + { + Context = SqlsugarScopeBasic.GetContextSafely("default"); + } + + private string GetCityKey(string cityEnName) + { + return $"{GlobalConst.CityTimezoneKeyPrefix}:{cityEnName}"; + } + + private string GetPortKey(string airCode) + { + return $"{GlobalConst.PortTimezoneKeyPrefix}:{airCode}"; + } + + /// + /// 获取城市时区 + /// + /// 城市英文名称 + /// 时区 + public async Task GetCityTimezone(string cityEnName) + { + var key =GetCityKey(cityEnName); + var timezone = RedisHelper.Client.Get(key); + if (!string.IsNullOrEmpty(timezone)) + { + return timezone; + } + + var cityTimezone = await GetTimezoneByCityName(cityEnName); + if (cityTimezone == null!) + { + await RedisHelper.Client.SetAsync(key, string.Empty, TimeSpan.FromSeconds(20)); + return string.Empty; + } + + await RedisHelper.Client.SetAsync(key, cityTimezone.Timezone, TimeSpan.FromHours(6)); + return cityTimezone.Timezone; + } + + /// + /// 获取港口时区 + /// + /// 港口三字码 + /// 时区 + public async Task GetPortTimezone(string airCode) + { + var key = GetPortKey(airCode); + var timezone = RedisHelper.Client.Get(key); + if (!string.IsNullOrEmpty(timezone)) + { + return timezone; + } + + var portTimezone = await GetTimezoneByPortCode(airCode); + if (portTimezone == null!) + { + await RedisHelper.Client.SetAsync(key, string.Empty, TimeSpan.FromSeconds(20)); + return string.Empty; + } + + await RedisHelper.Client.SetAsync(key, portTimezone.Timezone, TimeSpan.FromHours(6)); + return portTimezone.Timezone; + } + + private Task GetTimezoneByCityName(string cityEnName) + { + return Context.Queryable().Where(val => !val.IsDeleted && val.EnName == cityEnName) + .Select(val=>new CityTimezoneDto() + { + CityEnName =val.EnName, + Timezone = val.TimeZone + }) + .FirstAsync(); + } + + private Task GetTimezoneByPortCode(string airCode) + { + return Context.Queryable() + .InnerJoin((city, airport) => city.Id == airport.CityId) + .Where((city,airport) => !airport.IsDeleted && !city.IsDeleted && airport.Code == airCode) + .Select((city,airport)=>new PortTimezoneDto() + { + PortCode = airport.Code, + Timezone = city.TimeZone + }) + .FirstAsync(); + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Repository/Repositories/OrderRepository.cs b/src/SJZY.Track.Repository/Repositories/OrderRepository.cs index 85faff5d..85df94ed 100644 --- a/src/SJZY.Track.Repository/Repositories/OrderRepository.cs +++ b/src/SJZY.Track.Repository/Repositories/OrderRepository.cs @@ -19,6 +19,11 @@ public class OrderRepository : BasicRepository, IOrderRepository, I tran.Complete(); } + public Task UpdateBatchIdsAsync(List ids, int newValue) + { + return Context.Ado.ExecuteCommandAsync("UPDATE `t_order` SET `DeficiencyTag` = @newValue WHERE `Id` IN @ids", new { ids, newValue }); + } + public async Task UpdateOrderAsync(OrderEntity order) { using var tran = TransactionHelper.GetReadCommitted();