ComplianceServer/code/Hg.Complaint.Domain/ComplaintDomain.cs

1476 lines
70 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using DG.Core;
using Exceptionless.Models;
using Hg.Complaint.Domain.Dto.ContentModel;
using Hg.Core.Entity.Complaint;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.Extensions.DependencyInjection;
using MySqlConnector;
using Oracle.ManagedDataAccess.Client;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Security.Cryptography;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Xml.Linq;
namespace Hg.Complaint.Domain
{
internal class ComplaintDomain : IComplaintDomain
{
private readonly IServiceProvider _serviceProvider;
private readonly ComplaintEventSingleton _complaintEventSingleton;
private readonly IRedisManager _redisManager;
private readonly IConfiguration _configuration;
private readonly IHttpClient _httpClient;
private readonly IMapper _mapper;
private readonly ICacheDomain _cacheDomain;
private readonly int _retryCount = 3;
private readonly SystemConfig _systemConfig;
public ComplaintDomain(
ComplaintEventSingleton complaintEventSingleton,
IRedisManager redisManager,
IConfiguration configuration,
IMapper mapper,
IHttpClient httpClient,
ICacheDomain cacheDomain,
IServiceProvider serviceProvider)
{
_systemConfig = configuration.GetSection("SystemConfig").Get<SystemConfig>();
_complaintEventSingleton = complaintEventSingleton;
_redisManager = redisManager;
_mapper = mapper;
_httpClient = httpClient;
_configuration = configuration;
_cacheDomain = cacheDomain;
_serviceProvider = serviceProvider;
}
/// <summary>
/// 分析消极消息
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
public async Task<bool> AnalyseNegativeMessage(NegativeMessageDto dto)
{
var applyComplaint = new ApplyComplaintDto
{
Appid = dto.Corpid,
Appuserid = dto.EnternalAppuserid,
Unionid = dto.ExternalUnionid,
Deptid = dto.InternalDeptid,
CrmAppid = "",
Source = ComplaintSource.,
Resid = dto.ExternalResid,
Content = dto.ToJson(),
SignType = ComplaintSignType.,
SignWay = ComplaintSignWay.,
};
return await ApplyComplaint(applyComplaint);
}
/// <summary>
/// 申请投诉
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
public async Task<bool> ApplyComplaint(ApplyComplaintDto dto)
{
var key = CacheKeys.ComplaintMessageEnqueue;
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
Log.Information($"投诉申请日志dto:{dto.ToJson()}");
if (dto.Channel.HasValue)
{
var deptments = await _cacheDomain.GetDeptments();
var deptment = deptments.FirstOrDefault(y => y.DeptmentCampains.Any(a => dto.Channel >= a.StartCampainId && dto.Channel <= a.EndCampainId));
if (deptment != null)
{
dto.Deptid = deptment.Id;
}
}
var complaintLog = new ComplaintLog
{
Appid = dto.Appid,
Appuserid = dto.Appuserid,
Unionid = dto.Unionid,
Deptid = dto.Deptid,
CrmAppid = dto.CrmAppid,
Source = dto.Source,
Resid = dto.Resid,
Content = dto.Content,
Ctime = DateTime.Now,
IsLast = false,
SignType = dto.SignType,
SignWay = dto.SignWay,
IsCompletion = false,
Channel = dto.Channel,
Eid = dto.Eid,
Ename = dto.Ename,
Reason = dto.Reason,
};
complaintLog = await hgActionRepository.GetRepository<ComplaintLog>().InsertAsync(complaintLog);
var messageDto = _mapper.Map<ComplaintLog, ComplaintLogMessageDto>(complaintLog);
await _redisManager.EnqueueAsync(key, messageDto);
return true;
}
/// <summary>
/// 获取队列数量
/// </summary>
/// <returns></returns>
public async Task<long> GetQueue()
{
var key = CacheKeys.ComplaintMessageEnqueue;
if (!await _redisManager.ExistsAsync(key))
{
return 0;
}
return await _redisManager.CountAsync(key);
}
/// <summary>
/// 消费单个队列对象
/// </summary>
/// <returns></returns>
public async Task<ComplaintLogMessageDto> DequeueQueue()
{
var key = CacheKeys.ComplaintMessageEnqueue;
if (!await _redisManager.ExistsAsync(key))
{
return new ComplaintLogMessageDto();
}
return await _redisManager.DequeueAsync<ComplaintLogMessageDto>(key);
}
/// <summary>
/// 获取队列信息
/// </summary>
/// <returns></returns>
public async Task<List<ComplaintLogMessageDto>> GetQueues()
{
var key = CacheKeys.ComplaintMessageEnqueue;
if (!await _redisManager.ExistsAsync(key))
{
return new List<ComplaintLogMessageDto>();
}
return await _redisManager.GetListAsync<ComplaintLogMessageDto>(key);
}
/// <summary>
/// 分析投诉日志
/// </summary>
/// <param name="messageDto"></param>
/// <returns></returns>
public async Task AnalyseComplaintLog(ComplaintLogMessageDto messageDto)
{
Log.Information($"开始分析投诉日志dto:{messageDto.ToJson()}");
var key = CacheKeys.ComplaintMessageEnqueue;
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
var complaintData = await GetComplaintUser(messageDto);
var complaintUser = complaintData.Item1;
var complaintUserDept = complaintData.Item2;
if (complaintUser == null)
{
if (messageDto.RetryCount > _retryCount)
{
Log.Error($"用户数据获取失败,已重试超过{_retryCount}次dto:{messageDto.ToJson()}");
return;
}
Log.Information($"用户数据获取失败下次重试dto:{messageDto.ToJson()}");
// 丢到新的用户队列
messageDto.RetryCount++;
await _redisManager.EnqueueAsync(key, messageDto);
return;
}
if (complaintUserDept == null)
{
if (messageDto.Deptid == 0)
{
messageDto.Udid = 0;
}
else
{
if (messageDto.RetryCount > _retryCount)
{
Log.Error($"事业部组不存,已重试超过{_retryCount}次dto:{messageDto.ToJson()}");
return;
}
Log.Information($"事业部组不存下次重试dto:{messageDto.ToJson()}");
messageDto.RetryCount++;
await _redisManager.EnqueueAsync(key, messageDto);
return;
}
}
else
{
messageDto.Udid = complaintUserDept.Id;
}
var complaintLog = _mapper.Map<ComplaintLogMessageDto, ComplaintLog>(messageDto);
complaintLog.Fid = complaintUser.Id;
complaintLog.IsLast = true;
var oldLog = await hgActionRepository.GetRepository<ComplaintLog>().Query()
.Where(x => x.Udid == complaintLog.Udid && x.IsLast == true)
.FirstOrDefaultAsync();
var transaction = await hgActionRepository.BeginTransactionAsync();
try
{
// 更新是否有订单字段
if (complaintUserDept != null && !complaintUserDept.HasOrder)
{
var hasOrder = await HasOrderByResid(complaintUser.Resid, complaintUserDept.Deptid);
if (complaintUserDept.HasOrder != hasOrder)
{
complaintUserDept.HasOrder = hasOrder;
await hgActionRepository.GetRepository<ComplaintUserDept>().UpdateAsync(complaintUserDept, x => new
{
x.HasOrder
});
}
}
if (complaintUserDept != null)
{
complaintUserDept.Status = ComplaintStatus.;
await hgActionRepository.GetRepository<ComplaintUserDept>().UpdateAsync(complaintUserDept, x => new
{
x.Status
});
_complaintEventSingleton.AddComplaintEvent(new ComplaintEventDto
{
Id = complaintUserDept.Id,
Fid = complaintUserDept.Fid,
Ctime = complaintLog.Ctime
});
}
if (oldLog != null)
{
oldLog.IsLast = false;
await hgActionRepository.GetRepository<ComplaintLog>().UpdateAsync(oldLog, x => new
{
x.IsLast
});
}
complaintLog = await hgActionRepository.GetRepository<ComplaintLog>().UpdateAsync(complaintLog, x => new
{
x.Fid,
x.Udid,
x.IsLast
});
await transaction.CommitAsync();
}
catch (Exception ex)
{
await transaction.RollbackAsync();
await transaction.DisposeAsync();
Log.Error(ex, $"分析投诉日志失败dto:{messageDto.ToJson()}");
throw;
}
}
/// <summary>
/// 获取投诉用户和投诉用户归属
/// </summary>
/// <param name="complaintLog"></param>
/// <returns></returns>
private async Task<(ComplaintUser?, ComplaintUserDept?)> GetComplaintUser(ComplaintLog complaintLog)
{
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
Expression<Func<ComplaintUser, bool>> expressionComplaintUser = x => 1 == 1;
if (!string.IsNullOrEmpty(complaintLog.Appid) && !string.IsNullOrEmpty(complaintLog.Appuserid))
{
expressionComplaintUser = expressionComplaintUser.And(x => x.Appid == complaintLog.Appid && x.Appuserid == complaintLog.Appuserid);
}
else if (!string.IsNullOrEmpty(complaintLog.Resid))
{
expressionComplaintUser = expressionComplaintUser.And(x => x.Resid == complaintLog.Resid);
}
else if (!string.IsNullOrEmpty(complaintLog.Unionid))
{
expressionComplaintUser = expressionComplaintUser.And(x => x.Unionid == complaintLog.Unionid);
}
var queryComplaintUser = hgActionRepository.GetRepository<ComplaintUser>().Query()
.Where(expressionComplaintUser);
var complaintUserDept = new ComplaintUserDept();
var complaintUser = await queryComplaintUser.FirstOrDefaultAsync();
// 先判断是否有已存在的投诉用户
if (complaintUser != null)
{
complaintUserDept = await GetOrCreatComplaintUserDept(complaintUser, complaintLog);
return (complaintUser, complaintUserDept);
}
else
{
// 获取用户中心的用户信息
var user = await GetUserInfo(complaintLog.Appid, complaintLog.Appuserid, complaintLog.Resid, complaintLog.Unionid);
if (user.Item2 == null || user.Item2.Uid == 0)
{
Log.Information($"用户数据获取失败dto:{complaintLog.ToJson()}");
return (null, null);
}
complaintUser = await hgActionRepository.GetRepository<ComplaintUser>().Query()
.Where(x => x.Appid + x.Appuserid == $"{user.Item2.Appid}{user.Item2.Appuserid}")
.FirstOrDefaultAsync();
// 如果用户中心的用户信息存在,但是投诉用户不存在,则创建投诉用户
if (complaintUser == null)
{
return await CreateComplaintUser(user.Item2, complaintLog);
}
}
// 如果用户中心的用户信息存在,投诉用户也存在,则更新投诉用户信息
complaintUserDept = await GetOrCreatComplaintUserDept(complaintUser, complaintLog);
return (complaintUser, complaintUserDept);
}
/// <summary>
/// 获取用户信息
/// </summary>
/// <param name="appid"></param>
/// <param name="appuserid"></param>
/// <param name="resid"></param>
/// <param name="unionid"></param>
/// <returns></returns>
private async Task<(int, UserInfo?)> GetUserInfo(string? appid, string? appuserid, string? resid, string? unionid)
{
var userInfo = new UserInfo();
var cid = 0;
if (!string.IsNullOrEmpty(appid) && !string.IsNullOrEmpty(appuserid))
{
// 从缓存中获取用户信息
var uid = await _redisManager.ExistsAsync($"{appid}_1_{appuserid}", "UserCenter") ? await _redisManager.GetAsync<int>($"{appid}_1_{appuserid}", "UserCenter") : 0;
Log.Information($"在缓存key:【{appid}_1_{appuserid}】中获取 uid{uid}");
if (uid == 0)
{
uid = await _redisManager.ExistsAsync($"{appid}_{appuserid}", "UserCenter") ? await _redisManager.GetAsync<int>($"{appid}_{appuserid}", "UserCenter") : 0;
Log.Information($"在缓存key:【{appid}_{appuserid}】中获取 uid{uid}");
}
if (uid > 0 && await _redisManager.ExistsAsync($"user_{uid}", "UserCenter"))
{
Log.Information($"在缓存key:【user_{uid}】");
var userInfoDto = await _redisManager.GetHashAsync<UserInfoDto>($"user_{uid}", "UserCenter");
Log.Information($"在缓存key:【user_{uid}】, 获取数据:{userInfoDto.ToJson()}");
userInfo.Appuserid = userInfoDto.Appuserid;
userInfo.Appid = userInfoDto.Appid;
userInfo.Customerid = !string.IsNullOrEmpty(userInfoDto.Customerid) ? int.Parse(userInfoDto.Customerid) : 0;
cid = userInfo.Customerid;
}
// 如果uid不等于cid, 则根据cid获取用户信息
if (userInfo.Uid != cid || string.IsNullOrEmpty(userInfo.Resid))
{
userInfo = await GetUserInfoByCid(cid);
}
if (userInfo != null && string.IsNullOrEmpty(userInfo.Resid))
{
userInfo ??= await GetUserInfoBySqlCondition("customerid", cid);
}
}
else if (!string.IsNullOrEmpty(resid))
{
// 从缓存中获取用户信息
cid = await _redisManager.ExistsAsync(resid, "UserCenter") ? await _redisManager.GetAsync<int>(resid, "UserCenter") : 0;
if (cid > 0)
{
// 如果存cid则根据cid获取用户信息
userInfo = await GetUserInfoByCid(cid);
}
// 如果缓存中没有用户信息,则从数据库中获取
userInfo ??= await GetUserInfoBySqlCondition("Resid", resid);
}
else if (!string.IsNullOrEmpty(unionid))
{
// 如果缓存中没有用户信息,则从数据库中获取
userInfo = await GetUserInfoBySqlCondition("Unionid", unionid);
}
return (cid, userInfo);
}
/// <summary>
/// 根据客户id获取客户信息
/// </summary>
/// <param name="cid"></param>
/// <returns></returns>
private async Task<UserInfo?> GetUserInfoByCid(int cid)
{
var userInfo = await _redisManager.GetHashAsync<UserInfo>($"user_{cid}", "UserCenter");
if (userInfo != null && string.IsNullOrEmpty(userInfo.Resid))
{
var result = await _redisManager.GetDatabase("UserCenter").SetMembersAsync($"cid_{cid}");
var userInfos = new List<UserInfoDto>();
#region
foreach (var item in result)
{
if (!item.HasValue) continue;
try
{
var data = JsonSerializer.Deserialize<UserInfo>(item, new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
});
if (data == null) continue;
userInfos.Add(new UserInfoDto
{
Appid = data.Appid,
Appuserid = data.Appuserid,
Uid = data.Uid.ToString()
});
}
catch (Exception e)
{
Log.Error($"反序列化失败:{e.Message}");
}
try
{
var data = JsonSerializer.Deserialize<UserInfoDto>(item, new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
});
if (data == null) continue;
userInfos.Add(new UserInfoDto
{
Appid = data.Appid,
Appuserid = data.Appuserid,
Uid = data.Uid
});
}
catch (Exception e)
{
Log.Error($"反序列化失败:{e.Message}");
}
}
#endregion
Log.Information($"在缓存key:【cid_{cid}】, 获取数据:{userInfos.ToJson()} ");
if (userInfos != null && userInfos.Any())
{
foreach (var user in userInfos)
{
Log.Information($"在缓存key:【user_{user.Uid}】");
var u = await _redisManager.GetHashAsync<UserInfo>($"user_{user.Uid}", "UserCenter");
Log.Information($"在缓存key:【user_{user.Uid}】, 获取数据:{u.ToJson()}");
userInfo.Resid = !string.IsNullOrEmpty(u.Resid) ? u.Resid : userInfo.Resid;
Log.Information($"成功获取resid{userInfo.Resid}");
if (!string.IsNullOrEmpty(userInfo.Resid)) break;
}
}
}
return userInfo;
}
/// <summary>
/// 根据sql和条件获取客户信息
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
private async Task<UserInfo?> GetUserInfoBySqlCondition(string key, object value)
{
var userInfo = new UserInfo();
var sql = @"SELECT Uid, Appid, Appuserid, Customerid, Resid, Unionid FROM UserInfo ";
if (string.IsNullOrEmpty(key) || value == null) return null;
using (var scope = _serviceProvider.CreateAsyncScope())
{
var userCenterRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<UserCenterDbContext>>();
sql += $"WHERE {key} = @{key}";
var param = new List<MySqlParameter>()
{
new MySqlParameter() { ParameterName=key, MySqlDbType = MySqlDbType.VarChar, Value=value }
};
Log.Information($"sql: {sql}, param: {value}");
var userInfos = await userCenterRepository.ExecuteSqlToListAsync<UserInfo>(sql, param.ToArray());
userInfo = userInfos.FirstOrDefault(x => x.Uid == x.Customerid);
if (userInfo != null && string.IsNullOrEmpty(userInfo.Resid))
{
userInfo.Resid = userInfos.FirstOrDefault(x => !string.IsNullOrEmpty(x.Resid))?.Resid;
}
}
return userInfo;
}
/// <summary>
/// 获取用户名
/// </summary>
/// <param name="resid"></param>
/// <returns></returns>
private async Task<string> GetUserName(string? resid)
{
if (string.IsNullOrEmpty(resid)) return "";
using var scope = _serviceProvider.CreateAsyncScope();
var zxdRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<ZxdDbContext>>();
var orders = await zxdRepository.GetRepository<WX_SZZYORDER>().Query()
.Where(x => x.RESID == resid)
.Distinct()
.ToListAsync();
if (orders == null) return "";
if (orders.Any(x => !string.IsNullOrEmpty(x.CNAME)))
{
return orders.First(x => !string.IsNullOrEmpty(x.CNAME)).CNAME ?? "";
}
else if (orders.Any(x => !string.IsNullOrEmpty(x.SOFTUSERNAME)))
{
var softUserName = orders.First(x => !string.IsNullOrEmpty(x.SOFTUSERNAME)).SOFTUSERNAME;
var riskinfoUrl = _systemConfig.GetRiskinfo();
var bf = "{\"uid\": \"" + softUserName + "\"}";
var hqr = BlowFish.Encode(bf);
var para = new { hqr };
var res = await _httpClient.PostAsync<RiskInfoDto>(riskinfoUrl, para);
if (res.Ret == 0 && res.Businesstype != "smallAmount")
{
return res.Name ?? "";
}
}
return "";
}
/// <summary>
/// 获取或创建用户事业部关系
/// </summary>
/// <param name="complaintUser"></param>
/// <param name="complaintLog"></param>
/// <returns></returns>
private async Task<ComplaintUserDept> GetOrCreatComplaintUserDept(ComplaintUser complaintUser, ComplaintLog complaintLog)
{
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
var complaintUserDept = await hgActionRepository.GetRepository<ComplaintUserDept>().Query()
.Where(x => x.Fid == complaintUser.Id)
.Where(x => x.Deptid == complaintLog.Deptid)
.FirstOrDefaultAsync();
if (complaintUserDept == null)
{
try
{
var deptmentGroup = await _cacheDomain.GetDeptmentGroupByDeptid(complaintLog.Deptid);
if (deptmentGroup == null)
{
Log.Information($"事业部组不存id:{complaintLog.Deptid}");
return complaintUserDept;
}
complaintUserDept = new ComplaintUserDept
{
Deptid = complaintLog.Deptid,
Ctime = DateTime.Now,
DeptGroupId = deptmentGroup.Id,
CrmAppid = complaintLog.Appid,
Fid = complaintUser.Id,
LastContent = complaintLog.Content,
LastContentId = complaintLog.Id,
Status = ComplaintStatus.
};
complaintUserDept = await hgActionRepository.GetRepository<ComplaintUserDept>().InsertAsync(complaintUserDept);
}
catch (Exception ex)
{
Log.Error(ex, $"创建用户事业部关系失败complaintUser:{complaintUser.ToJson()}, complaintLog:{complaintLog.ToJson()}");
throw;
}
}
return complaintUserDept;
}
/// <summary>
/// 创建用户
/// </summary>
/// <param name="userInfo"></param>
/// <param name="complaintLog"></param>
/// <returns></returns>
private async Task<(ComplaintUser, ComplaintUserDept?)> CreateComplaintUser(UserInfo userInfo, ComplaintLog complaintLog)
{
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
var deptmentGroup = await _cacheDomain.GetDeptmentGroupByDeptid(complaintLog.Deptid);
var complaintUser = new ComplaintUser
{
Appid = userInfo.Appid,
Appuserid = userInfo.Appuserid,
Ctime = DateTime.Now,
LastType = complaintLog.Source.ToString(),
Resid = complaintLog.Resid ?? userInfo.Resid,
Unionid = userInfo.Unionid,
Uname = await GetUserName(userInfo.Resid)
};
var transaction = await hgActionRepository.BeginTransactionAsync();
try
{
complaintUser = await hgActionRepository.GetRepository<ComplaintUser>().InsertAsync(complaintUser);
if (deptmentGroup == null)
{
Log.Information($"事业部组不存id:{complaintLog.Deptid}");
return (complaintUser, null);
}
else
{
var complaintUserDept = await hgActionRepository.GetRepository<ComplaintUserDept>().Query()
.Where(x => x.Fid == complaintUser.Id)
.Where(x => x.Deptid == complaintLog.Deptid)
.FirstOrDefaultAsync();
if (complaintUserDept == null)
{
complaintUserDept = new ComplaintUserDept
{
Deptid = complaintLog.Deptid,
Ctime = DateTime.Now,
DeptGroupId = deptmentGroup.Id,
CrmAppid = complaintLog.Appid,
Fid = complaintUser.Id,
LastContent = complaintLog.Content,
LastContentId = complaintLog.Id,
Status = ComplaintStatus.
};
if (!string.IsNullOrEmpty(userInfo.Resid))
{
complaintUserDept.HasOrder = await HasOrderByResid(complaintUser.Resid, complaintLog.Deptid);
}
complaintUserDept = await hgActionRepository.GetRepository<ComplaintUserDept>().InsertAsync(complaintUserDept);
}
else
{
complaintUserDept.LastContent = complaintLog.Content;
complaintUserDept.LastContentId = complaintLog.Id;
complaintUserDept.Status = ComplaintStatus.;
complaintUserDept.Utime = DateTime.Now;
await hgActionRepository.GetRepository<ComplaintUserDept>().UpdateAsync(complaintUserDept, x => new
{
x.LastContent,
x.LastContentId,
x.Status,
x.Utime
});
}
await transaction.CommitAsync();
return (complaintUser, complaintUserDept);
}
}
catch (Exception ex)
{
await transaction.RollbackAsync();
await transaction.DisposeAsync();
Log.Error(ex, $"创建用户失败dto:{complaintLog.ToJson()}");
throw;
}
}
/// <summary>
/// 根据resid获取用户是否有订单
/// </summary>
/// <param name="resid"></param>
/// <param name="deptid"></param>
/// <returns></returns>
private async Task<bool> HasOrderByResid(string? resid, int? deptid)
{
var deptments = await _cacheDomain.GetDeptments();
var deptment = deptments.FirstOrDefault(y => y.Id == deptid);
using var scope = _serviceProvider.CreateAsyncScope();
var zxdRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<ZxdDbContext>>();
var where = PredicateExtensionses.True<WX_SZZYORDER>();
where = where.And(x => x.RESID == resid);
var whereOr = PredicateExtensionses.False<WX_SZZYORDER>();
if (deptment != null && deptment.DeptmentCampains != null && deptment.DeptmentCampains.Any())
{
foreach (var item in deptment.DeptmentCampains)
{
whereOr = whereOr.Or(m => m.CHANNEL >= item.StartCampainId && m.CHANNEL <= item.EndCampainId);
}
}
where = where.And(whereOr);
return await zxdRepository.GetRepository<WX_SZZYORDER>().Query()
.Where(where)
.AnyAsync();
}
private async Task<T> GetData<T>(string url, string appid) where T : class, new()
{
var client = new System.Net.Http.HttpClient();
client.DefaultRequestHeaders.Add("appid", appid);
var result = await client.GetAsync(url);
var bytes = await result.Content.ReadAsByteArrayAsync();
var json = Encoding.UTF8.GetString(bytes);
var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(json);
return obj;
}
/// <summary>
/// 分页
/// </summary>
/// <param name="dto"></param>
/// <param name="appid"></param>
/// <returns></returns>
public async Task<PageResult<ComplaintDto>> GetPage(SearchComplaintDto dto, string? appid)
{
var deptmentGroups = await _cacheDomain.GetDeptmentGroups();
var deptments = await _cacheDomain.GetDeptments();
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
var zxdRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<ZxdDbContext>>();
var userQuery = hgActionRepository.GetRepository<ComplaintUser>().Query();
var logQuery = hgActionRepository.GetRepository<ComplaintLog>().Query();
var deptQuery = hgActionRepository.GetRepository<ComplaintUserDept>().Query();
var followQuery = hgActionRepository.GetRepository<ComplaintUserFollow>().Query();
var cur = zxdRepository.GetRepository<RES_CUSTOMER>().Query();
var eids = new List<int>();
var deptids = new List<int>();
#region UMID转RESID
if (!string.IsNullOrEmpty(dto.UMID) && string.IsNullOrEmpty(dto.ResId)) {
var UMIDMain = cur.FirstOrDefault(m => m.UMID == dto.UMID);
if (UMIDMain != null)
{
dto.ResId = UMIDMain.RESID;
}
else {
dto.ResId = "NULL_RESID";
}
}
#endregion
if (!string.IsNullOrEmpty(dto.Txt_deptId) || !string.IsNullOrEmpty(dto.Txt_groupIds))
{
//接口需要appid传到header中此方法不适用暂时改为自定义方法
//var eidResult = await _httpClient.GetAsync<ApiResult<BusinessLineDto>>($"{_systemConfig.GetBusinessLineByDeptMentIds(dto.Txt_groupIds, dto.Txt_deptId)}", appid);
var eidResult = await GetData<ApiResult<BusinessLineDto>>($"{_systemConfig.GetBusinessLineByDeptMentIds(dto.Txt_groupIds, dto.Txt_deptId)}", appid);
if (eidResult.Code == 0)
{
if (eidResult.Data.IsLine)
{
dto.DeptId = eidResult.Data.DeptId.ToString();
}
else
{
eids = eidResult.Data.EidInfo;
}
}
else
{
Log.Error($"查询CRM组织结构接口报错, message: {eidResult.Message}");
}
}
if (dto.Txt_userId.HasValue)
{
//接口需要appid传到header中此方法不适用暂时改为自定义方法
//var usersResult = await _httpClient.GetAsync<ApiResult<List<CrmUserInfoDto>>>(_systemConfig.GetUserInfoByEIds(dto.Txt_userId.ToString()), appid);
var usersResult = await GetData<ApiResult<List<CrmUserInfoDto>>>(_systemConfig.GetUserInfoByEIds(dto.Txt_userId.ToString()), appid);
if (usersResult.Code == 0)
{
var userInfos = usersResult.Data;
userInfos.ForEach(x =>
{
if (x.Eid.HasValue)
eids = new List<int> { x.Eid.Value };
});
}
else
{
Log.Error($"查询CRM组织结构接口报错, message: {usersResult.Message}");
}
}
if (!string.IsNullOrEmpty(appid))
{
deptids = deptments.Where(x => x.Appid == appid && x.Id != 0).Select(x => x.Id).ToList();
}
if (!string.IsNullOrWhiteSpace(dto.DeptId))
{
deptids = dto.DeptId.Split(',').Select(n => Convert.ToInt32(n)).ToList();
}
var endTime = dto.ETime.HasValue ? dto.ETime.Value.AddDays(1) : DateTime.Now;
var query = from a in deptQuery
join b in userQuery on a.Fid equals b.Id into tempB
from b in tempB.DefaultIfEmpty()
join c in logQuery.Where(x => x.IsLast) on a.Id equals c.Udid into tempC
from c in tempC.DefaultIfEmpty()
join d in followQuery.Where(x => x.IsLast) on a.Id equals d.Udid into tempD
from d in tempD.DefaultIfEmpty()
select new ComplaintDto
{
Id = a.Id,
ResId = b.Resid,
DeptId = a.Deptid,
SignType = c.SignType,
SignWay = c.SignWay,
ContentJson = c.Content,
Source = c.Source,
Ctime = c.Ctime,
Status = a.Status,
FollowContent = d.Content,
FollowTime = d.Ctime,
Eid = b.Eid,
EName = d.Ename,
BelongEname = b.Ename,
Appid = b.Appid,
Appuserid = b.Appuserid,
HasOrder = a.HasOrder,
HasAssign = b.Eid != null,
Uname = b.Uname,
Reason = c.Reason
};
query = query.If(dto.Status.HasValue, x => x.Where(q => q.Status == dto.Status))
.If(!string.IsNullOrEmpty(dto.DeptId), x => x.Where(q => deptids.Contains(q.DeptId.Value)))
.If(!string.IsNullOrEmpty(dto.ResId), x => x.Where(q => q.ResId.Contains(dto.ResId)))
.If(dto.Source.HasValue, x => x.Where(q => q.Source == dto.Source))
.If(dto.SignWay.HasValue, x => x.Where(q => q.SignWay == dto.SignWay))
.If(dto.SignType.HasValue, x => x.Where(q => q.SignType == dto.SignType))
.If(dto.STime.HasValue, x => x.Where(q => q.Ctime >= dto.STime))
.If(dto.ETime.HasValue, x => x.Where(q => q.Ctime < endTime))
.If(!string.IsNullOrEmpty(dto.UName), x => x.Where(q => q.Uname.Contains(dto.UName)))
.If(eids.Count > 0, x => x.Where(x => eids.Contains(x.Eid.Value)))
.If(dto.HasAssign.HasValue, x => x.Where(q => q.HasAssign == dto.HasAssign))
.If(dto.HasOrder.HasValue, x => x.Where(q => q.HasOrder == dto.HasOrder))
.If(!string.IsNullOrEmpty(dto.Content), x => x.Where(q => q.ContentJson.Contains(dto.Content)))
.If(deptids != null && deptids.Any(), x => x.Where(x => deptids.Contains(x.DeptId.Value)));
var total = await query.CountAsync();
var data = await query.OrderByDescending(x => x.Ctime)
.Skip((dto.PageIndex - 1) * dto.PageSize)
.Take(dto.PageSize)
.ToListAsync();
var resids = data.Where(x => !string.IsNullOrEmpty(x.ResId)).Select(x => x.ResId).Distinct().ToList();
var mycur = cur.Where(m => resids.Contains(m.RESID)).ToList();
foreach (var item in data)
{
var deptmentGroup = deptmentGroups.FirstOrDefault(x => x.Deptments != null && x.Deptments.Any(y => y.Id == item.DeptId));
if (deptmentGroup != null && deptmentGroup.Deptments != null && deptmentGroup.Deptments.Any())
{
item.DeptGroupName = deptmentGroup.GroupName;
item.DeptName = deptmentGroup.Deptments.First(x => x.Id == item.DeptId).Title;
}
try
{
switch (item.Source)
{
case ComplaintSource.:
case ComplaintSource.:
case ComplaintSource.:
case ComplaintSource.app:
{
if (!string.IsNullOrEmpty(item.ContentJson))
{
var model = JsonSerializer.Deserialize<FormContentModelDto>(item.ContentJson);
item.Content = model?.Content;
}
break;
}
case ComplaintSource.:
{
if (!string.IsNullOrEmpty(item.ContentJson))
{
var model = JsonSerializer.Deserialize<NegativeContentModelDto>(item.ContentJson);
item.Content = model?.TextContent;
item.Keywords = model?.IllegalWords != null && model.IllegalWords.Any() ? string.Join(";", model?.IllegalWords) : "";
}
break;
}
case ComplaintSource.:
{
item.Content = @$"<div>{item.Uname}: {item.ResId}</div>
<div>{item.Reason?.GetDescription()}: {item.ContentJson}</div>";
break;
}
default:
item.Content = item.ContentJson;
break;
};
}
catch (Exception ex)
{
Log.Error(ex, "投诉内容json解析失败");
}
item.UMID = mycur.FirstOrDefault(m => m.RESID == item.ResId)?.UMID;
}
return new PageResult<ComplaintDto>(dto.PageIndex, dto.PageSize, total, data);
}
/// <summary>
/// 重新发起队列
/// </summary>
/// <returns></returns>
public async Task<List<ComplaintLogMessageDto>> SyncQueue()
{
var key = CacheKeys.ComplaintMessageEnqueue;
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
var data = await hgActionRepository.GetRepository<ComplaintLog>().Query()
.Where(x => x.Udid == null && x.Fid == null)
.ToListAsync();
await _redisManager.RemoveAsync(key);
foreach (var item in data)
{
var messageDto = _mapper.Map<ComplaintLog, ComplaintLogMessageDto>(item);
await _redisManager.EnqueueAsync(key, messageDto);
}
return _mapper.Map<ComplaintLog, ComplaintLogMessageDto>(data);
}
public async Task<ComplaintDetailDto> GetComplaintDetail(string? appid, string? appuserid, int? deptid)
{
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
var query = from a in hgActionRepository.GetRepository<ComplaintUser>().Query()
join b in hgActionRepository.GetRepository<ComplaintUserDept>().Query() on a.Id equals b.Fid
where a.Appid == appid && a.Appuserid == appuserid && b.Deptid == deptid
select b.Id;
var userDeptid = await query.FirstOrDefaultAsync();
if (userDeptid > 0)
{
return await GetComplaintDetail(userDeptid);
}
throw new ApiException("未找到投诉记录");
}
/// <summary>
/// 根据资源id和业务线获取投诉详情
/// </summary>
/// <param name="resid"></param>
/// <param name="deptid"></param>
/// <returns></returns>
public async Task<ComplaintDetailDto> GetComplaintDetail(string? resid, int? deptid)
{
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
var query = from a in hgActionRepository.GetRepository<ComplaintUser>().Query()
join b in hgActionRepository.GetRepository<ComplaintUserDept>().Query() on a.Id equals b.Fid
where a.Resid == resid && b.Deptid == deptid
select b.Id;
var userDeptid = await query.FirstOrDefaultAsync();
if (userDeptid > 0)
{
return await GetComplaintDetail(userDeptid);
}
throw new ApiException("未找到投诉记录");
}
/// <summary>
/// 获取投诉详情
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
/// <exception cref="ApiException"></exception>
public async Task<ComplaintDetailDto> GetComplaintDetail(int id)
{
var deptmentGroups = await _cacheDomain.GetDeptmentGroups();
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
var data = await (from a in hgActionRepository.GetRepository<ComplaintUserDept>().Query()
join b in hgActionRepository.GetRepository<ComplaintUser>().Query() on a.Fid equals b.Id
where a.Id == id
select new ComplaintDetailDto
{
Id = a.Id,
Fid = a.Fid,
Status = a.Status,
Deptid = a.Deptid,
Uname = b.Uname,
Resid = b.Resid
}).FirstOrDefaultAsync() ?? throw new ApiException("未找到投诉记录");
data.ComplaintLogDetails = await hgActionRepository.GetRepository<ComplaintLog>().Query()
.Where(x => x.Udid == data.Id && x.Fid == data.Fid)
.OrderByDescending(x => x.Ctime)
.Select(x => new ComplaintLogDetailDto
{
ContentJson = x.Content,
SignType = x.SignType,
SignWay = x.SignWay,
Source = x.Source,
Ctime = x.Ctime,
Type = x.Type,
Appid = x.Appid,
Appuserid = x.Appuserid,
Id = x.Id,
Deptid = x.Deptid,
Eid = x.Eid,
InternalNickname = x.Ename,
Reason = x.Reason
}).ToListAsync();
foreach (var item in data.ComplaintLogDetails)
{
if (item.Deptid != null)
{
var deptmentGroup = deptmentGroups.FirstOrDefault(x => x.Deptments != null && x.Deptments.Any(y => y.Id == item.Deptid));
if (deptmentGroup != null && deptmentGroup.Deptments != null && deptmentGroup.Deptments.Any())
{
item.Deptname = deptmentGroup.Deptments.First(x => x.Id == item.Deptid).Title;
}
}
switch (item.Source)
{
case ComplaintSource.:
case ComplaintSource.:
case ComplaintSource.:
case ComplaintSource.app:
{
if (!string.IsNullOrEmpty(item.ContentJson))
{
var model = JsonHelper.FromJson<FormContentModelDto>(item.ContentJson);
item.Content = model?.Content;
}
break;
}
case ComplaintSource.:
{
if (!string.IsNullOrEmpty(item.ContentJson))
{
var model = JsonHelper.FromJson<NegativeContentModelDto>(item.ContentJson);
item.Nickname = model?.ExternalNickname;
item.Content = model?.TextContent;
item.InternalNickname = model?.InternalNickname;
item.InternalAppuserid = model?.InternalAppuserid;
item.Msgid = model?.Msgid;
item.Keywords = model?.IllegalWords != null && model.IllegalWords.Any() ? string.Join(";", model?.IllegalWords) : "";
}
break;
}
case ComplaintSource.:
{
item.Content = @$"<div>{data.Uname}: {data.Resid}</div>
<div>{item.Reason?.GetDescription()}: {item.ContentJson}</div>";
break;
}
default:
item.Content = item.ContentJson;
break;
};
}
data.ComplaintFollowDetails = await hgActionRepository.GetRepository<ComplaintUserFollow>().Query()
.Where(x => x.Udid == data.Id && x.Fid == data.Fid)
.OrderByDescending(x => x.Ctime)
.Select(x => new ComplaintFollowDetailDto
{
Content = x.Content,
Eid = x.Eid,
Ename = x.Ename,
Ctime = x.Ctime,
Id = x.Id,
Title = x.Title,
Crmappid = x.Crmappid,
}).ToListAsync();
if (data.ComplaintFollowDetails != null && data.ComplaintFollowDetails.Any())
{
var appids = data.ComplaintFollowDetails.Where(x => !string.IsNullOrEmpty(x.Crmappid)).Select(x => x.Crmappid);
foreach (var appid in appids)
{
var eids = string.Join(",", data.ComplaintFollowDetails.Where(x => x.Crmappid == appid).Select(x => x.Eid));
var usersResult = await _httpClient.GetAsync<ApiResult<List<CrmUserInfoDto>>>(_systemConfig.GetUserInfoByEIds(eids), appid);
if (usersResult.Code == 0)
{
var userInfos = usersResult.Data;
data.ComplaintFollowDetails.Where(x => x.Crmappid == appid).ToList().ForEach(x =>
{
var userInfo = userInfos.FirstOrDefault(x => x.Eid == x.Eid);
x.Deptname = userInfo?.DeptName;
});
}
}
}
return data;
}
/// <summary>
/// 更新投诉状态
/// </summary>
/// <param name="dto"></param>
/// <param name="appid"></param>
/// <returns></returns>
/// <exception cref="ApiException"></exception>
public async Task<bool> UpdateComplaintStatus(UpdateComplaintStatusDto dto, string? appid)
{
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
var data = await hgActionRepository.GetRepository<ComplaintUserDept>().Query()
.FirstOrDefaultAsync(x => x.Id == dto.Id) ?? throw new ApiException("未找到投诉记录");
var title = $"由【{data.Status.GetDescription()}】变更为【{dto.Status.GetDescription()}】";
if (data.Status == ComplaintStatus.)
{
throw new ApiException($"投诉记录【{data.Status.GetDescription()}】,无法更新状态");
}
if (data.Status > dto.Status && dto.Status != ComplaintStatus.)
{
throw new ApiException($"投诉记录【{data.Status.GetDescription()}】,无法更新状态到【{dto.Status.GetDescription()}】");
}
data.Status = dto.Status;
data.Utime = DateTime.Now;
var transaction = await hgActionRepository.BeginTransactionAsync();
try
{
var complaintLogs = await hgActionRepository.GetRepository<ComplaintLog>().Query()
.Where(x => x.Udid == data.Id && x.Fid == data.Fid && x.IsLast)
.ToListAsync();
await hgActionRepository.GetRepository<ComplaintUserDept>().UpdateAsync(data, x => new
{
x.Status,
x.Utime
});
var complaintUserFollows = await hgActionRepository.GetRepository<ComplaintUserFollow>().Query()
.Where(x => x.Udid == data.Id && x.Fid == data.Fid && x.IsLast)
.ToListAsync();
if (complaintUserFollows.Any())
{
complaintUserFollows.ForEach(x => x.IsLast = false);
await hgActionRepository.GetRepository<ComplaintUserFollow>().BatchUpdateAsync(complaintUserFollows, x => new
{
x.IsLast
});
}
var complaintUserFollow = new ComplaintUserFollow
{
Udid = data.Id,
Fid = data.Fid,
Content = dto.Content,
Ctime = DateTime.Now,
Eid = dto.Eid,
Ename = dto.Ename,
IsLast = true,
Title = title,
Crmappid = appid
};
if (complaintLogs.Any())
{
if (data.Status == ComplaintStatus.)
{
complaintLogs.ForEach(x => x.IsCompletion = true);
await hgActionRepository.GetRepository<ComplaintLog>().BatchUpdateAsync(complaintLogs, x => new
{
x.IsCompletion
});
}
complaintUserFollow.LastContentId = complaintLogs.FirstOrDefault()?.Id;
}
await hgActionRepository.GetRepository<ComplaintUserFollow>().InsertAsync(complaintUserFollow);
await transaction.CommitAsync();
if (dto.Status != ComplaintStatus.)
{
_complaintEventSingleton.RemoveComplaint(data.Id);
}
}
catch (Exception ex)
{
Log.Error(ex, $"更新投诉状态报错dto:{dto.ToJson()}");
}
return true;
}
/// <summary>
/// 获取投诉状态
/// </summary>
/// <param name="udid"></param>
/// <returns></returns>
public async Task<ComplainStatusModel> GetComplaintStatus(int udid)
{
ComplainStatusModel res = new ComplainStatusModel();
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
var data = await hgActionRepository.GetRepository<ComplaintUserDept>().Query()
.FirstOrDefaultAsync(x => x.Id == udid);
if (data != null)
{
res.Id = data.Id;
res.Status = data.Status;
}
return res;
}
/// <summary>
/// 标记客户
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
public async Task<bool> MarkCustomer(MarkCustomerDto dto)
{
try
{
ApplyComplaintDto applyComplaintDto = new ApplyComplaintDto();
if (dto.IsResid)
{
applyComplaintDto.Resid = dto.PostId;
}
else
{
applyComplaintDto.Unionid = dto.PostId;
}
applyComplaintDto.SignType = dto.Signtype;
applyComplaintDto.SignWay = ComplaintSignWay.;
applyComplaintDto.Source = dto.Type == 1 ? ComplaintSource. : ComplaintSource.;
applyComplaintDto.Content = dto.Content;
applyComplaintDto.Eid = dto.Eid;
applyComplaintDto.Ename = dto.Ename;
if (!string.IsNullOrWhiteSpace(dto.DeptId))
{
var depts = dto.DeptId.Split(",").ToList();
foreach (var dept in depts)
{
applyComplaintDto.Deptid = Convert.ToInt32(dept);
await ApplyComplaint(applyComplaintDto);
}
}
else
{
await ApplyComplaint(applyComplaintDto);
}
}
catch (Exception ex)
{
Log.Error($"MarkCustomer{ex.Message}");
throw;
}
return true;
}
/// <summary>
/// 初始化处理过期未处理投诉
/// </summary>
/// <returns></returns>
public async Task InitOverdueComplaint()
{
var now = DateTime.Now;
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
var dueTime = now.AddHours(-DefaultHelper.DueHours);
var query = from a in hgActionRepository.GetRepository<ComplaintUserDept>().Query()
join b in hgActionRepository.GetRepository<ComplaintLog>().Query() on a.Id equals b.Udid
where a.Status == ComplaintStatus. && b.IsLast
select new ComplaintEventDto
{
Id = a.Id,
Ctime = b.Ctime,
Fid = a.Fid,
};
var data = await query.ToListAsync();
if (data.Any())
{
// 超时未跟进处理
var overdueData = data.Where(x => x.Ctime < dueTime).ToList();
foreach (var item in overdueData)
{
Log.Information($"系统处理超时未跟进id: {item.Id}");
var dto = new UpdateComplaintStatusDto
{
Id = item.Id,
Status = ComplaintStatus.,
Content = "超时未跟进",
Ename = "系统"
};
await UpdateComplaintStatus(dto, "");
}
// 未超时未跟进处理
var dueData = data.Where(x => x.Ctime >= dueTime).ToList();
if (dueData.Any())
{
_complaintEventSingleton.InitComplaintEvents(dueData);
}
}
}
/// <summary>
/// 处理过期未处理投诉
/// </summary>
/// <returns></returns>
public async Task OverdueComplaint()
{
var now = DateTime.Now;
var dueTime = now.AddHours(-DefaultHelper.DueHours);
var data = _complaintEventSingleton.GetComplaintEvents();
if (data.Any())
{
var overdueData = data.Where(x => x.Ctime < dueTime).ToList();
foreach (var item in overdueData)
{
Log.Information($"系统处理超时未跟进id: {item.Id}");
var dto = new UpdateComplaintStatusDto
{
Id = item.Id,
Status = ComplaintStatus.,
Content = "超时未跟进",
Ename = "系统"
};
await UpdateComplaintStatus(dto, "");
}
}
}
/// <summary>
/// 刷新resid
/// </summary>
/// <returns></returns>
public async Task SyncResid()
{
//var json = "{\"Msgid\":\"12603565224196055910_1684218213018_external\",\"Msgtype\":\"text\",\"Recvtime\":null,\"Msgtime\":1684218208766,\"Corpid\":\"wwd4cd11d60db47118\",\"Corpname\":null,\"Tolist\":\"懂牛股票通\",\"Roomid\":\"\",\"Seq\":674415358,\"send_type\":2,\"text_content\":\"大盘调整从来就不是一件可怕的事可怕的是咱们一直在做涨了去追跌了割肉迟迟不敢下手的事情uD83DuDD25“大科技行情”可能即将出现起爆点今年的半导体板块走出了一波行情 但目前又回调到前期低点位置。 机会大于风险 - 值得我们持续关注, 要珍惜眼下黄金坑主线方向持续关注大科技与中特估一带一路, 大科技包括AI + 半导体 + 跨境支付 + 消费电子等等。 每个时期的主线机会都十分稀缺, 我们可以看到北上资金持续流入, 也预示了当前市场并不存在大的风险, 短期的回调都是为了更好的上涨!主力的每一次洗盘, 都是希望散户交出带血的筹码。 但跟对主线非常重要, 否则只剩下煎熬。 未来的市场普遍只存在局部牛市, 需要时刻紧盯主力动向才能享受到财富喜悦。( 投顾: 罗啼明; 执业编号: A0100622030001 股市有风险, 投资需谨慎。)没有对的逻辑和正确的思维, 再好的低位也把握不住! 四月份的回调, 正是给五月份蓄能的契机。紧跟头部动向, 速度跟上咱们这轮的部署计划好吗? \",\"illegal_words \":[\"坑\"],\"external_resid \":\"257029289502501233\",\"external_unionid \":\"o5bj2wX--v3UdvKYz - L0oHY24aEw\",\"external_appuserid \":\"wmir6CCwAAfwgRKIz3oGLpK1Aus_YRvw\",\"external_nickname \":\"17709026787\",\"internal_eid \":802021,\"internal_groupid \":87,\"internal_deptid \":40,\"internal_employee_name \":\"陈景固\",\"internal_group_name \":\"客户服务二组 \",\"internal_dept_name \":\"六合投研服务中心 \",\"internal_unionid \":\"o5bj2wfT3_EPTluIfOq7q2gohlmU\",\"internal_nickname \":\"东高投研-陈经理\",\"internal_appuserid \":\"220321-134803-45\"}";
//var da = JsonHelper.FromJson<NegativeContentModelDto>(json);
//var da2 = JsonSerializer.Deserialize<NegativeContentModelDto>(json);
//var us = await GetUserInfo("wwd4cd11d60db47118", "221213-142659-33", "", "");
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
var query = from a in hgActionRepository.GetRepository<ComplaintUserDept>().Query()
join b in hgActionRepository.GetRepository<ComplaintUser>().Query() on a.Fid equals b.Id
where !string.IsNullOrEmpty(b.Resid)
select new { a, b };
var data = await query.ToListAsync();
if (data.Any())
{
foreach (var item in data)
{
try
{
// 获取用户中心的用户信息
//var user = await GetUserInfo(item.Appid, item.Appuserid, item.Resid, item.Unionid);
var hasOrder = await HasOrderByResid(item.b.Resid, item.a.Deptid);
if (hasOrder)
{
item.a.HasOrder = true;
await hgActionRepository.GetRepository<ComplaintUserDept>().UpdateAsync(item.a, x => new
{
x.HasOrder
});
}
}
catch (Exception ex)
{
Log.Error(ex, $"刷新resid出错data: {item.ToJson()}");
}
}
}
}
/// <summary>
/// 批量分配客户给客服
/// </summary>
/// <param name="dto"></param>
/// <param name="appid"></param>
/// <returns></returns>
public async Task<bool> BatchAssignComplaint(BatchAssignComplaintDto dto, string? appid)
{
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
var complaintUsers = await (from a in hgActionRepository.GetRepository<ComplaintUserDept>().Query()
join b in hgActionRepository.GetRepository<ComplaintUser>().Query() on a.Fid equals b.Id into abtemp
from b in abtemp.DefaultIfEmpty()
where dto.Ids.Contains(a.Id)
select b).ToListAsync();
if (complaintUsers == null || !complaintUsers.Any()) throw new ApiException("投诉用户信息不存在!");
//接口需要appid传到header中此方法不适用暂时改为自定义方法
//var usersResult = await _httpClient.GetAsync<ApiResult<List<CrmUserInfoDto>>>(_systemConfig.GetUserInfoByEIds(dto.Eid.ToString()), appid);
var usersResult = await GetData<ApiResult<List<CrmUserInfoDto>>>(_systemConfig.GetUserInfoByEIds(dto.Eid.ToString()), appid);
var ename = "";
if (usersResult.Code == 0)
{
var userInfos = usersResult.Data;
var userInfo = userInfos.FirstOrDefault(x => x.Eid == x.Eid);
ename = userInfo?.Uname;
}
foreach (var complaintUser in complaintUsers)
{
complaintUser.Eid = dto.Eid;
complaintUser.Ename = ename;
complaintUser.Utime = DateTime.Now;
}
await hgActionRepository.GetRepository<ComplaintUser>().BatchUpdateAsync(complaintUsers, x => new
{
x.Ename,
x.Eid,
x.Utime
});
return true;
}
public async Task Total()
{
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
var querlog = hgActionRepository.GetRepository<ComplaintLog>().Query().Select(x => new { x.Deptid, x.Fid, x.Udid, x.Source }).Distinct();
var query =
hgActionRepository.GetRepository<ComplaintUserDept>().Query()
.GroupBy(x => x.Deptid)
.Select(x => new
{
x.Key,
= querlog.Where(a => a.Deptid == x.Key && a.Source == ComplaintSource.)
.Sum(x => 1),
= querlog.Where(a => a.Deptid == x.Key && new List<ComplaintSource> {
ComplaintSource.,
ComplaintSource.PC软件,
ComplaintSource.,
ComplaintSource.app,
ComplaintSource.
}.Contains(a.Source.Value)).Sum(x => 1),
= querlog.Where(a => a.Deptid == x.Key && new List<ComplaintSource> {
ComplaintSource.,
ComplaintSource.
}.Contains(a.Source.Value)).Sum(x => 1),
= x.Sum(x => 1),
= x.Where(x => x.Status == ComplaintStatus.).Sum(x => 1),
1 = x.Where(x => x.Status == ComplaintStatus.).Sum(x => 1) / x.Sum(x => 1),
= x.Where(x => x.Status == ComplaintStatus.).Sum(x => 1),
2 = x.Where(x => x.Status == ComplaintStatus.).Sum(x => 1) / x.Sum(x => 1),
= x.Where(x => x.Status == ComplaintStatus.).Sum(x => 1),
3 = x.Where(x => x.Status == ComplaintStatus.).Sum(x => 1) / x.Sum(x => 1),
= x.Where(x => x.Status == ComplaintStatus.).Sum(x => 1),
4 = x.Where(x => x.Status == ComplaintStatus.).Sum(x => 1) / x.Sum(x => 1),
});
var data = await query.ToListAsync();
}
public async Task<bool> MarkTrolls(MarkTrollsDto dto)
{
var deptids = dto.Deptid?.Split(',').Select(x => int.Parse(x));
if (deptids == null) return false;
foreach (var deptid in deptids)
{
var applyComplaint = new ApplyComplaintDto
{
Deptid = deptid,
Appid = dto.Appid,
Appuserid = dto.Appuserid,
Content = dto.Content,
Eid = dto.Eid,
SignWay = ComplaintSignWay.,
Source = ComplaintSource.,
Reason = dto.Reason
};
await ApplyComplaint(applyComplaint);
}
return true;
}
public async Task<int> ComplaintLabel(string resId)
{
if (string.IsNullOrWhiteSpace(resId))
throw new ApiException("请输入客户ID");
using var scope = _serviceProvider.CreateAsyncScope();
var hgActionRepository = scope.ServiceProvider.GetRequiredService<IBaseRepository<HgAtionDbContext>>();
var id = await hgActionRepository.GetRepository<ComplaintUser>().Query()
.Where(x => x.Resid == resId).Select(x => x.Id).FirstOrDefaultAsync();
return id;
}
}
}