Remove KPI warning areas and slim transport warning scene schema.

Drop legacy scene match columns from code/SQL and delete unused area tables guidance for pre-prod cleanup.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zzh 2026-08-01 11:56:15 +08:00
parent 4f954df02a
commit af86a1fdff
33 changed files with 269 additions and 1058 deletions

View File

@ -0,0 +1,211 @@
-- 运输时效场景表瘦身:删除历史匹配字段,并同步现行字段注释
-- 执行前请备份 t_warning_transport_scene
-- 依赖:已执行 20260801_transport_warning_simplify.sql(CountryCode / AssessmentTotalTimeSpan 已存在)
-- 注释更新通过 information_schema 保留原列类型,避免误改长度/默认值
-- 1) 删除历史字段(列不存在则跳过,避免 1091)
SET @schema = DATABASE();
SET @sql = (
SELECT IF(COUNT(*) > 0, 'ALTER TABLE `t_warning_transport_scene` DROP COLUMN `IsTransit`', 'SELECT 1')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = 't_warning_transport_scene' AND COLUMN_NAME = 'IsTransit'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @sql = (
SELECT IF(COUNT(*) > 0, 'ALTER TABLE `t_warning_transport_scene` DROP COLUMN `CargoType`', 'SELECT 1')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = 't_warning_transport_scene' AND COLUMN_NAME = 'CargoType'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @sql = (
SELECT IF(COUNT(*) > 0, 'ALTER TABLE `t_warning_transport_scene` DROP COLUMN `LeavePort`', 'SELECT 1')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = 't_warning_transport_scene' AND COLUMN_NAME = 'LeavePort'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @sql = (
SELECT IF(COUNT(*) > 0, 'ALTER TABLE `t_warning_transport_scene` DROP COLUMN `Months`', 'SELECT 1')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = 't_warning_transport_scene' AND COLUMN_NAME = 'Months'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @sql = (
SELECT IF(COUNT(*) > 0, 'ALTER TABLE `t_warning_transport_scene` DROP COLUMN `AreaId`', 'SELECT 1')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = 't_warning_transport_scene' AND COLUMN_NAME = 'AreaId'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 2) 表注释
ALTER TABLE t_warning_transport_scene
COMMENT = '运输时效场景(产品+国家+考核总时效)';
-- 3) 现行字段注释(保留原 COLUMN_TYPE / NULLABLE)
-- WarningId
SELECT CONCAT(
'ALTER TABLE `t_warning_transport_scene` MODIFY COLUMN `', COLUMN_NAME, '` ', COLUMN_TYPE,
IF(IS_NULLABLE = 'YES', ' NULL', ' NOT NULL'),
' COMMENT ''预警规则主体Id(t_warning.Id,运输时效为 AppKey 级方案)'''
)
INTO @sql
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema
AND TABLE_NAME = 't_warning_transport_scene'
AND COLUMN_NAME = 'WarningId';
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ProductCode
SELECT CONCAT(
'ALTER TABLE `t_warning_transport_scene` MODIFY COLUMN `', COLUMN_NAME, '` ', COLUMN_TYPE,
IF(IS_NULLABLE = 'YES', ' NULL', ' NOT NULL'),
' COMMENT ''销售产品编码(单一,命中订单产品)'''
)
INTO @sql
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema
AND TABLE_NAME = 't_warning_transport_scene'
AND COLUMN_NAME = 'ProductCode';
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- CountryCode
SELECT CONCAT(
'ALTER TABLE `t_warning_transport_scene` MODIFY COLUMN `', COLUMN_NAME, '` ', COLUMN_TYPE,
IF(IS_NULLABLE = 'YES', ' NULL', ' NOT NULL'),
' COMMENT ''到达国家二字码(单一,命中订单到达国家)'''
)
INTO @sql
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema
AND TABLE_NAME = 't_warning_transport_scene'
AND COLUMN_NAME = 'CountryCode';
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- AssessmentTotalTimeSpan
SELECT CONCAT(
'ALTER TABLE `t_warning_transport_scene` MODIFY COLUMN `', COLUMN_NAME, '` ', COLUMN_TYPE,
IF(IS_NULLABLE = 'YES', ' NULL', ' NOT NULL'),
' COMMENT ''考核总时效(小时;前端按天录入后×24入库)'''
)
INTO @sql
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema
AND TABLE_NAME = 't_warning_transport_scene'
AND COLUMN_NAME = 'AssessmentTotalTimeSpan';
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
ALTER TABLE t_warning_transport_scene_rule_item
COMMENT = '运输时效场景分段规则项';
-- WarningId / TransportWarningSceneId 注释
SELECT CONCAT(
'ALTER TABLE `t_warning_transport_scene_rule_item` MODIFY COLUMN `', COLUMN_NAME, '` ', COLUMN_TYPE,
IF(IS_NULLABLE = 'YES', ' NULL', ' NOT NULL'),
' COMMENT ''预警规则主体Id(t_warning.Id)'''
)
INTO @sql
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema
AND TABLE_NAME = 't_warning_transport_scene_rule_item'
AND COLUMN_NAME = 'WarningId';
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SELECT CONCAT(
'ALTER TABLE `t_warning_transport_scene_rule_item` MODIFY COLUMN `', COLUMN_NAME, '` ', COLUMN_TYPE,
IF(IS_NULLABLE = 'YES', ' NULL', ' NOT NULL'),
' COMMENT ''运输时效场景Id(t_warning_transport_scene.Id)'''
)
INTO @sql
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema
AND TABLE_NAME = 't_warning_transport_scene_rule_item'
AND COLUMN_NAME = 'TransportWarningSceneId';
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 4) t_warning.Customer:运输时效 AppKey 级方案(固定空串);回传/完整预警仍按客户匹配
SELECT CONCAT(
'ALTER TABLE `t_warning` MODIFY COLUMN `', COLUMN_NAME, '` ', COLUMN_TYPE,
IF(IS_NULLABLE = 'YES', ' NULL', ' NOT NULL'),
' COMMENT ''客户(运输时效固定空串;回传/完整预警按客户匹配)'''
)
INTO @sql
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema
AND TABLE_NAME = 't_warning'
AND COLUMN_NAME = 'Customer';
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 5) t_warning 上若仍残留旧匹配列 / CustomName(实体已不映射),按列存在则删
-- drop helper: 仅当列存在时生成 DROP,否则 SELECT 1
SET @sql = (
SELECT IF(COUNT(*) > 0, 'ALTER TABLE `t_warning` DROP COLUMN `IsTransit`', 'SELECT 1')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = 't_warning' AND COLUMN_NAME = 'IsTransit'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @sql = (
SELECT IF(COUNT(*) > 0, 'ALTER TABLE `t_warning` DROP COLUMN `CargoType`', 'SELECT 1')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = 't_warning' AND COLUMN_NAME = 'CargoType'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @sql = (
SELECT IF(COUNT(*) > 0, 'ALTER TABLE `t_warning` DROP COLUMN `LeavePort`', 'SELECT 1')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = 't_warning' AND COLUMN_NAME = 'LeavePort'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @sql = (
SELECT IF(COUNT(*) > 0, 'ALTER TABLE `t_warning` DROP COLUMN `Months`', 'SELECT 1')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = 't_warning' AND COLUMN_NAME = 'Months'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @sql = (
SELECT IF(COUNT(*) > 0, 'ALTER TABLE `t_warning` DROP COLUMN `AreaId`', 'SELECT 1')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = 't_warning' AND COLUMN_NAME = 'AreaId'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @sql = (
SELECT IF(COUNT(*) > 0, 'ALTER TABLE `t_warning` DROP COLUMN `CustomName`', 'SELECT 1')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = 't_warning' AND COLUMN_NAME = 'CustomName'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 6) 废表清理(代码已无映射;未上线可直接删)
-- 现行预警相关表(勿删):
-- t_warning
-- t_warning_transport_scene
-- t_warning_transport_scene_rule_item
-- t_warning_transport_generate_task
-- t_warning_notify_task
-- t_warning_return_rule_item
-- t_warning_return_retry_task
-- t_warning_complete_rule_item
--
-- 执行前可先核对:
-- SHOW TABLES LIKE 't_warning%';
-- SHOW TABLES LIKE 't_area%';
-- SHOW TABLES LIKE 't_rule_area%';
-- 6.1 WarningRuleEntity 映射为 t_warning,无 t_warning_rule
DROP TABLE IF EXISTS t_warning_rule;
-- 6.2 预警分区已下线(原 KPIAreaAggregate:RuleAreaEntity / RuleAreaInfoEntity)
DROP TABLE IF EXISTS t_area_details;
DROP TABLE IF EXISTS t_area;
-- 注释里曾写 t_rule_area,若库中存在且无代码引用也可删
DROP TABLE IF EXISTS t_rule_area;
DROP TABLE IF EXISTS t_rule_area_details;

View File

@ -3,11 +3,11 @@
-- 1) 国家列(若已存在可跳过)
ALTER TABLE t_warning_transport_scene
ADD COLUMN CountryCode VARCHAR(16) NULL COMMENT '国家二字码(单一)' AFTER ProductCode;
ADD COLUMN CountryCode VARCHAR(16) NULL COMMENT '到达国家二字码(单一,命中订单到达国家)' AFTER ProductCode;
-- 2) 考核总时效(小时)
ALTER TABLE t_warning_transport_scene
ADD COLUMN AssessmentTotalTimeSpan FLOAT NULL COMMENT '考核总时效(小时)' AFTER CountryCode;
ADD COLUMN AssessmentTotalTimeSpan FLOAT NULL COMMENT '考核总时效(小时;前端按天录入后×24入库)' AFTER CountryCode;
-- 3) 运输时效规则主体改为方案级:客户清空
UPDATE t_warning

View File

@ -2,8 +2,6 @@ using AutoMapper;
using TrackCenter.Application.Dtos.Warning.Complete;
using TrackCenter.Application.Dtos.Warning.Return;
using TrackCenter.Application.Dtos.Warning.Transport;
using TrackCenter.Domain.Aggregates.KPIAreaAggregate;
using TrackCenter.Domain.Dtos.Forewarning;
using TrackCenter.Domain.Dtos.Warning;
namespace TrackCenter.Application.AutoMapper;
@ -15,27 +13,5 @@ public class WarningMapperProfile : Profile
CreateMap<GetPageCompleteWarningDetailsInput, GetPageCompleteWarningDetailsInputVO>(MemberList.None);
CreateMap<GetPageReturnWarningDetailsInput, GetPageReturnWarningDetailsInputVO>(MemberList.None);
CreateMap<GetPageTransportWarningDetailsInput, GetPageTransportWarningDetailsInputVO>(MemberList.None);
// kpi区域
CreateMap<UpdateRuleAreaRequest, RuleAreaEntity>(MemberList.None);
CreateMap<AddRuleAreaInfoRequest, RuleAreaInfoEntity>(MemberList.None)
.ForMember(dest => dest.CountryCode, opt => opt.MapFrom(src => src.CountryCode))
.ForMember(dest => dest.CountryName, opt => opt.MapFrom(src => src.CountryName))
.ForMember(dest => dest.Province, opt => opt.MapFrom(src => src.Province))
.ForMember(dest => dest.City, opt => opt.MapFrom(src => src.City))
.ForMember(dest => dest.LeftPostcode, opt => opt.MapFrom(src => src.LeftPostCode))
.ForMember(dest => dest.RightPostcode, opt => opt.MapFrom(src => src.RightPostCode))
.ForMember(dest => dest.AreaId, opt => opt.MapFrom(src => src.AreaId));
CreateMap<CreateRuleAreaRequest, RuleAreaEntity>(MemberList.None)
.ForMember(dest => dest.AppKey, opt => opt.MapFrom(src => src.AppKey))
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name));
CreateMap<UpdateRuleAreaInfoRequest, RuleAreaInfoEntity>(MemberList.None)
.ForMember(dest => dest.CountryCode, opt => opt.MapFrom(src => src.CountryCode))
.ForMember(dest => dest.CountryName, opt => opt.MapFrom(src => src.CountryName))
.ForMember(dest => dest.Province, opt => opt.MapFrom(src => src.Province))
.ForMember(dest => dest.City, opt => opt.MapFrom(src => src.City))
.ForMember(dest => dest.LeftPostcode, opt => opt.MapFrom(src => src.LeftPostCode))
.ForMember(dest => dest.RightPostcode, opt => opt.MapFrom(src => src.RightPostCode));
}
}

