123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- using Hotline.Caching.Interfaces;
- using Hotline.File;
- using Hotline.FlowEngine.Workflows;
- using Hotline.Orders;
- using Hotline.Repository.SqlSugar.Extensions;
- using Hotline.Repository.SqlSugar.Ts;
- using Hotline.Settings.TimeLimits;
- using Hotline.Share.Dtos;
- using Hotline.Share.Dtos.File;
- using Hotline.Share.Dtos.FlowEngine;
- using Hotline.Share.Dtos.FlowEngine.Workflow;
- using Hotline.Share.Dtos.Order;
- using Hotline.Share.Dtos.Settings;
- using Hotline.Share.Enums.Order;
- using Hotline.Share.Enums.Settings;
- using Hotline.Tools;
- using Hotline.Users;
- using MapsterMapper;
- using XF.Domain.Constants;
- using XF.Domain.Dependency;
- using XF.Domain.Entities;
- using XF.Domain.Exceptions;
- using XF.Domain.Repository;
- namespace Hotline.Application.Orders;
- public class OrderApplication : IOrderApplication, IScopeDependency
- {
- private readonly IOrderDomainService _orderDomainService;
- private readonly IWorkflowDomainService _workflowDomainService;
- private readonly IOrderRepository _orderRepository;
- private readonly ITimeLimitDomainService _timeLimitDomainService;
- private readonly IMapper _mapper;
- private readonly ISystemSettingCacheManager _systemSettingCacheManager;
- private readonly IRepository<OrderWord> _orderWrodRepository;
- private readonly IRepositoryTextSearch<OrderTs> _repositoryts;
- private readonly IFileRepository _fileRepository;
- public OrderApplication(
- IOrderDomainService orderDomainService,
- IOrderRepository orderRepository,
- IWorkflowDomainService workflowDomainService,
- ITimeLimitDomainService timeLimitDomainService,
- ISystemSettingCacheManager systemSettingCacheManager,
- IMapper mapper,
- IRepository<OrderWord> orderWrodRepository,
- IRepositoryTextSearch<OrderTs> repositoryts,
- IFileRepository fileRepository
- )
- {
- _orderDomainService = orderDomainService;
- _workflowDomainService = workflowDomainService;
- _orderRepository = orderRepository;
- _timeLimitDomainService = timeLimitDomainService;
- _mapper = mapper;
- _systemSettingCacheManager = systemSettingCacheManager;
- _orderWrodRepository = orderWrodRepository;
- _repositoryts = repositoryts;
- _fileRepository = fileRepository;
- }
- /// <summary>
- /// 更新工单办理期满时间
- /// 1.更新工单 2.更新流程 3.推送省平台
- /// </summary>
- /// <returns></returns>
- public async Task DelayOrderExpiredTimeAsync(string orderId, int timeCount, ETimeType timeType, CancellationToken cancellationToken)
- {
- var order = await _orderDomainService.GetOrderAsync(orderId, cancellationToken: cancellationToken);
- var expiredTimeConfig =
- _timeLimitDomainService.CalcEndTime(order.ExpiredTime.Value, new TimeConfig(timeCount, timeType), order.AcceptTypeCode);
- order.TimeLimit = expiredTimeConfig.TimeText;
- order.TimeLimitCount = expiredTimeConfig.Count;
- order.TimeLimitUnit = expiredTimeConfig.TimeType;
- order.ExpiredTime = expiredTimeConfig.ExpiredTime;
- order.NearlyExpiredTime = expiredTimeConfig.NearlyExpiredTime;
- //if (string.IsNullOrEmpty(order.WorkflowId))
- // throw new UserFriendlyException("该工单流程id异常");
- //var workflow = await _workflowDomainService.GetWorkflowAsync(order.WorkflowId, cancellationToken: cancellationToken);
- //await _workflowDomainService.UpdateExpiredTimeAsync(workflow, expiredTimeConfig.ExpiredTime,
- // expiredTimeConfig.TimeText, expiredTimeConfig.Count, expiredTimeConfig.TimeType, expiredTimeConfig.NearlyExpiredTime, cancellationToken);
- await _orderRepository.UpdateAsync(order, cancellationToken);
- }
- /// <summary>
- /// 新增工单办理流程记录
- /// </summary>
- public async Task AddOrderTracesAsync(string orderId, ICollection<WorkflowTraceDto> traces, CancellationToken cancellationToken)
- {
- var order = await _orderRepository.GetAsync(orderId, cancellationToken);
- if (order is null)
- throw new UserFriendlyException("工单不存在");
- if (string.IsNullOrEmpty(order.WorkflowId))
- throw new UserFriendlyException("工单未开启流程");
- await _workflowDomainService.AddTracesAsync(order.WorkflowId, _mapper.Map<List<WorkflowTrace>>(traces),
- cancellationToken);
- }
- /// <summary>
- /// 撤销工单
- /// </summary>
- public async Task CancelOrderAsync(string orderId, string opinion, CancellationToken cancellationToken)
- {
- var order = await _orderRepository.GetAsync(orderId, cancellationToken);
- if (order is null)
- throw new UserFriendlyException("工单不存在");
- if (!string.IsNullOrEmpty(order.WorkflowId))
- {
- //结束流程
- await _workflowDomainService.TerminateAsync(new TerminateDto
- {
- WorkflowId = order.WorkflowId,
- Opinion = opinion
- }, cancellationToken);
- }
- //归档工单
- var now = DateTime.Now;
- var handleDuration = order.StartTime.HasValue
- ? _timeLimitDomainService.CalcWorkTime(order.StartTime.Value,
- now, order.ProcessType is EProcessType.Zhiban)
- : 0;
- var fileDuration = order.CenterToOrgTime.HasValue
- ? _timeLimitDomainService.CalcWorkTime(order.CenterToOrgTime.Value,
- now, order.ProcessType is EProcessType.Zhiban)
- : 0;
- var allDuration = order.StartTime.HasValue
- ? _timeLimitDomainService.CalcWorkTime(order.StartTime.Value, now,
- order.ProcessType is EProcessType.Zhiban)
- : 0;
- order.File(now, handleDuration, fileDuration, allDuration);
- await _orderRepository.UpdateAsync(order, cancellationToken);
- }
- /// <summary>
- /// 即将超期列表
- /// </summary>
- /// <param name="dto"></param>
- /// <param name="cancellationToken"></param>
- /// <returns></returns>
- public async Task<PagedDto<OrderDto>> GetAboutToExpireAsync(AboutToExpireListDto dto, CancellationToken cancellationToken)
- {
- var setting = _systemSettingCacheManager.GetSetting(SettingConstants.OrderAboutToExpire);
- var value = setting?.SettingValue[0];
- value = string.IsNullOrEmpty(value) ? "0" : value;
- DateTime stTime = DateTime.Now.AddDays(int.Parse(value));
- stTime = _timeLimitDomainService.WorkDay(DateTime.Now);
- DateTime stTime2 = _timeLimitDomainService.WorkDay(DateTime.Now);
- var (total, items) = await _orderRepository.Queryable(viewFilter:true)
- .WhereIF(dto.IsProvince.HasValue, x => x.IsProvince == dto.IsProvince)
- .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Title.Contains(dto.Keyword!) || x.No.Contains(dto.Keyword!))
- .Where(x => x.ExpiredTime != null &&
- x.Status != EOrderStatus.Filed && x.Status != EOrderStatus.Published && x.Status != EOrderStatus.Visited && stTime >= x.ExpiredTime.Value && stTime2 <= x.ExpiredTime.Value)
- .OrderByDescending(x => x.CreationTime)
- .ToPagedListAsync(dto.PageIndex, dto.PageSize, cancellationToken);
- return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
- }
- // /// <summary>
- // /// 即将超期节点列表
- // /// </summary>
- // /// <param name="dto"></param>
- // /// <param name="cancellationToken"></param>
- // /// <returns></returns>
- //public async Task<PagedDto<WorkflowOrderDto>> GetAboutToExpireNodeAsync(AboutToExpireListDto dto, CancellationToken cancellationToken)
- //{
- // var setting = _systemSettingCacheManager.GetSetting(SettingConstants.OrderAboutToExpire);
- // var value = setting?.SettingValue[0];
- // value = string.IsNullOrEmpty(value) ? "0" : value;
- // DateTime stTime = DateTime.Now.AddDays(int.Parse(value));
- // stTime = _timeLimitDomainService.WorkDay(DateTime.Now);
- // DateTime stTime2 = _timeLimitDomainService.WorkDay(DateTime.Now);
- // RefAsync<int> total = 0;
- // var items = await Db.Queryable<Workflow>()
- // .LeftJoin<Order>((x, o) => x.ExternalId == o.Id)
- // .Where(x => x.ModuleCode == "OrderHandle")
- // .WhereIF(dto.IsProvince.HasValue, (x, o) => o.IsProvince == dto.IsProvince)
- // .WhereIF(!string.IsNullOrEmpty(dto.Keyword), (x, o) => o.Title.Contains(dto.Keyword!) || o.No.Contains(dto.Keyword!))
- // .Where((x, o) => (int)x.Status < 20 && stTime >= x.ExpiredTime && stTime2 <= x.ExpiredTime)
- // .Select((x, o) => new WorkflowOrder { Order = o }, true)
- // .OrderByDescending(x => x.CreationTime)
- // .ToPageListAsync(dto.PageIndex, dto.PageSize, total, cancellationToken);
- // return new PagedDto<WorkflowOrderDto>(total, _mapper.Map<IReadOnlyList<WorkflowOrderDto>>(items));
- //}
- /// <summary>
- /// 已超期列表
- /// </summary>
- /// <param name="dto"></param>
- /// <param name="cancellationToken"></param>
- /// <returns></returns>
- public async Task<PagedDto<OrderDto>> GetToExpireAsync(AboutToExpireListDto dto, CancellationToken cancellationToken)
- {
- DateTime stTime = _timeLimitDomainService.WorkDay(DateTime.Now);
- var (total, items) = await _orderRepository.Queryable(viewFilter:true)
- .WhereIF(dto.IsProvince.HasValue, x => x.IsProvince == dto.IsProvince)
- .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Title.Contains(dto.Keyword!) || x.No.Contains(dto.Keyword!))
- //.WhereIF(!string.IsNullOrEmpty(dto.No), x => x.No == dto.No)
- //.WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Title.Contains(dto.Title!))
- .Where(x => x.ExpiredTime != null &&
- (((x.Status == EOrderStatus.Filed || x.Status == EOrderStatus.Published || x.Status == EOrderStatus.Visited) && x.FiledTime >= x.ExpiredTime) ||
- ((x.Status != EOrderStatus.Filed && x.Status != EOrderStatus.Published && x.Status != EOrderStatus.Visited) && stTime >= x.ExpiredTime.Value)))
- .OrderByDescending(x => x.CreationTime)
- .ToPagedListAsync(dto.PageIndex, dto.PageSize, cancellationToken);
- return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
- }
- // /// <summary>
- // /// 已超期节点列表
- // /// </summary>
- // /// <param name="dto"></param>
- // /// <param name="cancellationToken"></param>
- // /// <returns></returns>
- // public async Task<PagedDto<WorkflowOrderDto>> GetToExpireNodeAsync(AboutToExpireListDto dto, CancellationToken cancellationToken)
- // {
- // DateTime stTime = _timeLimitDomainService.WorkDay(DateTime.Now);
- //RefAsync<int> total = 0;
- //var items= await Db.Queryable<Workflow>()
- // .LeftJoin<Order>((x,o)=>x.ExternalId == o.Id)
- // .Where(x => x.ModuleCode == "OrderHandle")
- // .WhereIF(dto.IsProvince.HasValue, (x, o) => o.IsProvince == dto.IsProvince)
- // .WhereIF(!string.IsNullOrEmpty(dto.Keyword), (x, o) => o.Title.Contains(dto.Keyword!) || o.No.Contains(dto.Keyword!))
- // .Where((x,o) => (((int)x.Status >= 20 && x.EndTime >= x.ExpiredTime) || ((int)x.Status < 20 && stTime >= x.ExpiredTime)))
- // .Select((x, o) => new WorkflowOrder { Order = o }, true)
- // .OrderByDescending(x => x.CreationTime)
- // .ToPageListAsync(dto.PageIndex, dto.PageSize, total, cancellationToken);
- // return new PagedDto<WorkflowOrderDto>(total, _mapper.Map<IReadOnlyList<WorkflowOrderDto>>(items));
- // }
- /// <summary>
- /// 工单关键字分词
- /// </summary>
- /// <param name="inputStr"></param>
- /// <returns></returns>
- public async Task OrderParticiple(string inputStr, string orderId, CancellationToken cancellationToken)
- {
- var words = await _orderWrodRepository.Queryable().Where(x => x.IsEnable == 1 && x.Classify.Contains("普通标签")).Select(x => x.Tag).ToListAsync(cancellationToken);
- var res = new List<string>();
- if (words.Any()) res = ParticipleTool.SegMMDouble(inputStr, ref words);
- var participles = await _orderWrodRepository.Queryable().In(x => x.Tag, res).ToListAsync(cancellationToken);
- if (participles.Any())
- {
- //关键词
- var tags = participles.Select(x => x.Tag).ToList();
- var tagsStr = string.Join(",", tags);
- await _orderRepository.Updateable().SetColumns(x => x.TagNames == tagsStr).Where(x => x.Id == orderId).ExecuteCommandAsync(cancellationToken);
- List<string> synonyms = participles.Select(x => x.Synonym).ToList();
- if (synonyms.Any())
- {
- var synonymsStr = string.Join(",", synonyms);
- synonyms = synonymsStr.Split(",").Distinct().ToList();
- tags.AddRange(synonyms);
- }
- var vector = await _orderRepository.Queryable().Where(x => x.Id == orderId).ToListAsync(cancellationToken);
- if (vector.Any()) await _repositoryts.UpdateVectorAsync(orderId, tags, cancellationToken);
- else await _repositoryts.AddVectorAsync(orderId, DateTime.Now, tags, cancellationToken);
- }
- }
- /// <summary>
- /// 接收外部平台工单
- /// </summary>
- public Task<AddOrderResponse> ReceiveOrderFromExternalAsync(AddOrderDto dto, CancellationToken cancellationToken)
- {
- switch (dto.Source)
- {
- case ESource.ProvinceStraight:
- return ReceiveOrderFromProvinceAsync(dto, dto.Files, cancellationToken);
- case ESource.Police110:
- case ESource.CityDataExchangeLz:
- case ESource.ConvergenceMedia:
- case ESource.WebPortal:
- return ReceiveOrderFromOtherPlatformAsync(dto, dto.Files, cancellationToken);
- case ESource.Hotline:
- case ESource.HotlineImport:
- default:
- throw new ArgumentOutOfRangeException();
- }
- }
- #region private
- /// <summary>
- /// 接受外部工单(除省平台)
- /// </summary>
- /// <param name="dto"></param>
- /// <param name="cancellationToken"></param>
- /// <returns></returns>
- private async Task<AddOrderResponse> ReceiveOrderFromOtherPlatformAsync(AddOrderDto dto, List<FileDto> files, CancellationToken cancellationToken)
- {
- if (string.IsNullOrEmpty(dto.ExternalId))
- throw new UserFriendlyException("工单外部编号不能为空");
- var order = await _orderRepository.Queryable()
- .FirstAsync(d => d.ExternalId == dto.ExternalId, cancellationToken);
- if (order == null)
- {
- order = _mapper.Map<Order>(dto);
- order.InitId();
- if (files != null && files.Any())
- order.FileJson = await _fileRepository.AddFileAsync(files, order.Id, "", cancellationToken);
- await _orderDomainService.AddAsync(order, cancellationToken: cancellationToken);
- }
- else
- {
- _mapper.Map(dto, order);
- if (files != null && files.Any())
- order.FileJson = await _fileRepository.AddFileAsync(files, order.Id, "", cancellationToken);
- await _orderRepository.UpdateAsync(order, cancellationToken);
- }
- return _mapper.Map<AddOrderResponse>(order);
- }
- /// <summary>
- /// 接受省平台工单
- /// </summary>
- private async Task<AddOrderResponse> ReceiveOrderFromProvinceAsync(AddOrderDto dto, List<FileDto> files, CancellationToken cancellationToken)
- {
- if (string.IsNullOrEmpty(dto.ProvinceNo))
- throw new UserFriendlyException("无效省工单编号");
- var orderExtension = await _orderDomainService.GetOrderExtensionsAsync(dto.ProvinceNo, cancellationToken);
- var order = await _orderRepository.GetAsync(d => d.ProvinceNo == dto.ProvinceNo, cancellationToken);
- if (order is null)
- {
- order = _mapper.Map<Order>(dto);
- order.InitId();
- if (files != null && files.Any())
- order.FileJson = await _fileRepository.AddFileAsync(files, order.Id, "", cancellationToken);
- await _orderDomainService.AddAsync(order, cancellationToken: cancellationToken);
- if (orderExtension is not null)
- {
- orderExtension.Id = order.Id;
- if (dto.OrderExtension != null)
- _mapper.Map(dto.OrderExtension, orderExtension);
- await _orderDomainService.UpdateExtensionAsync(orderExtension, cancellationToken);
- }
- }
- else
- {
- _mapper.Map(dto, order);
- if (files != null && files.Any())
- order.FileJson = await _fileRepository.AddFileAsync(files, order.Id, "", cancellationToken);
- await _orderRepository.UpdateAsync(order, cancellationToken);
- if (orderExtension is not null)
- {
- orderExtension.Id = order.Id;
- if (dto.OrderExtension != null)
- _mapper.Map(dto.OrderExtension, orderExtension);
- await _orderDomainService.UpdateExtensionAsync(orderExtension, cancellationToken);
- }
- //特提(撤回至发起)
- if (!string.IsNullOrEmpty(order.WorkflowId))
- await _workflowDomainService.RecallToStartStepAsync(order.WorkflowId, "省工单重派", cancellationToken);
- }
- return _mapper.Map<AddOrderResponse>(order);
- }
- #endregion
- }
|