|
@@ -20,9 +20,11 @@ using Microsoft.AspNetCore.Authorization;
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
using Microsoft.Extensions.Options;
|
|
|
using Newtonsoft.Json;
|
|
|
+using SqlSugar;
|
|
|
using System.Threading;
|
|
|
using XF.Domain.Authentications;
|
|
|
using XF.Domain.Constants;
|
|
|
+using XF.Domain.Exceptions;
|
|
|
using XF.Domain.Repository;
|
|
|
|
|
|
namespace Hotline.Api.Controllers
|
|
@@ -124,70 +126,123 @@ namespace Hotline.Api.Controllers
|
|
|
var aiOrderVisitDetail = aiOrderVisit.AiOrderVisitDetails.FirstOrDefault(x => x.TaskUid == dto.TaskUid);
|
|
|
if (aiOrderVisitDetail != null)
|
|
|
{
|
|
|
+ var callRecord = dto.CallRecordList.OrderBy(x => x.CallStartTime).LastOrDefault();
|
|
|
// 回访结果(ReturnVisit)[1成功、0不涉及、-1失败]
|
|
|
- var callRecord = dto.CallRecordList.OrderByDescending(x => x.CallNo).FirstOrDefault(x => x.ReturnVisit == 1);
|
|
|
+
|
|
|
if (callRecord != null) //有结果的任务
|
|
|
{
|
|
|
aiOrderVisitDetail.AiOrderVisitState = Share.Enums.Ai.EAiOrderVisitState.Ended; //更新AI子表
|
|
|
aiOrderVisitDetail.AiVisitTime = DateTime.Now;
|
|
|
aiOrderVisit.VisitedCount++;
|
|
|
//处理结果
|
|
|
- var visitDetail = _orderVisitDetailRepository.Queryable().Where(x => x.VisitId == aiOrderVisitDetail.OrderVisit.Id);
|
|
|
+ var visitDetail = _orderVisitDetailRepository.Queryable().Where(x => x.VisitId == aiOrderVisitDetail.OrderVisit.Id).ToList();
|
|
|
//先处理子表
|
|
|
- //先处理坐席(因没有坐席回访,所以默认满意)
|
|
|
- var seatDetail = visitDetail.First(x => x.VisitTarget == Share.Enums.Order.EVisitTarget.Seat);
|
|
|
- if (seatDetail != null)
|
|
|
- {
|
|
|
- seatDetail.VoiceEvaluate = Share.Enums.Order.EVoiceEvaluate.Satisfied;
|
|
|
- seatDetail.SeatEvaluate = Share.Enums.Order.ESeatEvaluate.Satisfied;
|
|
|
- }
|
|
|
- await _orderVisitDetailRepository.UpdateAsync(seatDetail, HttpContext.RequestAborted);
|
|
|
+
|
|
|
//处理部门
|
|
|
var orgDetail = visitDetail.Where(x => x.VisitTarget == Share.Enums.Order.EVisitTarget.Org).ToList();
|
|
|
//过滤结果
|
|
|
var orgProcessingResults = new Kv();
|
|
|
var orgHandledAttitude = new Kv();
|
|
|
+ ESeatEvaluate? seatEvaluate = null;
|
|
|
var visitContent = "";
|
|
|
+ var seatVisitContent = "";
|
|
|
+ var volveConent = "";
|
|
|
+ bool? isSolve = null;
|
|
|
+ bool? isContact = null;
|
|
|
+ //通话录音
|
|
|
+ var recordUrl = callRecord.RecordUrl;
|
|
|
foreach (var item in callRecord.QuestionnaireResult)
|
|
|
{
|
|
|
- //服务过程满意度
|
|
|
+ ////服务过程满意度
|
|
|
+ //if (item.QuestionId == _options.Value.QuestionIdOne)
|
|
|
+ //{
|
|
|
+ // if (item.QuestionResult == "满意")
|
|
|
+ // {
|
|
|
+ // orgHandledAttitude = new Kv() { Key="4", Value="满意" };
|
|
|
+ // }
|
|
|
+ // else
|
|
|
+ // {
|
|
|
+ // orgHandledAttitude = new Kv() { Key = "2", Value = "不满意" };
|
|
|
+
|
|
|
+ // }
|
|
|
+ //}
|
|
|
+ //是否联系
|
|
|
+ if (item.QuestionId == _options.Value.QuestionIdZone)
|
|
|
+ {
|
|
|
+ if (item.QuestionResult == "有联系")
|
|
|
+ {
|
|
|
+ isContact = true;
|
|
|
+ }
|
|
|
+ else if(item.QuestionResult == "没有联系")
|
|
|
+ {
|
|
|
+ isContact = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //是否解决
|
|
|
if (item.QuestionId == _options.Value.QuestionIdOne)
|
|
|
{
|
|
|
- if (item.QuestionResult == "满意")
|
|
|
+ if (item.QuestionResult == "得到解决")
|
|
|
{
|
|
|
- orgHandledAttitude = new Kv() { Key="4", Value="满意" };
|
|
|
+ isSolve = true;
|
|
|
}
|
|
|
- else
|
|
|
+ else if(item.QuestionResult == "未得到解决")
|
|
|
{
|
|
|
- orgHandledAttitude = new Kv() { Key = "2", Value = "不满意" };
|
|
|
-
|
|
|
+ isSolve = false;
|
|
|
}
|
|
|
}
|
|
|
//办件结果满意度
|
|
|
if (item.QuestionId == _options.Value.QuestionIdTwo)
|
|
|
{
|
|
|
- if (item.QuestionResult == "满意")
|
|
|
+ if (item.QuestionResult == "办件结果满意")
|
|
|
{
|
|
|
orgProcessingResults = new Kv() { Key = "4", Value = "满意" };
|
|
|
}
|
|
|
- else
|
|
|
+ else if(item.QuestionResult == "办件结果不满意")
|
|
|
{
|
|
|
orgProcessingResults = new Kv() { Key = "2", Value = "不满意" };
|
|
|
- visitContent = callRecord.SceneVariable[_options.Value.VisitContentId];
|
|
|
+ visitContent = callRecord.SceneVariable[_options.Value.VisitContentIdOne];
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
aiOrderVisitDetail.OrderVisit.VisitState = Share.Enums.Order.EVisitState.WaitForVisit;
|
|
|
}
|
|
|
+
|
|
|
+ //坐席是否满意
|
|
|
+ if (item.QuestionId == _options.Value.QuestionIdThree)
|
|
|
+ {
|
|
|
+ if (item.QuestionResult == "满意接电坐席")
|
|
|
+ {
|
|
|
+ seatEvaluate = ESeatEvaluate.Satisfied;
|
|
|
+ }
|
|
|
+ else if(item.QuestionResult == "不满意接电坐席")
|
|
|
+ {
|
|
|
+ seatEvaluate = ESeatEvaluate.NoSatisfied;
|
|
|
+ seatVisitContent = callRecord.SceneVariable[_options.Value.VisitContentIdTwo];
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ //先处理坐席(因没有坐席回访,所以默认满意)
|
|
|
+ var seatDetail = visitDetail.Where(x => x.VisitTarget == Share.Enums.Order.EVisitTarget.Seat).ToList();
|
|
|
+ seatDetail.ForEach(x =>
|
|
|
+ {
|
|
|
+ x.VoiceEvaluate = Share.Enums.Order.EVoiceEvaluate.Satisfied;
|
|
|
+ x.SeatEvaluate = seatEvaluate;
|
|
|
+ x.VisitContent = seatVisitContent;
|
|
|
+ });
|
|
|
+
|
|
|
+ await _orderVisitDetailRepository.UpdateRangeAsync(seatDetail, HttpContext.RequestAborted);
|
|
|
+
|
|
|
//处理结果
|
|
|
orgDetail.ForEach(x =>
|
|
|
{
|
|
|
x.OrgHandledAttitude = orgHandledAttitude;
|
|
|
x.OrgProcessingResults = orgProcessingResults;
|
|
|
x.VisitContent = visitContent;
|
|
|
- if (orgProcessingResults.Value == "不满意")
|
|
|
+ x.Volved = isSolve;
|
|
|
+ x.IsContact = isContact;
|
|
|
+ if (orgProcessingResults.Value == "不满意" || (string.IsNullOrEmpty(orgProcessingResults.Key) && seatEvaluate!=null && isSolve!=null && isContact!=null))
|
|
|
{
|
|
|
//x.OrgNoSatisfiedReason = new List<Kv>() { new Kv() { Key = "7", Value = "未回复" } };
|
|
|
//TODO 记录不满意原因到内容中供人工回访甄别选择不满意原因
|
|
@@ -212,6 +267,9 @@ namespace Hotline.Api.Controllers
|
|
|
{
|
|
|
aiOrderVisitDetail.OrderVisit.NowEvaluate = orgProcessingResults;
|
|
|
}
|
|
|
+ //处理是否回访完成TODO
|
|
|
+
|
|
|
+
|
|
|
await _orderVisitRepository.UpdateAsync(aiOrderVisitDetail.OrderVisit, HttpContext.RequestAborted);
|
|
|
|
|
|
//处理Order表
|
|
@@ -230,7 +288,7 @@ namespace Hotline.Api.Controllers
|
|
|
VisitType = aiOrderVisitDetail.OrderVisit.VisitType,
|
|
|
VisitName = aiOrderVisitDetail.OrderVisit.CreatorName,
|
|
|
VisitTime = aiOrderVisitDetail.OrderVisit.VisitTime,
|
|
|
- VisitRemark = string.IsNullOrEmpty(visitContent)?aiOrderVisitDetail.OrderVisit.NowEvaluate?.Value: visitContent,
|
|
|
+ VisitRemark = string.IsNullOrEmpty(visitContent) ? aiOrderVisitDetail.OrderVisit.NowEvaluate?.Value : visitContent,
|
|
|
AreaCode = aiOrderVisitDetail.OrderVisit.Order.AreaCode!,
|
|
|
SubjectResultSatifyCode = orgProcessingResults.Key,
|
|
|
FirstSatisfactionCode = aiOrderVisitDetail.OrderVisit.Order.FirstVisitResultCode!,
|
|
@@ -261,6 +319,8 @@ namespace Hotline.Api.Controllers
|
|
|
aiOrderVisitDetail.IsSuccess = false;
|
|
|
await _orderVisitRepository.UpdateAsync(aiOrderVisitDetail.OrderVisit, HttpContext.RequestAborted);
|
|
|
}
|
|
|
+ //var callRecord = dto.CallRecordList.OrderByDescending(x => x.CallNo).FirstOrDefault(x => x.ReturnVisit == 1);
|
|
|
+
|
|
|
|
|
|
await _aiOrderVisitDetailRepository.UpdateAsync(aiOrderVisitDetail, HttpContext.RequestAborted);
|
|
|
if ((aiOrderVisit.VisitedFailCount+aiOrderVisit.VisitedCount)== aiOrderVisit.HasVisitCount)
|
|
@@ -414,6 +474,12 @@ namespace Hotline.Api.Controllers
|
|
|
[HttpPost("aivisit/add-aivisit")]
|
|
|
public async Task AddAiVisit([FromBody]AddAiVisitDto dto)
|
|
|
{
|
|
|
+ //验证是否有重复电话
|
|
|
+ if(dto.AiOrderVisitDetails.Distinct().Count() != dto.AiOrderVisitDetails.Count)
|
|
|
+ {
|
|
|
+ throw UserFriendlyException.SameMessage("任务中存在重复外呼号码,请检查后重新提交");
|
|
|
+ }
|
|
|
+
|
|
|
var model = _mapper.Map<AiOrderVisit>(dto);
|
|
|
|
|
|
var detaillist = _mapper.Map<List<AiOrderVisitDetail>>(dto.AiOrderVisitDetails);
|
|
@@ -432,11 +498,7 @@ namespace Hotline.Api.Controllers
|
|
|
x.AiOrderVisitState = Share.Enums.Ai.EAiOrderVisitState.InProgress;
|
|
|
});
|
|
|
await _aiOrderVisitDetailRepository.AddRangeAsync(detaillist, HttpContext.RequestAborted);
|
|
|
- //修改回访主表
|
|
|
- await _orderVisitRepository.Updateable()
|
|
|
- .SetColumns(x => x.IsCanAiVisit == false)
|
|
|
- .SetColumns(x=> x.VisitState == EVisitState.Visiting)
|
|
|
- .Where(x=> detaillist.Select(s=>s.OrderVisitId).Contains(x.Id)).ExecuteCommandAsync(HttpContext.RequestAborted);
|
|
|
+
|
|
|
//推送任务
|
|
|
//准备原始数据
|
|
|
var pushModel = await _aiOrderVisitRepository.Queryable()
|
|
@@ -445,6 +507,19 @@ namespace Hotline.Api.Controllers
|
|
|
.FirstAsync(x => x.Id == id);
|
|
|
|
|
|
var newModel = await _aiVisitService.CreateAiOrderVisitTask(pushModel, HttpContext.RequestAborted);
|
|
|
+
|
|
|
+ if (!string.IsNullOrEmpty(newModel.BatchUid))
|
|
|
+ {
|
|
|
+ //修改回访主表
|
|
|
+ await _orderVisitRepository.Updateable()
|
|
|
+ .SetColumns(x => x.IsCanAiVisit == false)
|
|
|
+ .SetColumns(x => x.VisitState == EVisitState.Visiting)
|
|
|
+ .Where(x => detaillist.Select(s => s.OrderVisitId).Contains(x.Id)).ExecuteCommandAsync(HttpContext.RequestAborted);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ newModel.TaskState = Share.Enums.Ai.EAiOrderVisitTaskState.Ended;
|
|
|
+ }
|
|
|
await _aiOrderVisitRepository.UpdateAsync(newModel, HttpContext.RequestAborted);
|
|
|
await _aiOrderVisitDetailRepository.UpdateRangeAsync(newModel.AiOrderVisitDetails, HttpContext.RequestAborted);
|
|
|
}
|