View File

@ -1,29 +0,0 @@
namespace TrackCenter.Application.Dtos.Forewarning;
public class AreaCacheEntry
{
/// <summary>
/// 国家或地区
/// </summary>
public string CountryCode { get; set; } = null!;
/// <summary>
/// 省份
/// </summary>
public string? Province { get; set; }
/// <summary>
/// 城市
/// </summary>
public string? City { get; set; }
/// <summary>
/// 开始邮编
/// </summary>
public string? LeftPostcode { get; set; }
/// <summary>
/// 截止邮编
/// </summary>
public string? RightPostcode { get; set; }
}

View File

@ -1,17 +0,0 @@
namespace TrackCenter.Application.Dtos.Forewarning;
public class RuleAreaBaseInfo
{
public RuleAreaBaseInfo()
{
}
public RuleAreaBaseInfo(string appKey, string customer)
{
AppKey = appKey;
Customer = customer;
}
public string AppKey { get; set; }
public string Customer { get; set; }
}

View File

@ -1,7 +1,7 @@
namespace TrackCenter.Application.Dtos.Warning.Transport;
/// <summary>
/// 预警规则场景
/// 运输时效场景(一产品 + 一国家 + 考核总时效)
/// </summary>
public class TransportWarningSceneDto
{
@ -11,57 +11,27 @@ public class TransportWarningSceneDto
public int Id { get; set; }
/// <summary>
/// 预警规则主体id
/// 预警规则主体id(AppKey 级方案)
/// </summary>
public int WarningId { get; set; }
/// <summary>
/// 场景摘要(用于展示场景tabs)
/// 场景摘要(产品 / 国家 / 考核总时效)
/// </summary>
public string Summary { get; set; }
/// <summary>
/// 是否中转(单一)
/// </summary>
public bool? IsTransit { get; set; }
/// <summary>
/// 货物类型(多个,分割)
/// </summary>
public string? CargoType { get; set; }
/// <summary>
/// 起运港口(多个,分割)
/// </summary>
public string? LeavePort { get; set; }
/// <summary>
/// 产品编码(单一)
/// 销售产品编码(单一)
/// </summary>
public string? ProductCode { get; set; }
/// <summary>
/// 国家二字码(单一)
/// 到达国家二字码(单一)
/// </summary>
public string? CountryCode { get; set; }
/// <summary>
/// 考核总时效(小时)
/// 考核总时效(小时;前端按天展示)
/// </summary>
public float? AssessmentTotalTimeSpan { get; set; }
/// <summary>
/// 月份(多个/分割,历史字段)
/// </summary>
public string? Months { get; set; }
/// <summary>
/// 区域Id(单一,历史字段)
/// </summary>
public int? AreaId { get; set; }
/// <summary>
/// 区域id对应的名称(历史字段)
/// </summary>
public string? AreaName { get; set; }
}

View File

@ -11,36 +11,21 @@ public sealed class UpsertTransportWarningSceneInput
public int Id { get; set; }
/// <summary>
/// 预警规则主体id
/// 预警规则主体id(AppKey 级方案)
/// </summary>
[IdRequired]
public int WarningId { get; set; }
/// <summary>历史字段,忽略</summary>
public bool? IsTransit { get; set; }
/// <summary>历史字段,忽略</summary>
public string? CargoType { get; set; }
/// <summary>历史字段,忽略</summary>
public string? LeavePort { get; set; }
/// <summary>产品编码(单一销售产品)</summary>
/// <summary>销售产品编码(单一)</summary>
[Required(ErrorMessage = "请配置销售产品")]
public string? ProductCode { get; set; }
/// <summary>国家二字码(单一)</summary>
/// <summary>到达国家二字码(单一)</summary>
[Required(ErrorMessage = "请配置国家")]
public string? CountryCode { get; set; }
/// <summary>考核总时效(小时)</summary>
/// <summary>考核总时效(小时;前端按天录入后×24)</summary>
[Required(ErrorMessage = "请配置考核总时效")]
[Range(0.1, 99999, ErrorMessage = "考核总时效须大于0")]
public float? AssessmentTotalTimeSpan { get; set; }
/// <summary>历史字段,忽略</summary>
public string? Months { get; set; }
/// <summary>历史字段,忽略</summary>
public int? AreaId { get; set; }
}

View File

@ -1,8 +1,9 @@
using TrackCenter.Application.Dtos.Forewarning;
namespace TrackCenter.Application.Events;
/// <summary>
/// 历史区域缓存清理事件(预警分区已下线,保留空壳兼容 Redis 订阅反序列化)
/// </summary>
public class ClearRulCacheEvent
{
public List<RuleAreaBaseInfo> Items { get; set; }
public List<int> AreaIds { get; set; } = new();
}

View File

@ -2,11 +2,9 @@ using Microsoft.Extensions.Options;
using TrackCenter.Application.Dtos.Warning;
using TrackCenter.Application.Options;
using TrackCenter.Application.Services.Warning.Model;
using TrackCenter.Domain.Aggregates.KPIAreaAggregate;
using TrackCenter.Domain.Aggregates.OrderAggregate;
using TrackCenter.Domain.Aggregates.TrackDetailsAggregate;
using TrackCenter.Domain.Aggregates.WarningAggregate;
using TrackCenter.Domain.Dtos.Forewarning;
using TrackCenter.Domain.Dtos.Warning;
namespace TrackCenter.Application.Hangfire;
@ -17,21 +15,25 @@ namespace TrackCenter.Application.Hangfire;
public sealed class WarningNotifyAggregator : ITransientDependency
{
private readonly IOrderRepository _orderRepository;
private readonly IKpiAreaRepository _kpiAreaRepository;
private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
private readonly IWarningTaskRepository _warningTaskRepository;
private readonly IWarningRuleRepository _warningRuleRepository;
private readonly IWarningDetailsEsRepository _warningDetailsEsRepository;
private readonly IOptionsMonitor<TrackWarningTaskOptions> _optionsMonitor;
public WarningNotifyAggregator(IWarningTaskRepository warningTaskRepository, IWarningRuleRepository warningRuleRepository, IOrderRepository orderRepository, ITrackDetailsEsRepository trackDetailsEsRepository, IWarningDetailsEsRepository warningDetailsEsRepository, IKpiAreaRepository kpiAreaRepository, IOptionsMonitor<TrackWarningTaskOptions> optionsMonitor)
public WarningNotifyAggregator(
IWarningTaskRepository warningTaskRepository,
IWarningRuleRepository warningRuleRepository,
IOrderRepository orderRepository,
ITrackDetailsEsRepository trackDetailsEsRepository,
IWarningDetailsEsRepository warningDetailsEsRepository,
IOptionsMonitor<TrackWarningTaskOptions> optionsMonitor)
{
_warningTaskRepository = warningTaskRepository;
_warningRuleRepository = warningRuleRepository;
_orderRepository = orderRepository;
_trackDetailsEsRepository = trackDetailsEsRepository;
_warningDetailsEsRepository = warningDetailsEsRepository;
_kpiAreaRepository = kpiAreaRepository;
_optionsMonitor = optionsMonitor;
}
@ -140,19 +142,13 @@ public sealed class WarningNotifyAggregator : ITransientDependency
// 2.场景验证
var sceneDict = scenes.ToDictionary(x => x.Id.ToString(), TransportWarningSceneBO.From);
// 2.1查找场景关联的区域信息
var areaIds = scenes.Select(x => x.AreaId ?? 0).Where(id => id != 0).ToHashSet();
var ruleAreaInfosDict = areaIds.Count > 0
? await _kpiAreaRepository.GetAreaInfosDictByAreaId(areaIds)
: new Dictionary<int, List<KpiAreaInfo>>(0);
// 2.2场景验证
// 2.1场景验证(产品+国家)
var validTasks = new List<WarningNotifyTaskEntity>(filtered.Count);
foreach (var task in filtered)
{
if (sceneDict.TryGetValue(task.AuxiliaryId!, out var scene)
&& orderDict.TryGetValue(task.OrderId, out var order)
&& scene.CanHitScene(order, ruleAreaInfosDict.GetValueOrDefault(scene.AreaId ?? 0)))
&& scene.CanHitScene(order))
{
validTasks.Add(task);
}

View File

@ -1,24 +0,0 @@
using TrackCenter.Domain.Aggregates.KPIAreaAggregate;
namespace TrackCenter.Application.Services.ForewarningServices;
public class KpiAreaCacheService : ITransientDependency
{
const string GlobalKpiAreaLockKey = "KpiAreaCacheService_GlobalLock";
IKpiAreaRepository _kpiAreaRepository;
public KpiAreaCacheService(IKpiAreaRepository kpiAreaRepository)
{
_kpiAreaRepository = kpiAreaRepository;
}
private string GetKey(string appKey, string country)
{
return $"{GlobalConst.KpiAreaKeyPrefix}:{appKey}:{country}";
}
public Task GetKpiArea(string appKey, string country)
{
throw new NotImplementedException();
}
}

View File

@ -1,147 +0,0 @@
using Fake.Application.Dtos;
using TrackCenter.Domain.Aggregates.KPIAreaAggregate;
using TrackCenter.Domain.Dtos.Forewarning;
namespace TrackCenter.Application.Services.ForewarningServices;
[ApiExplorerSettings(GroupName = "预警服务")]
[Route("/ForewarningService")]
public class KpiAreaService : ApplicationServiceBase
{
private readonly IKpiAreaRepository _ruleAreaRepository;
private readonly KpiAreaCacheService _kpiAreaCacheService;
public KpiAreaService(IKpiAreaRepository ruleAreaRepository, KpiAreaCacheService kpiAreaCacheService)
{
_ruleAreaRepository = ruleAreaRepository;
_kpiAreaCacheService = kpiAreaCacheService;
}
/// <summary>
/// 创建分区
/// </summary>
/// <param name="input"></param>
/// <returns>分区id</returns>
[HttpPost("KpiArea/CreateKpiArea")]
public async ValueTask<IdBaseDto> CreateKpiArea(CreateRuleAreaRequest input)
{
var ruleAreaEntity = ObjectMapper.Map<CreateRuleAreaRequest, RuleAreaEntity>(input);
var hasSameName =
await _ruleAreaRepository.IsAnyAsync(val => val.AppKey == input.AppKey && val.Name == input.Name);
if (hasSameName)
{
throw new BusinessException("分区名称重复,请重新修改提交");
}
var areaId = await _ruleAreaRepository.CreateAreaAsync(ruleAreaEntity);
return new IdBaseDto
{
Id = areaId,
};
}
/// <summary>
/// 添加区域信息
/// </summary>
/// <param name="input"></param>
/// <returns>区域id</returns>
[HttpPost("KpiArea/AddAreaInfo")]
public async ValueTask<IdBaseDto> AddAreaInfoAsync(AddRuleAreaInfoRequest input)
{
var ruleAreaEntity = ObjectMapper.Map<AddRuleAreaInfoRequest, RuleAreaInfoEntity>(input);
var ruleInfoId = await _ruleAreaRepository.AddAreaInfoAsync(ruleAreaEntity);
// todo: 删除 kpi区域缓存
return new IdBaseDto
{
Id = ruleInfoId,
};
}
/// <summary>
/// 删除分区
/// </summary>
/// <param name="id">分区id</param>
/// <returns></returns>
[HttpDelete("KpiArea/DeleteKpiArea")]
public async ValueTask DeleteKpiArea(int id)
{
await _ruleAreaRepository.DeleteArea(id);
// todo: 删除 kpi区域缓存
}
/// <summary>
/// 删除分区信息
/// </summary>
/// <param name="id">分区信息id</param>
/// <returns></returns>
[HttpDelete("KpiArea/DeleteKpiAreaInfo")]
public async ValueTask DeleteKpiAreaInfo(int id)
{
var info = await _ruleAreaRepository.GetAreaInfoById(id);
if (info == null) throw new BusinessException("未找到该区域信息");
await _ruleAreaRepository.DeleteAreaInfo(id);
// todo: 删除 kpi区域缓存
}
/// <summary>
/// 更新区域信息
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("KpiArea/ModifyKpiArea")]
public async Task ModifyKpiArea(UpdateRuleAreaRequest input)
{
if (input.Id <= 0)
throw new BusinessException("id不能为空");
var ruleArea = await _ruleAreaRepository.GetFirstAsync(val => val.Id == input.Id);
if (ruleArea == null)
throw new BusinessException("未找到该区域");
ruleArea.Name = input.Name;
await _ruleAreaRepository.UpdateAsync(ruleArea);
}
/// <summary>
/// 更新区域信息
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("KpiArea/ModifyKpiAreaInfo")]
public async Task ModifyKpiAreaInfo(UpdateRuleAreaInfoRequest input)
{
if (input.Id <= 0)
throw new BusinessException("id不能为空");
var areaInfo = await _ruleAreaRepository.GetAreaInfoById(input.Id);
if (areaInfo == null)
throw new BusinessException("未找到该区域信息");
var ruleAreaEntity = ObjectMapper.Map(input, areaInfo);
await _ruleAreaRepository.UpdateAreaInfoAsync(ruleAreaEntity);
// todo: 删除 kpi区域缓存
}
/// <summary>
/// 查询分区列表
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("KpiArea/GetKpiAreas")]
public async Task<PagedResult<AreaDto>> GetKpiAreas(QueryAreaRequest input)
{
return await _ruleAreaRepository.GetAreas(input);
}
/// <summary>
/// 查询分区列表
/// </summary>
/// <param name="query"></param>
/// <returns></returns>
[HttpPost("KpiArea/GetKpiAreaInfos")]
public async Task<PagedResult<RuleAreaInfoDto>> GetKpiAreaInfos(QueryAreaInfoRequest query)
{
return await _ruleAreaRepository.GetAreaInfos(query);
}
}

View File

@ -1,11 +1,9 @@
using System.Linq.Expressions;
using TrackCenter.Domain.Aggregates.KPIAreaAggregate;
using TrackCenter.Domain.Aggregates.OrderAggregate;
using TrackCenter.Domain.Aggregates.TrackDetailsAggregate;
using TrackCenter.Domain.Aggregates.TrackStatusAggregate;
using TrackCenter.Domain.Aggregates.WarningAggregate;
using TrackCenter.Domain.Aggregates.WarningAggregate.Transport;
using TrackCenter.Domain.Dtos.Forewarning;
using TrackCenter.Domain.Dtos.TrackDetails;
using TrackCenter.Domain.Dtos.Warning;
using SqlSugar;
@ -16,7 +14,6 @@ namespace TrackCenter.Application.Services.Warning.Handlers;
public class TransportWarningHandler : ITransportWarningHandler, ITransientDependency
{
private readonly IKpiAreaRepository _kpiAreaRepository;
private readonly IOrderRepository _orderRepository;
private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
private readonly IWarningRuleRepository _warningRuleRepository;
@ -24,14 +21,19 @@ public class TransportWarningHandler : ITransportWarningHandler, ITransientDepen
private readonly IWarningDetailsEsRepository _warningDetailsEsRepository;
private readonly ITrackStatusRepository _trackStatusRepository;
public TransportWarningHandler(IWarningTaskRepository warningTaskRepository, IWarningDetailsEsRepository warningDetailsEsRepository, IWarningRuleRepository warningRuleRepository, IOrderRepository orderRepository, ITrackDetailsEsRepository trackDetailsEsRepository, IKpiAreaRepository kpiAreaRepository, ITrackStatusRepository trackStatusRepository)
public TransportWarningHandler(
IWarningTaskRepository warningTaskRepository,
IWarningDetailsEsRepository warningDetailsEsRepository,
IWarningRuleRepository warningRuleRepository,
IOrderRepository orderRepository,
ITrackDetailsEsRepository trackDetailsEsRepository,
ITrackStatusRepository trackStatusRepository)
{
_warningTaskRepository = warningTaskRepository;
_warningDetailsEsRepository = warningDetailsEsRepository;
_warningRuleRepository = warningRuleRepository;
_orderRepository = orderRepository;
_trackDetailsEsRepository = trackDetailsEsRepository;
_kpiAreaRepository = kpiAreaRepository;
_trackStatusRepository = trackStatusRepository;
}
@ -599,7 +601,7 @@ public class TransportWarningHandler : ITransportWarningHandler, ITransientDepen
{
var ruleItem = ruleItemDict[detail.WarningSceneRuleItemId];
detail.WarningName = rule.Name;
detail.WarningRuleDescription = detail.GetWarningRuleDescription(postScene.ToEntity(), ruleItem, null);
detail.WarningRuleDescription = detail.GetWarningRuleDescription(postScene.ToEntity(), ruleItem);
needUpdateDetails.Add(detail);
}
}
@ -835,9 +837,6 @@ public class TransportWarningHandler : ITransportWarningHandler, ITransientDepen
.ToDictionary(x => x.Key, y => y.ToList());
// 3.检查是否重新命中规则
var ruleArea = scene.AreaId.HasValue
? await _kpiAreaRepository.GetFirstAsync(x => x.Id == scene.AreaId.Value)
: null;
var updateFollowRuleItemIdDict = updateFollowRuleItems.ToDictionary(x => x.Id);
foreach (var group in handleBlocks.GroupBy(x => (x.OrderId, x.RuleItemId)))
{
@ -865,7 +864,7 @@ public class TransportWarningHandler : ITransportWarningHandler, ITransientDepen
{
// 配置相关信息
block.Detail.WarningName = rule.Name;
block.Detail.WarningRuleDescription = block.Detail.GetWarningRuleDescription(scene.ToEntity(), ruleItem.ToEntity(), ruleArea);
block.Detail.WarningRuleDescription = block.Detail.GetWarningRuleDescription(scene.ToEntity(), ruleItem.ToEntity());
block.Detail.TransportTimeSpan = ruleItem.TransportTimeSpan;
block.Detail.StartTrackWarningTimeSpan = ruleItem.StartTrackWarningTimeSpan;
// 起始轨迹相关信息
@ -1173,15 +1172,6 @@ public class TransportWarningHandler : ITransportWarningHandler, ITransientDepen
);
var sceneDict = scenes.ToDictionary(x => x.Id);
// 获取区域字典
Dictionary<int, RuleAreaEntity> areaDict = null;
var areaIds = scenes.Where(x => x.AreaId.HasValue).Select(x => x.AreaId.Value!).ToHashSet();
if (areaIds.Count > 0)
{
var areas = await _kpiAreaRepository.GetListAsync(x => areaIds.Contains(x.Id));
areaDict = areas.ToDictionary(x => x.Id);
}
// 6.生成预警明细,手动赋予EsId,规则版本号,截止轨迹状态名称
addDetails.ForEach(x =>
{
@ -1193,7 +1183,7 @@ public class TransportWarningHandler : ITransportWarningHandler, ITransientDepen
var scene = sceneDict[x.WarningSceneId]; //一定存在
x.Version = rule.Version;
x.WarningName = rule.Name;
x.WarningRuleDescription = x.GetWarningRuleDescription(scene, ruleItemDict[x.WarningSceneRuleItemId], areaDict?.GetValueOrDefault(scene.AreaId ?? 0));
x.WarningRuleDescription = x.GetWarningRuleDescription(scene, ruleItemDict[x.WarningSceneRuleItemId]);
});
await _warningDetailsEsRepository.BulkInsertTransportWarningDetailsAsync(addDetails);

View File

@ -1,7 +1,6 @@
using TrackCenter.Application.Dtos.Warning.Transport;
using TrackCenter.Domain.Aggregates.OrderAggregate;
using TrackCenter.Domain.Aggregates.WarningAggregate.Transport;
using TrackCenter.Domain.Dtos.Forewarning;
namespace TrackCenter.Application.Services.Warning.Model;
@ -9,16 +8,11 @@ public sealed class TransportWarningSceneBO
{
public int Id { get; }
public int WarningId { get; }
public string? CargoType { get; }
public string? Months { get; }
public int? AreaId { get; }
public bool? IsTransit { get; }
public string? LeavePort { get; }
/// <summary>产品编码(单一)</summary>
/// <summary>销售产品编码(单一)</summary>
public string? ProductCode { get; }
/// <summary>国家二字码(单一)</summary>
/// <summary>到达国家二字码(单一)</summary>
public string? CountryCode { get; }
/// <summary>考核总时效(小时)</summary>
@ -27,22 +21,12 @@ public sealed class TransportWarningSceneBO
public TransportWarningSceneBO(
int id,
int warningId,
string? cargoType,
string? months,
int? areaId,
bool? isTransit,
string? leavePort,
string? productCode,
string? countryCode = null,
float? assessmentTotalTimeSpan = null)
{
Id = id;
WarningId = warningId;
CargoType = cargoType;
Months = months;
AreaId = areaId;
IsTransit = isTransit;
LeavePort = leavePort;
ProductCode = string.IsNullOrWhiteSpace(productCode) ? null : productCode.Trim();
CountryCode = NormalizeSingleCountryCode(countryCode);
AssessmentTotalTimeSpan = assessmentTotalTimeSpan;
@ -51,10 +35,8 @@ public sealed class TransportWarningSceneBO
/// <summary>
/// 命中:订单产品 = 配置产品;到达国家 = 配置国家(一对一)。
/// </summary>
public bool CanHitScene(OrderEntity order, List<KpiAreaInfo>? ruleAreas = null)
public bool CanHitScene(OrderEntity order)
{
_ = ruleAreas;
if (string.IsNullOrWhiteSpace(ProductCode) || string.IsNullOrWhiteSpace(order.ProductCode))
return false;
@ -72,11 +54,6 @@ public sealed class TransportWarningSceneBO
return new TransportWarningSceneEntity(
bo.Id,
bo.WarningId,
bo.CargoType,
bo.Months,
bo.AreaId,
bo.IsTransit,
bo.LeavePort,
bo.ProductCode,
bo.CountryCode,
bo.AssessmentTotalTimeSpan
@ -90,11 +67,6 @@ public sealed class TransportWarningSceneBO
return new TransportWarningSceneBO(
entity.Id,
entity.WarningId,
entity.CargoType,
entity.Months,
entity.AreaId,
entity.IsTransit,
entity.LeavePort,
entity.ProductCode,
entity.CountryCode,
entity.AssessmentTotalTimeSpan
@ -109,11 +81,6 @@ public sealed class TransportWarningSceneBO
return new TransportWarningSceneBO(
input.Id,
input.WarningId,
null,
null,
null,
null,
null,
input.ProductCode,
input.CountryCode,
input.AssessmentTotalTimeSpan

View File

@ -6,7 +6,6 @@ using TrackCenter.Application.Caching;
using TrackCenter.Application.Helpers;
using TrackCenter.Application.Services.Warning.Handlers;
using TrackCenter.Application.Services.Warning.Model;
using TrackCenter.Domain.Aggregates.KPIAreaAggregate;
using TrackCenter.Domain.Aggregates.OrderAggregate;
using TrackCenter.Domain.Aggregates.TrackDetailsAggregate;
using TrackCenter.Domain.Aggregates.WarningAggregate;
@ -23,7 +22,6 @@ namespace TrackCenter.Application.Services.Warning;
public class TransportWarningService : ApplicationServiceBase
{
private readonly IOrderRepository _orderRepository;
private readonly IKpiAreaRepository _kpiAreaRepository;
private readonly IWarningRuleRepository _warningRuleRepository;
private readonly IWarningDetailsEsRepository _warningDetailsEsRepository;
private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
@ -33,7 +31,6 @@ public class TransportWarningService : ApplicationServiceBase
public TransportWarningService(
IOrderRepository orderRepository,
IKpiAreaRepository kpiAreaRepository,
IWarningRuleRepository warningRuleRepository,
IWarningDetailsEsRepository warningDetailsEsRepository,
ITrackDetailsEsRepository trackDetailsEsRepository,
@ -43,7 +40,6 @@ public class TransportWarningService : ApplicationServiceBase
)
{
_orderRepository = orderRepository;
_kpiAreaRepository = kpiAreaRepository;
_warningRuleRepository = warningRuleRepository;
_warningDetailsEsRepository = warningDetailsEsRepository;
_trackDetailsEsRepository = trackDetailsEsRepository;
@ -63,37 +59,14 @@ public class TransportWarningService : ApplicationServiceBase
var entities = await _warningRuleRepository.GetTransportSceneAsync(input.WarningId);
if (entities.Count == 0) return Empty<TransportWarningSceneDto>.List;
var areaIds = entities
.Select(x => x.AreaId)
.Where(x => x > 0)
.Select(x => x!.Value)
.ToHashSet();
Dictionary<int, string>? areaNameDict = null;
if (areaIds.Count > 0)
{
var areas = await _kpiAreaRepository.GetListAsync(x => areaIds.Contains(x.Id), y => new
{
y.Id,
y.Name
});
areaNameDict = areas.ToDictionary(x => x.Id, y => y.Name);
}
var map = entities.Select(x => new TransportWarningSceneDto
{
Id = x.Id,
WarningId = x.WarningId,
Summary = BuildSummary(x),
IsTransit = x.IsTransit,
CargoType = x.CargoType,
LeavePort = x.LeavePort,
ProductCode = x.ProductCode,
CountryCode = x.CountryCode,
AssessmentTotalTimeSpan = x.AssessmentTotalTimeSpan,
Months = x.Months,
AreaId = x.AreaId,
AreaName = x.AreaId.HasValue ? areaNameDict?.GetValueOrDefault(x.AreaId.Value) : null
AssessmentTotalTimeSpan = x.AssessmentTotalTimeSpan
});
return map.ToList();

View File

@ -1,75 +0,0 @@
using Fake.Application.Dtos;
using TrackCenter.Domain.Dtos.Forewarning;
namespace TrackCenter.Domain.Aggregates.KPIAreaAggregate;
public interface IKpiAreaRepository : IBasicRepository<RuleAreaEntity>
{
/// <summary>
/// 创建分区
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
ValueTask<int> CreateAreaAsync(RuleAreaEntity entity);
/// <summary>
/// 添加分区信息
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
ValueTask<int> AddAreaInfoAsync(RuleAreaInfoEntity entity);
/// <summary>
/// 删除分区信息
/// </summary>
/// <param name="areaInfoId">分区信息id</param>
/// <returns></returns>
Task<int> DeleteAreaInfo(int areaInfoId);
/// <summary>
/// 删除分区
/// </summary>
/// <param name="areaId">分区id</param>
/// <returns></returns>
ValueTask DeleteArea(int areaId);
/// <summary>
/// 更新区域信息
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
Task<int> UpdateAreaInfoAsync(RuleAreaInfoEntity entity);
/// <summary>
/// 获得分区
/// </summary>
/// <param name="query"></param>
/// <returns></returns>
Task<PagedResult<AreaDto>> GetAreas(QueryAreaRequest query);
/// <summary>
/// 获取分区信息
/// </summary>
/// <param name="query"></param>
/// <returns></returns>
Task<PagedResult<RuleAreaInfoDto>> GetAreaInfos(QueryAreaInfoRequest query);
/// <summary>
/// 获取分区信息通过id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
Task<RuleAreaInfoEntity?> GetAreaInfoById(int id);
/// <summary>
/// 获取所有区域信息
/// </summary>
/// <returns></returns>
List<KpiAreaInfo>? GetAreaInfosByAreaId(int areaId);
/// <summary>
/// 获取所有区域信息
/// </summary>
/// <returns></returns>
Task<Dictionary<int, List<KpiAreaInfo>>> GetAreaInfosDictByAreaId(HashSet<int> areaIds);
}

View File

@ -1,52 +0,0 @@
using Fake.Domain.Entities;
using Fake.Domain.Entities.Auditing;
namespace TrackCenter.Domain.Aggregates.KPIAreaAggregate;
[SugarTable("t_area", TableDescription = "KPI分区主表")]
public class RuleAreaEntity : AggregateRoot<int>, IHasCreateUserId<int>, IHasCreateTime, IHasUpdateUserId<int>, IHasUpdateTime
{
/// <summary>
/// 自增主键
/// </summary>
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "自增主键")]
public int Id { get; set; }
/// <summary>
/// 应用
/// </summary>
[SugarColumn(ColumnName = "AppKey", ColumnDescription = "应用")]
public string AppKey { get; set; }
/// <summary>
/// 分区名称KPI名称
/// </summary>
[SugarColumn(ColumnName = "Name", Length = 64, ColumnDescription = "分区名称KPI名称")]
public string Name { get; set; }
/// <summary>
/// 创建人
/// </summary>
[SugarColumn(ColumnName = "CreateUserId", ColumnDescription = "创建人")]
public int CreateUserId { get; set; }
/// <summary>
/// 创建时间
/// </summary>
[SugarColumn(ColumnName = "CreateTime", ColumnDescription = "创建时间")]
public DateTime CreateTime { get; set; }
/// <summary>
/// 更新人
/// </summary>
[SugarColumn(ColumnName = "UpdateUserId", ColumnDescription = "更新人")]
public int UpdateUserId { get; set; }
/// <summary>
/// 更新时间
/// </summary>
[SugarColumn(ColumnName = "UpdateTime", ColumnDescription = "更新时间")]
public DateTime UpdateTime { get; set; }
[SugarColumn(IsIgnore = true)] public List<RuleAreaInfoEntity> AreaInfos { get; set; }
}

View File

@ -1,80 +0,0 @@
using Fake.Domain.Entities;
using Fake.Domain.Entities.Auditing;
namespace TrackCenter.Domain.Aggregates.KPIAreaAggregate;
[SugarTable("t_area_details", TableDescription = "kpi 区域子表")]
public class RuleAreaInfoEntity : Entity<int>, IHasCreateUserId<int>, IHasCreateTime, IHasUpdateUserId<int>, IHasUpdateTime
{
/// <summary>
/// 自增主键
/// </summary>
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "自增主键")]
public int Id { get; set; }
/// <summary>
/// t_rule_area 表id
/// </summary>
[SugarColumn(ColumnName = "AreaId", ColumnDescription = "t_rule_area 表id")]
public int AreaId { get; set; }
/// <summary>
/// 国家或地区二字码
/// </summary>
[SugarColumn(ColumnName = "CountryCode", Length = 128, ColumnDescription = "国家或地区二字码")]
public string CountryCode { get; set; }
/// <summary>
/// 国家或地区名称
/// </summary>
[SugarColumn(ColumnName = "CountryName", Length = 128, ColumnDescription = "国家或地区名称")]
public string CountryName { get; set; }
/// <summary>
/// 州或者省份
/// </summary>
[SugarColumn(ColumnName = "Province", Length = 128, IsNullable = true, ColumnDescription = "州或者省份")]
public string Province { get; set; }
/// <summary>
/// 城市
/// </summary>
[SugarColumn(ColumnName = "City", Length = 128, IsNullable = true, ColumnDescription = "城市")]
public string City { get; set; }
/// <summary>
/// 起始邮编
/// </summary>
[SugarColumn(ColumnName = "LeftPostcode", Length = 10, IsNullable = true, ColumnDescription = "起始邮编")]
public string LeftPostcode { get; set; }
/// <summary>
/// 截止邮编
/// </summary>
[SugarColumn(ColumnName = "RightPostcode", Length = 10, IsNullable = true, ColumnDescription = "截止邮编")]
public string RightPostcode { get; set; }
/// <summary>
/// 创建人
/// </summary>
[SugarColumn(ColumnName = "CreateUserId", ColumnDescription = "创建人")]
public int CreateUserId { get; set; }
/// <summary>
/// 创建时间
/// </summary>
[SugarColumn(ColumnName = "CreateTime", ColumnDescription = "创建时间")]
public DateTime CreateTime { get; set; }
/// <summary>
/// 更新人
/// </summary>
[SugarColumn(ColumnName = "UpdateUserId", IsNullable = false, ColumnDescription = "更新人")]
public int UpdateUserId { get; set; }
/// <summary>
/// 更新时间
/// </summary>
[SugarColumn(ColumnName = "UpdateTime", IsNullable = false, ColumnDescription = "更新时间")]
public DateTime UpdateTime { get; set; }
}

View File

@ -1,6 +1,5 @@
using System.Text;
using Nest;
using TrackCenter.Domain.Aggregates.KPIAreaAggregate;
using TrackCenter.Domain.Aggregates.TrackDetailsAggregate;
using TrackCenter.Domain.Consts;
using TrackCenter.Domain.SeedWork;
@ -129,33 +128,17 @@ public sealed class TransportWarningDetailsIndex : IdBaseIndex
return Status;
}
// 预警规则描述,创建预警明细,更新场景(需要重新匹配),更新规则项目(需要重新匹配),更新规则区域名称
// todo:如果更新了规则区域名称不会同步到预警明细的描述中,出现预警明细和对于的规则区域名称不一致,考虑规则存缓存动态生成预警描述
public string GetWarningRuleDescription(TransportWarningSceneEntity scene, TransportWarningSceneRuleItemEntity ruleItem, RuleAreaEntity? ruleArea)
// 预警规则描述,创建预警明细,更新场景(需要重新匹配),更新规则项目(需要重新匹配)
public string GetWarningRuleDescription(TransportWarningSceneEntity scene, TransportWarningSceneRuleItemEntity ruleItem)
{
var res = new StringBuilder("{");
// 起始轨迹状态-截止轨迹状态
res.Append($"{StartTrackStatus}-{EndTrackStatus}");
// 货物类型 (普货/危险品/...)
if (!string.IsNullOrWhiteSpace(scene.CargoType))
res.Append($",{scene.CargoType}");
// 月份 (1/3/5/...)
if (!string.IsNullOrWhiteSpace(scene.Months))
res.Append($",{scene.Months}月份");
// 区域名称 (美国xxx区域)
if (ruleArea != null)
res.Append($",{ruleArea.Name}");
// 是否中转(中转/直飞)
if (scene.IsTransit != null)
res.Append($",{(scene.IsTransit ?? false ? "中转" : "直飞")}");
// 出发港(xxx港)
if (!string.IsNullOrWhiteSpace(scene.LeavePort))
res.Append($",{scene.LeavePort}");
// 产品代码(xxx)
if (!string.IsNullOrWhiteSpace(scene.ProductCode))
res.Append($",{scene.ProductCode}");
// 国家(US)
// 到达国家(US)
if (!string.IsNullOrWhiteSpace(scene.CountryCode))
res.Append($",{scene.CountryCode}");
// 考核总时效

View File

@ -3,39 +3,26 @@ using TrackCenter.Domain.SeedWork;
namespace TrackCenter.Domain.Aggregates.WarningAggregate.Transport;
// 运输时效场景
[SugarTable("t_warning_transport_scene", TableDescription = "运输时效规则场景")]
/// <summary>
/// 运输时效场景:一销售产品 + 一到达国家 + 考核总时效。
/// </summary>
[SugarTable("t_warning_transport_scene", TableDescription = "运输时效场景(产品+国家+考核总时效)")]
public sealed class TransportWarningSceneEntity : FullAuditedEntity<int, int>
{
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
[SugarColumn(ColumnName = "WarningId", ColumnDescription = "预警规则id")]
[SugarColumn(ColumnName = "WarningId", ColumnDescription = "预警规则主体Id(t_warning.Id,运输时效为 AppKey 级方案)")]
public int WarningId { get; set; }
[SugarColumn(ColumnName = "IsTransit", ColumnDescription = "是否中转", IsNullable = true)]
public bool? IsTransit { get; set; } //历史字段
[SugarColumn(ColumnName = "ProductCode", ColumnDescription = "销售产品编码(单一,命中订单产品)", IsNullable = true)]
public string? ProductCode { get; set; }
[SugarColumn(ColumnName = "CargoType", ColumnDescription = "货物类型", IsNullable = true)]
public string? CargoType { get; set; } //历史字段
[SugarColumn(ColumnName = "CountryCode", ColumnDescription = "到达国家二字码(单一,命中订单到达国家)", IsNullable = true, Length = 16)]
public string? CountryCode { get; set; }
[SugarColumn(ColumnName = "LeavePort", ColumnDescription = "起运港口", IsNullable = true)]
public string? LeavePort { get; set; } //历史字段
[SugarColumn(ColumnName = "ProductCode", ColumnDescription = "产品编码", IsNullable = true)]
public string? ProductCode { get; set; } //单一销售产品
[SugarColumn(ColumnName = "CountryCode", ColumnDescription = "国家二字码(单一)", IsNullable = true, Length = 16)]
public string? CountryCode { get; set; } //单一国家二字码
[SugarColumn(ColumnName = "AssessmentTotalTimeSpan", ColumnDescription = "考核总时效(小时)", IsNullable = true)]
public float? AssessmentTotalTimeSpan { get; set; } //考核总时效
[SugarColumn(ColumnName = "Months", ColumnDescription = "月份", IsNullable = true)]
public string? Months { get; set; } //历史字段
[SugarColumn(ColumnName = "AreaId", ColumnDescription = "区域id", IsNullable = true)]
public int? AreaId { get; set; } //历史字段
[SugarColumn(ColumnName = "AssessmentTotalTimeSpan", ColumnDescription = "考核总时效(小时;前端按天录入后×24入库)", IsNullable = true)]
public float? AssessmentTotalTimeSpan { get; set; }
public TransportWarningSceneEntity()
{
@ -44,22 +31,12 @@ public sealed class TransportWarningSceneEntity : FullAuditedEntity<int, int>
public TransportWarningSceneEntity(
int id,
int warningId,
string? cargoType,
string? months,
int? areaId,
bool? isTransit,
string? leavePort,
string? productCode,
string? countryCode = null,
float? assessmentTotalTimeSpan = null)
{
Id = id;
WarningId = warningId;
CargoType = cargoType;
Months = months;
AreaId = areaId;
IsTransit = isTransit;
LeavePort = leavePort;
ProductCode = productCode;
CountryCode = countryCode;
AssessmentTotalTimeSpan = assessmentTotalTimeSpan;

View File

@ -4,16 +4,16 @@ using TrackCenter.Domain.SeedWork;
namespace TrackCenter.Domain.Aggregates.WarningAggregate.Transport;
// 运输时效场景规则项
[SugarTable("t_warning_transport_scene_rule_item", TableDescription = "运输时效规则场景规则项")]
[SugarTable("t_warning_transport_scene_rule_item", TableDescription = "运输时效场景分段规则项")]
public sealed class TransportWarningSceneRuleItemEntity : FullAuditedEntity<int, int>
{
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
[SugarColumn(ColumnName = "WarningId", ColumnDescription = "预警规则id")]
[SugarColumn(ColumnName = "WarningId", ColumnDescription = "预警规则主体Id(t_warning.Id)")]
public int WarningId { get; set; }
[SugarColumn(ColumnName = "TransportWarningSceneId", ColumnDescription = "运输场景id")]
[SugarColumn(ColumnName = "TransportWarningSceneId", ColumnDescription = "运输时效场景Id(t_warning_transport_scene.Id)")]
public int TransportWarningSceneId { get; set; }
[SugarColumn(ColumnName = "StartTrackStatusId", ColumnDescription = "起始轨迹状态Id")]

View File

@ -14,8 +14,8 @@ public sealed class WarningRuleEntity : FullAuditedAggregateRoot<int, int>
[SugarColumn(ColumnName = "AppKey", ColumnDescription = "应用")]
public string AppKey { get; set; } //应用
[SugarColumn(ColumnName = "Customer", ColumnDescription = "客户")]
public string Customer { get; set; } //客户
[SugarColumn(ColumnName = "Customer", ColumnDescription = "客户(运输时效固定空串;回传/完整预警按客户匹配)")]
public string Customer { get; set; } //客户(运输时效固定空串;回传/完整预警按客户匹配)
// [SugarColumn(ColumnName = "CustomName", ColumnDescription = "客户名称")]
// public string CustomName { get; set; } //冗余客户简称,用于查询

View File

@ -32,11 +32,6 @@ public partial class GlobalConst
/// </summary>
public const string OrderPullStatusScanCheckKey = "OrderPullStatusScanCheck";
/// <summary>
/// kpi区域redis key前缀
/// </summary>
public const string KpiAreaKeyPrefix = "KpiArea";
/// <summary>
/// 城市时区redis key前缀
/// </summary>

View File

@ -1,44 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace TrackCenter.Domain.Dtos.Forewarning;
public class AddRuleAreaInfoRequest
{
/// <summary>
/// 国家二字码,必填项。
/// </summary>
[Required]
public string CountryCode { get; set; }
/// <summary>
/// 国家名称
/// </summary>
[Required]
public string CountryName { get; set; }
/// <summary>
/// 省份名称,可为空。
/// </summary>
public string? Province { get; set; }
/// <summary>
/// 城市名称,可为空。
/// </summary>
public string? City { get; set; }
/// <summary>
/// 左侧邮政编码,可为空。
/// </summary>
public string? LeftPostCode { get; set; }
/// <summary>
/// 右侧邮政编码,可为空。
/// </summary>
public string? RightPostCode { get; set; }
/// <summary>
/// 区域ID,必填项。
/// </summary>
[Required]
public int AreaId { get; set; }
}

View File

@ -1,29 +0,0 @@
namespace TrackCenter.Domain.Dtos.Forewarning;
public class AreaDto
{
/// <summary>
/// 区域id
/// </summary>
public int Id { get; set; }
/// <summary>
/// 应用
/// </summary>
public string AppKey { get; set; }
/// <summary>
/// 系统名称
/// </summary>
public string SystemName { get; set; }
/// <summary>
/// 区域名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 更新时间
/// </summary>
public DateTime UpdateTime { get; set; }
}

View File

@ -1,46 +0,0 @@
namespace TrackCenter.Domain.Dtos.Forewarning;
public class RuleAreaInfoDto
{
/// <summary>
/// 分区信息id
/// </summary>
public int Id { get; set; }
/// <summary>
/// 分区id
/// </summary>
public int AreaId { get; set; }
/// <summary>
/// 国家或地区 二字码
/// </summary>
public string CountryCode { get; set; }
/// <summary>
/// 国家名称
/// </summary>
public string CountryName { get; set; }
/// <summary>
/// 国家id
/// </summary>
public int CountryId { get; set; }
/// <summary>
/// 省份
/// </summary>
public string Province { get; set; }
/// <summary>
/// 城市
/// </summary>
public string City { get; set; }
/// <summary>
/// 开始邮编
/// </summary>
public string LeftPostcode { get; set; }
public string RightPostcode { get; set; }
}

View File

@ -1,18 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace TrackCenter.Domain.Dtos.Forewarning;
public class CreateRuleAreaRequest
{
/// <summary>
/// 系统id
/// </summary>
[Required]
public string AppKey { get; set; }
/// <summary>
/// 名称
/// </summary>
[Required]
public string Name { get; set; }
}

View File

@ -1,31 +0,0 @@
namespace TrackCenter.Domain.Dtos.Forewarning;
public class KpiAreaInfo
{
public int AreaId { get; set; }
/// <summary>
/// 国家或地区
/// </summary>
public string CountryCode { get; set; } = null!;
/// <summary>
/// 省份
/// </summary>
public string? Province { get; set; }
/// <summary>
/// 城市
/// </summary>
public string? City { get; set; }
/// <summary>
/// 开始邮编
/// </summary>
public string? LeftPostcode { get; set; }
/// <summary>
/// 截止邮编
/// </summary>
public string? RightPostcode { get; set; }
}

View File

@ -1,9 +0,0 @@
namespace TrackCenter.Domain.Dtos.Forewarning;
public class QueryAreaInfoRequest : PageInfoInput
{
/// <summary>
/// 区域id
/// </summary>
public int AreaId { get; set; }
}

View File

@ -1,14 +0,0 @@
namespace TrackCenter.Domain.Dtos.Forewarning;
public class QueryAreaRequest : PageInfoInput
{
/// <summary>
/// 分区名称
/// </summary>
public string? Name { get; set; }
/// <summary>
/// 应用
/// </summary>
public string? AppKey { get; set; }
}

View File

@ -1,46 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace TrackCenter.Domain.Dtos.Forewarning;
/// <summary>
/// 更新规则区域信息请求
/// </summary>
public class UpdateRuleAreaInfoRequest
{
/// <summary>
/// 区域信息ID
/// </summary>
public int Id { get; set; }
/// <summary>
/// 国家二字码,必填项。
/// </summary>
[Required]
public string CountryCode { get; set; }
/// <summary>
/// 国家名称,必填项。
/// </summary>
[Required]
public string CountryName { get; set; }
/// <summary>
/// 省份名称,可为空。
/// </summary>
public string? Province { get; set; }
/// <summary>
/// 城市名称,可为空。
/// </summary>
public string? City { get; set; }
/// <summary>
/// 左侧邮政编码,可为空。
/// </summary>
public string? LeftPostCode { get; set; }
/// <summary>
/// 右侧邮政编码,可为空。
/// </summary>
public string? RightPostCode { get; set; }
}

View File

@ -1,17 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace TrackCenter.Domain.Dtos.Forewarning;
public class UpdateRuleAreaRequest
{
/// <summary>
/// 名称
/// </summary>
[Required]
public string Name { get; set; }
/// <summary>
/// 区域id
/// </summary>
public int Id { get; set; }
}

View File

@ -1,5 +0,0 @@
namespace TrackCenter.Repository.Repositories;
public class KpiAreaInfoRepository
{
}

View File

@ -1,130 +0,0 @@
using TrackCenter.Domain;
using TrackCenter.Domain.Aggregates.KPIAreaAggregate;
using TrackCenter.Domain.Dtos.Forewarning;
using TrackCenter.Domain.VEntities;
namespace TrackCenter.Repository.Repositories;
public class KpiAreaRepository : BasicRepository<RuleAreaEntity>, IKpiAreaRepository, ITransientDependency
{
public async ValueTask<int> CreateAreaAsync(RuleAreaEntity entity)
{
return await InsertReturnIdentityAsync(entity);
}
public async ValueTask<int> AddAreaInfoAsync(RuleAreaInfoEntity entity)
{
return await Context.Insertable(entity).ExecuteReturnIdentityAsync();
}
public async ValueTask DeleteArea(int areaId)
{
using var transaction = TransactionHelper.GetReadCommitted();
await DeleteAsync(x => x.Id == areaId);
await Context.Deleteable<RuleAreaInfoEntity>().Where(x => x.AreaId == areaId).ExecuteCommandAsync();
transaction.Complete();
}
public Task<int> DeleteAreaInfo(int areaInfoId)
{
return Context.Deleteable<RuleAreaInfoEntity>().Where(val => val.Id == areaInfoId).ExecuteCommandAsync();
}
public Task<int> UpdateAreaInfoAsync(RuleAreaInfoEntity entity)
{
return Context.Updateable(entity).ExecuteCommandAsync();
}
/// <summary>
/// 获取分区
/// </summary>
/// <param name="query"></param>
/// <returns></returns>
public async Task<PagedResult<AreaDto>> GetAreas(QueryAreaRequest query)
{
return await Context.Queryable<RuleAreaEntity>()
.WhereIF(!string.IsNullOrEmpty(query.Name), area => area.Name.Contains(query.Name!))
.OrderBy(area => area.UpdateTime, OrderByType.Desc)
.Select<AreaDto>(area => new AreaDto()
{
Id = area.Id,
Name = area.Name,
AppKey = area.AppKey,
UpdateTime = area.CreateTime
})
.ToPagedListAsync(query.PageIndex, query.PageSize);
}
/// <summary>
/// 获得分区信息
/// </summary>
/// <param name="query"></param>
/// <returns></returns>
public async Task<PagedResult<RuleAreaInfoDto>> GetAreaInfos(QueryAreaInfoRequest query)
{
return await Context.Queryable<RuleAreaInfoEntity>()
//.InnerJoin<VCountryEntity>((x, c) => x.CountryCode == c.Digit2Code)
.Where(x => x.AreaId == query.AreaId)
.OrderBy(x => x.UpdateTime, OrderByType.Desc)
.Select<RuleAreaInfoDto>((x) => new RuleAreaInfoDto()
{
Id = x.Id,
AreaId = x.AreaId,
City = x.City,
//CountryId = c.Id,
CountryCode = x.CountryCode,
CountryName = x.CountryName,
LeftPostcode = x.LeftPostcode,
RightPostcode = x.RightPostcode,
Province = x.Province
})
.ToPagedListAsync(query.PageIndex, query.PageSize);
}
public Task<RuleAreaInfoEntity?> GetAreaInfoById(int id)
{
return Context.Queryable<RuleAreaInfoEntity>()
.FirstAsync(val => val.Id == id)!;
}
/// <summary>
/// 获取所有区域信息
/// </summary>
/// <returns></returns>
public List<KpiAreaInfo> GetAreaInfosByAreaId(int areaId)
{
return Context.Queryable<RuleAreaInfoEntity>()
.InnerJoin<RuleAreaEntity>((r, i) => r.AreaId == i.Id)
.Where((r, i) => r.AreaId == areaId)
.Select((r, i) => new KpiAreaInfo
{
AreaId = r.AreaId,
CountryCode = r.CountryCode,
LeftPostcode = r.LeftPostcode,
City = r.City,
Province = r.Province,
RightPostcode = r.RightPostcode
})
.ToList();
}
public async Task<Dictionary<int, List<KpiAreaInfo>>> GetAreaInfosDictByAreaId(HashSet<int> areaIds)
{
var list = await Context.Queryable<RuleAreaInfoEntity>()
.InnerJoin<RuleAreaEntity>((r, i) => r.AreaId == i.Id)
.Where((r, i) => areaIds.Contains(i.Id))
.Select((r, i) => new KpiAreaInfo
{
AreaId = r.AreaId,
CountryCode = r.CountryCode,
LeftPostcode = r.LeftPostcode,
City = r.City,
Province = r.Province,
RightPostcode = r.RightPostcode
})
.ToListAsync();
return list.GroupBy(x => x.AreaId)
.ToDictionary(x => x.Key, y => y.ToList());
}
}