884 lines
43 KiB
C#
884 lines
43 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using SA.Entity.zxdcrm_Models;
|
||
using SA.Core.Init;
|
||
using SA.Domain.XFYun.XFYunEntity;
|
||
using System.Collections.Concurrent;
|
||
using SA.Core.Util;
|
||
using SA.Domain.XFYun.BaseInfo;
|
||
using SA.Entity.dbcrm;
|
||
|
||
namespace SA.Domain.XFYun
|
||
{
|
||
/// <summary>
|
||
/// 获取订单
|
||
/// </summary>
|
||
public class GenOrderCall
|
||
{
|
||
private static ConcurrentDictionary<int, WxSzzyorder> wxSzzyorders = new ConcurrentDictionary<int, WxSzzyorder>();
|
||
|
||
private static ConcurrentDictionary<int, WxSzzyorder> wxSzzyordersChecking = new ConcurrentDictionary<int, WxSzzyorder>();
|
||
|
||
/// <summary>
|
||
/// 订单查询起始时间
|
||
/// </summary>
|
||
public static DateTime? startTime;
|
||
|
||
private static AI_CallTaskConfig genOrderCallConfig = GetConfig();
|
||
|
||
private static int GetNum = 100;
|
||
|
||
private int times = 0;
|
||
|
||
/// <summary>
|
||
/// 获取订单
|
||
/// </summary>
|
||
public void GetOrder()
|
||
{
|
||
try
|
||
{
|
||
//LogHelper.Info("OrderCallConfig: " + SerializeHelper.ToJson(genOrderCallConfig));
|
||
// 一段时间不跑任务
|
||
var now = DateTime.Now;
|
||
if (DateTime.TryParse(genOrderCallConfig.HgrecordStime, out DateTime stime)
|
||
&& DateTime.TryParse(genOrderCallConfig.HgrecordEtime, out DateTime etime))
|
||
{
|
||
if (now.TimeOfDay < stime.TimeOfDay || now.TimeOfDay > etime.TimeOfDay)
|
||
{
|
||
LogHelper.Info($"GetOrder Sleep:stime:{stime},etime:{etime},当前:{now.TimeOfDay}");
|
||
return;
|
||
}
|
||
}
|
||
|
||
times++;
|
||
List<int> status = new List<int> { 0, 6 };
|
||
status.AddRange(genOrderCallConfig.ReCallStatus);
|
||
|
||
if (times % 2 != 1) status = new List<int> { 0 };
|
||
var calltime = DateTime.Now.AddDays(-genOrderCallConfig.CallDay);
|
||
if (!startTime.HasValue) startTime = genOrderCallConfig.StartTime;
|
||
startTime = startTime < calltime ? calltime : startTime;
|
||
var orderlist = InitDB.zxdcrmDb.Queryable<WxSzzyorder>()
|
||
// .Select(d=>new WxSzzyorder { Orderid = d.Orderid,Cname=d.Cname,Idcard=d.Idcard,Subproductname=d.Subproductname,Subproductid=d.Subproductid,Arrivalpay=d.Arrivalpay, Opendays=d.Opendays,Giftdays=d.Giftdays,Giftdays2=d.Giftdays2, Resid = d.Resid, Ctime = d.Ctime, Channel = d.Channel, Contractctime = d.Contractctime,AiHgrecordStime=d.AiHgrecordStime,AiHgrecordEtime=d.AiHgrecordEtime })
|
||
.Where(d => d.Orderstatus!.Equals("200") && status.Contains(d.AiHgrecordStatus.Value))
|
||
.Where(d => d.Contractctime >= startTime)
|
||
.Where(d => d.Idcard != null)
|
||
.Where(d => d.Hashgrecord == null || d.Hashgrecord != 1) //判断是否已经进行过合规
|
||
//.Where(d=>d.Orderid== 81118603)
|
||
.OrderBy(d => d.Orderid).Take(GetNum).ToList();
|
||
//测试
|
||
//orderlist = InitDB.zxdcrmDb.Queryable<WxSzzyorder>().Where(n => n.Orderid == 80338991).ToList();
|
||
|
||
if (orderlist.Count < GetNum) GetNum = GetNum <= 20 ? GetNum : GetNum - 20;
|
||
if (orderlist.Count >= GetNum) GetNum = GetNum >= 500 ? GetNum : GetNum + 100;
|
||
|
||
var filterCodes = orderlist.Select(n => n.Productcode).Distinct().ToList();
|
||
var basProduct = InitDB.dbcrmDb.Queryable<TProduct>().Where(n => filterCodes.Contains(n.id)).ToList();
|
||
var basPackage = InitDB.dbcrmDb.Queryable<TPackageProduct>().Where(n => filterCodes.Contains(n.id)).ToList();
|
||
var updatenum = 0;
|
||
foreach (var item in orderlist)
|
||
{
|
||
var product = basProduct.FirstOrDefault(n => n.id == item.Productcode);
|
||
if (product != null)
|
||
{
|
||
if (genOrderCallConfig.IgnoreProductType.Contains(product.groupid))
|
||
{
|
||
LogHelper.Info($"IgnoreProductType: 订单【{item.Orderid}】产品类型为{product.groupid}忽略不外呼");
|
||
continue;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
var package = basPackage.FirstOrDefault(n => n.id == item.Productcode);
|
||
if (package != null && genOrderCallConfig.IgnoreProductType.Contains(package.groupid))
|
||
{
|
||
LogHelper.Info($"IgnoreProductType: 订单【{item.Orderid}】产品类型为{product.groupid}忽略不外呼");
|
||
continue;
|
||
}
|
||
}
|
||
WxSzzyorder wxSzzyorder;
|
||
if (wxSzzyorders.TryRemove(item.Orderid, out wxSzzyorder))
|
||
{
|
||
wxSzzyorders.TryAdd(item.Orderid, item);
|
||
updatenum++;
|
||
}
|
||
else
|
||
{
|
||
//处理时加入处理列表,处理列表有的时候暂不加入待处理列表
|
||
if (!wxSzzyordersChecking.ContainsKey(item.Orderid))
|
||
{
|
||
wxSzzyorders.TryAdd(item.Orderid, item);
|
||
}
|
||
}
|
||
}
|
||
LogHelper.Info($"查询数据times:{times}次,status={SerializeHelper.ToJson(status)}数据:{orderlist.Count},当前待处理列表:{wxSzzyorders.Count},正在处理列表:{wxSzzyordersChecking.Count},更新数据:{updatenum};");
|
||
CheckOrderList();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.Error($"查询数据错误!{ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查列表
|
||
/// </summary>
|
||
public void CheckOrderList()
|
||
{
|
||
var sameuserlist = wxSzzyorders.Values.GroupBy(d => new { d.Resid }, d => d);
|
||
LogHelper.Info($"检查订单数量:【{wxSzzyorders.Count}】相同用户数量:【{sameuserlist.Count()}】");
|
||
foreach (var item in sameuserlist)
|
||
{
|
||
var resid = item.Key.Resid!.ToString();
|
||
var wxSzzyorderslist = item.ToList();
|
||
LogHelper.Info($"开始检查用户:【{resid}】满足条件订单【{string.Join(",", wxSzzyorderslist.Select(n => n.Orderid))}】");
|
||
//同人有未完成订单且未超时的不处理
|
||
if (CheckOrderSameUserNotFinish(resid, wxSzzyorderslist))
|
||
{
|
||
wxSzzyorderslist.ForEach(d =>
|
||
{
|
||
WxSzzyorder wxSzzyorder;
|
||
wxSzzyorders.TryRemove(d.Orderid, out wxSzzyorder);
|
||
});
|
||
continue;
|
||
}
|
||
|
||
var checklist = new List<WxSzzyorder>();
|
||
foreach (var wxSzzyorderitem in wxSzzyorderslist)
|
||
{
|
||
LogHelper.Info($"开始检查订单:【{wxSzzyorderitem.Orderid}】");
|
||
WxSzzyorder wxSzzyorder;
|
||
|
||
//加入正在处理列表
|
||
wxSzzyordersChecking.TryAdd(wxSzzyorderitem.Orderid, wxSzzyorderitem);
|
||
if (wxSzzyorders.TryRemove(wxSzzyorderitem.Orderid, out wxSzzyorder))
|
||
{
|
||
if (CheckOrderFail(wxSzzyorder) && !CheckOrderIgnore(wxSzzyorder))
|
||
{
|
||
//忽略的不处理
|
||
checklist.Add(wxSzzyorder);
|
||
}
|
||
}
|
||
}
|
||
//处理
|
||
if (checklist.Count > 0)
|
||
{
|
||
CheckOrder(checklist);
|
||
}
|
||
//取出正在处理列表
|
||
wxSzzyorderslist.ForEach(d =>
|
||
{
|
||
WxSzzyorder wxSzzyorder;
|
||
wxSzzyordersChecking.TryRemove(d.Orderid, out wxSzzyorder);
|
||
});
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查同人,若同人有一定时间内的未完成订单,将不处理,等待完成。
|
||
/// </summary>
|
||
/// <param name="resid"></param>
|
||
/// <param name="wxSzzyorders"></param>
|
||
/// <returns></returns>
|
||
public static bool CheckOrderSameUserNotFinish(string resid, List<WxSzzyorder> wxSzzyorders)
|
||
{
|
||
var orderlist = wxSzzyorders.Select(d => d.Orderid).ToList();
|
||
//四种状态
|
||
List<int> status = new List<int> { 0, 6 };
|
||
status.AddRange(genOrderCallConfig.ReCallStatus);
|
||
//查看一下是否有当天已支付 未合规 且未签合同的 其他单
|
||
var sevenDay = DateTime.Now.Date.AddDays(-7);
|
||
var wlist = InitDB.zxdcrmDb.Queryable<WxSzzyorder>().Where(d => d.Resid == resid && d.Ctime >= sevenDay)
|
||
.Where(d => status.Contains(d.AiHgrecordStatus.Value))
|
||
.Where(d => d.Hashgrecord == null || d.Hashgrecord != 1)
|
||
.Where(d => !orderlist.Contains(d.Orderid)).ToList();
|
||
//查看一下是否有当天已支付 或者 已提交支付 未签合同的 其他单
|
||
List<string> waitStatus = new List<string> { "200", "190" };
|
||
var hasPayList = wlist.Where(d => waitStatus.Contains(d.Orderstatus)).ToList();
|
||
if (hasPayList.Count > 0)
|
||
{
|
||
LogHelper.Info($"检查相同用户:【{resid}】,正在等待已支付单【{string.Join(",", hasPayList.Select(n => n.Orderid).ToList())}】");
|
||
return true;
|
||
}
|
||
var noPayList = wlist.Where(d => !waitStatus.Contains(d.Orderstatus) && d.Ctime >= DateTime.Now.Date).ToList();
|
||
if (noPayList.Count > 0)
|
||
{
|
||
var maxTime = wxSzzyorders.Select(d => d.Contractctime).Max();
|
||
var timespan = DateTime.Now - maxTime;
|
||
if (timespan.HasValue && timespan.Value.Minutes < genOrderCallConfig.SameUserCheckTimeSpanMin)
|
||
{
|
||
LogHelper.Info($"检查相同用户:{resid},合同最大签订时间:{maxTime},有未支付订单【{string.Join(",", noPayList.Select(n => n.Orderid))}】,需等待时间:{genOrderCallConfig.SameUserCheckTimeSpanMin},已等待【{timespan.Value.Minutes}分钟】");
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查订单
|
||
/// </summary>
|
||
/// <param name="wxSzzyorders">订单列表</param>
|
||
|
||
public static void CheckOrder(List<WxSzzyorder> wxSzzyorders)
|
||
{
|
||
LogHelper.Info($"开始处理:resid:{wxSzzyorders.First().Resid},订单号【{string.Join(",", wxSzzyorders.Select(n => n.Orderid))}】");
|
||
var oldTaskList = InitDB.zxdcrmDb.Queryable<CsvrAiCalltaskOrders>()
|
||
.Where(d => wxSzzyorders.Select(n => n.Orderid).ToList().Contains(d.Orderid.Value)).ToList();
|
||
try
|
||
{
|
||
CsvrAiCalltask csvrAiCalltask = GetCsvrAiCalltaskFromConfig(wxSzzyorders.First());
|
||
csvrAiCalltask.Resid = wxSzzyorders.First().Resid;
|
||
csvrAiCalltask.Props = GetPropos(wxSzzyorders);
|
||
csvrAiCalltask.Status = 0;
|
||
csvrAiCalltask.Ctime = DateTime.Now;
|
||
csvrAiCalltask.AiHgrecordStatus = 1;
|
||
if (oldTaskList.Count > 0)
|
||
{
|
||
csvrAiCalltask.HasCall = 1;
|
||
}
|
||
else
|
||
{
|
||
//等待重播不需要修改状态为 等待AI外呼
|
||
wxSzzyorders.ForEach(d =>
|
||
{
|
||
d.AiHgrecordStatus = 1;
|
||
});
|
||
}
|
||
|
||
var csvrAiCalltaskOrders = GetCsvrAiCalltaskOrders(wxSzzyorders);
|
||
LogHelper.Info($"Props:{csvrAiCalltask.Props}");
|
||
CreatCsvrAiCalltask(wxSzzyorders, csvrAiCalltask, csvrAiCalltaskOrders);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.Error($"resid:{wxSzzyorders.First().Resid}处理失败,orderid:{SerializeHelper.ToJson(wxSzzyorders.Select(d => d.Orderid).ToList())},{ex.Message}");
|
||
}
|
||
}
|
||
|
||
private static List<CsvrAiCalltaskOrders> GetCsvrAiCalltaskOrders(List<WxSzzyorder> wxSzzyorders)
|
||
{
|
||
List<CsvrAiCalltaskOrders> csvrAiCalltaskOrders = new List<CsvrAiCalltaskOrders>();
|
||
foreach (var item in wxSzzyorders)
|
||
{
|
||
LogHelper.Info($"Orderid:{item.Orderid},AiHgrecordStatus:{item.AiHgrecordStatus}");
|
||
csvrAiCalltaskOrders.Add(new CsvrAiCalltaskOrders
|
||
{
|
||
Orderid = item.Orderid,
|
||
Subproductname = item.Subproductname,
|
||
Cname = item.Cname,
|
||
Idcard = item.Idcard
|
||
});
|
||
}
|
||
return csvrAiCalltaskOrders;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建任务
|
||
/// </summary>
|
||
/// <param name="wxSzzyorders"></param>
|
||
/// <param name="csvrAiCalltask"></param>
|
||
/// <param name="csvrAiCalltaskOrders"></param>
|
||
public static void CreatCsvrAiCalltask(List<WxSzzyorder> wxSzzyorders, CsvrAiCalltask csvrAiCalltask, List<CsvrAiCalltaskOrders> csvrAiCalltaskOrders)
|
||
{
|
||
try
|
||
{
|
||
InitDB.zxdcrmDb.Ado.BeginTran();
|
||
|
||
InitDB.zxdcrmDb.Updateable(wxSzzyorders).UpdateColumns(d => new { d.AiHgrecordStatus, d.AiHgrecordStatusname }).ExecuteCommand();
|
||
var id = InitDB.zxdcrmDb.Insertable(csvrAiCalltask).ExecuteReturnIdentity();
|
||
|
||
foreach (var item in csvrAiCalltaskOrders)
|
||
{
|
||
item.Taskid = id;
|
||
}
|
||
InitDB.zxdcrmDb.Insertable(csvrAiCalltaskOrders).ExecuteCommand();
|
||
|
||
InitDB.zxdcrmDb.Ado.CommitTran();
|
||
LogHelper.Info($"CreatCsvrAiCalltask:{csvrAiCalltask.Resid},Exetime:{csvrAiCalltask.Exetime}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
InitDB.zxdcrmDb.Ado.RollbackTran();
|
||
LogHelper.Error($"orderid:{SerializeHelper.ToJson(wxSzzyorders.Select(d => d.Orderid))}", ex);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// "姓氏":"郭",
|
||
/// "先生/女士":"先生",
|
||
/// "姓名":"郭立兴",
|
||
/// "身份证后6位":"310911",
|
||
/// "产品确认":"智赢系列"
|
||
/// </summary>
|
||
/// <param name="wxSzzyorders"></param>
|
||
/// <returns></returns>
|
||
public static string GetPropos(List<WxSzzyorder> wxSzzyorders)
|
||
{
|
||
var wxSzzyorder = wxSzzyorders.First();
|
||
Dictionary<string, string> Proposkv = new Dictionary<string, string>();
|
||
Proposkv.Add("【姓氏】", wxSzzyorder.Cname!.Substring(0, 1));
|
||
var cardnum = 1;
|
||
if (wxSzzyorder.Idcard!.Length == 18) cardnum = int.Parse(wxSzzyorder.Idcard.Substring(16, 1));
|
||
Proposkv.Add("【先生/女士】", cardnum % 2 == 1 ? "先生" : "女士");
|
||
Proposkv.Add("【姓名】", wxSzzyorder.Cname);
|
||
Proposkv.Add("【身份证后4位】", wxSzzyorder.Idcard.Substring(wxSzzyorder.Idcard.Length - 4, 4));
|
||
|
||
var productConfir = "";
|
||
|
||
if (wxSzzyorders.Count == 1)
|
||
{
|
||
var subproductname = genOrderCallConfig.proposProductConfig.Subproductname.Replace("#Subproductname", wxSzzyorder.Subproductname);
|
||
productConfir = genOrderCallConfig.proposProductConfig.OneTemplate
|
||
.Replace("@Subproductname", subproductname)
|
||
.Replace("#Arrivalpay", PriceToCn(wxSzzyorder.Arrivalpay.Value));
|
||
var payexp = "";
|
||
if (wxSzzyorder.Opendays > 1)
|
||
{
|
||
payexp = genOrderCallConfig.proposProductConfig.PayExp.Replace("@Subproductname", "")
|
||
.Replace("#OpenDays", toHanStr(wxSzzyorder.Opendays.ToString()));
|
||
var gift = "";
|
||
var giftday = 0;
|
||
if (wxSzzyorder.Giftdays.HasValue) giftday += wxSzzyorder.Giftdays.Value;
|
||
if (wxSzzyorder.Giftdays2.HasValue) giftday += wxSzzyorder.Giftdays2.Value;
|
||
if (giftday > 0)
|
||
{
|
||
gift = genOrderCallConfig.proposProductConfig.GiftExp.Replace("#GiftDays", toHanStr(giftday.ToString()));
|
||
gift = gift.Replace("#OpenDays", toHanStr((wxSzzyorder.Opendays + giftday).ToString()));
|
||
}
|
||
payexp = payexp.Replace("@GiftExp", gift);
|
||
}
|
||
productConfir = productConfir.Replace("@PayExp", payexp);
|
||
if (payexp.Equals("")) productConfir = productConfir.Replace(",,", ",");
|
||
}
|
||
else
|
||
{
|
||
var subproductnames = "";
|
||
var payexps = "";
|
||
foreach (var item in wxSzzyorders.GroupBy(d => d.Subproductname, d => d).ToList())
|
||
{
|
||
var subproductname = genOrderCallConfig.proposProductConfig.Subproductname.Replace("#Subproductname", item.Key);
|
||
|
||
subproductnames += subproductname + "和";
|
||
if (item.Sum(d => d.Opendays) == item.Count()) continue;
|
||
var payexp = genOrderCallConfig.proposProductConfig.PayExp.Replace("@Subproductname", subproductname)
|
||
.Replace("#OpenDays", toHanStr(item.Sum(d => d.Opendays).ToString()));
|
||
var gift = "";
|
||
var giftday = 0;
|
||
foreach (var subwxSzzyorderitem in item)
|
||
{
|
||
if (subwxSzzyorderitem.Giftdays.HasValue) giftday += subwxSzzyorderitem.Giftdays.Value;
|
||
if (subwxSzzyorderitem.Giftdays2.HasValue) giftday += subwxSzzyorderitem.Giftdays2.Value;
|
||
}
|
||
if (giftday > 0)
|
||
{
|
||
gift = genOrderCallConfig.proposProductConfig.GiftExp.Replace("#GiftDays", toHanStr(giftday.ToString()));
|
||
gift = gift.Replace("#OpenDays", toHanStr((item.Sum(d => d.Opendays) + giftday).ToString()));
|
||
}
|
||
payexp = payexp.Replace("@GiftExp", gift);
|
||
|
||
payexps += payexp;
|
||
}
|
||
subproductnames = subproductnames.Substring(0, subproductnames.Length - 1);
|
||
if (payexps.Length > 1) payexps = payexps.Substring(0, payexps.Length - 1);
|
||
productConfir = genOrderCallConfig.proposProductConfig.MultipleTemplate
|
||
.Replace("@Subproductname", subproductnames)
|
||
.Replace("@PayExp", payexps)
|
||
.Replace("#Arrivalpay", PriceToCn(wxSzzyorders.Sum(d => d.Arrivalpay).Value));
|
||
}
|
||
|
||
Proposkv.Add("【产品确认】", productConfir);
|
||
var result = SerializeHelper.ToJson(Proposkv);
|
||
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 金额数字转大写(带小数点)
|
||
/// </summary>
|
||
public static string PriceToCn(decimal price)
|
||
{
|
||
//数字转大写
|
||
string[] n = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
|
||
string[] d = { "", "分", "角", "元", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿" };
|
||
|
||
//不同位置的数字要加单位
|
||
List<string> needReplace = new List<string> { "零拾", "零佰", "零仟", "零万", "零亿", "亿万", "零元", "零零", "零角", "零分" };
|
||
List<string> afterReplace = new List<string> { "零", "零", "零", "万", "亿", "亿", "元", "零", "零", "" };
|
||
|
||
string e = price % 1 == 0 ? "整" : ""; //金额是整数,加一个“整”结尾
|
||
string re = "";
|
||
int a = (int)(price * 100);
|
||
int k = 1;
|
||
while (a != 0)
|
||
{
|
||
//初步转换大小写
|
||
re = n[a % 10] + d[k] + re;
|
||
a = a / 10;
|
||
k = k < 11 ? k + 1 : 4;
|
||
}
|
||
|
||
string need = needReplace.Where(tb => re.Contains(tb)).FirstOrDefault<string>();
|
||
while (need != null)
|
||
{
|
||
int i = needReplace.IndexOf(need);
|
||
re = re.Replace(needReplace[i], afterReplace[i]);
|
||
need = needReplace.Where(tb => re.Contains(tb)).FirstOrDefault<string>();
|
||
}//循环排除特殊情况
|
||
// re = re == "" ? "零元" : re + e;
|
||
re = re == "" ? "零元" : re;
|
||
return re;
|
||
}
|
||
|
||
public static string toHanStr(String numStr)
|
||
{
|
||
var price = Convert.ToDecimal(numStr);
|
||
//数字转大写
|
||
string[] n = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
|
||
string[] d = { "", "分", "角", "元", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿" };
|
||
|
||
//不同位置的数字要加单位
|
||
List<string> needReplace = new List<string> { "零拾", "零佰", "零仟", "零万", "零亿", "亿万", "零元", "零零", "零角", "零分" };
|
||
List<string> afterReplace = new List<string> { "零", "零", "零", "万", "亿", "亿", "元", "零", "零", "" };
|
||
|
||
string e = price % 1 == 0 ? "整" : ""; //金额是整数,加一个“整”结尾
|
||
string re = "";
|
||
int a = (int)(price * 100);
|
||
int k = 1;
|
||
while (a != 0)
|
||
{
|
||
//初步转换大小写
|
||
re = n[a % 10] + d[k] + re;
|
||
a = a / 10;
|
||
k = k < 11 ? k + 1 : 4;
|
||
}
|
||
|
||
string need = needReplace.Where(tb => re.Contains(tb)).FirstOrDefault<string>();
|
||
while (need != null)
|
||
{
|
||
int i = needReplace.IndexOf(need);
|
||
re = re.Replace(needReplace[i], afterReplace[i]);
|
||
need = needReplace.Where(tb => re.Contains(tb)).FirstOrDefault<string>();
|
||
}//循环排除特殊情况
|
||
// re = re == "" ? "零元" : re + e;
|
||
re = re == "" ? "零" : re.Replace("元", "");
|
||
return re;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取任务
|
||
/// </summary>
|
||
/// <param name="wxSzzyorder"></param>
|
||
/// <returns></returns>
|
||
public static CsvrAiCalltask GetCsvrAiCalltaskFromConfig(WxSzzyorder wxSzzyorder)
|
||
{
|
||
CsvrAiCalltask csvrAiCalltask = new CsvrAiCalltask();
|
||
csvrAiCalltask.Robot = genOrderCallConfig.Robot;
|
||
csvrAiCalltask.AppId = genOrderCallConfig.AppId;
|
||
csvrAiCalltask.CallNo = genOrderCallConfig.CallNo;
|
||
|
||
csvrAiCalltask.Sms = genOrderCallConfig.Sms;
|
||
DateTime now = DateTime.Now;
|
||
var expmin = genOrderCallConfig.SmsExprieMinCall;
|
||
csvrAiCalltask.Smstime = now;
|
||
csvrAiCalltask.Exetime = now.AddMinutes(expmin);
|
||
|
||
//优先级别1-紧急 2-优先
|
||
csvrAiCalltask.Priority = genOrderCallConfig.Priority;
|
||
|
||
return csvrAiCalltask;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 失败订单重试//true 重试
|
||
/// </summary>
|
||
/// <param name="wxSzzyorder"></param>
|
||
/// <returns></returns>
|
||
public static bool CheckOrderFail(WxSzzyorder wxSzzyorder)
|
||
{
|
||
var aihgrecoedStatus = wxSzzyorder.AiHgrecordStatus!.Value;
|
||
var now = DateTime.Now;
|
||
var ReCallMin = genOrderCallConfig.ReCallMins;
|
||
var ReCallStatus = genOrderCallConfig.ReCallStatus;
|
||
if (ReCallStatus.Contains(aihgrecoedStatus) || aihgrecoedStatus == 6)
|
||
{
|
||
var taskids = InitDB.zxdcrmDb.Queryable<CsvrAiCalltaskOrders>().Where(d => d.Orderid == wxSzzyorder.Orderid).OrderByDescending(d => d.Taskid).Select(d => d.Taskid).ToList();
|
||
if (taskids == null || taskids.Count == 0)
|
||
{
|
||
return true;
|
||
}
|
||
var logInfo = $"检查订单重试:【{wxSzzyorder.Orderid}】,状态:【{wxSzzyorder.AiHgrecordStatusname}】任务Id【{SerializeHelper.ToJson(taskids)}】";
|
||
LogHelper.Info($"{logInfo}");
|
||
var maxid = taskids.Max(d => d.Value);
|
||
var exectime = InitDB.zxdcrmDb.Queryable<CsvrAiCalltask>().Where(d => d.Id == maxid).OrderByDescending(d => d.Id).Select(d => d.Exetime).First();
|
||
var min = 0;
|
||
if (taskids.Count() > ReCallMin.Count)
|
||
{
|
||
LogHelper.Info($"{logInfo}超过最大重试次数【{ReCallMin.Count}】,忽略。");
|
||
//wxSzzyorder.AiHgrecordStatus = -2;
|
||
//InitDB.zxdcrmDb.Updateable(wxSzzyorder).UpdateColumns(d => new { d.AiHgrecordStatus, d.AiHgrecordStatusname }).ExecuteCommand();
|
||
return false;
|
||
}
|
||
else
|
||
{
|
||
min = ReCallMin[taskids.Count() - 1];
|
||
}
|
||
var difmin = now - exectime!.Value;
|
||
|
||
// 如果在固定时间内的话直接重试
|
||
DateTime stime;
|
||
DateTime etime;
|
||
if (DateTime.TryParse(wxSzzyorder.AiHgrecordStime, out stime) && DateTime.TryParse(wxSzzyorder.AiHgrecordEtime, out etime))
|
||
{
|
||
if (now.TimeOfDay >= stime.TimeOfDay && now.TimeOfDay <= etime.TimeOfDay)
|
||
{
|
||
LogHelper.Info($"{logInfo}: 设置间隔【{stime}-{etime}】当前:{now.TimeOfDay},上次执行时间:{exectime!.Value},开始重试!");
|
||
return true;
|
||
}
|
||
}
|
||
if (difmin.TotalMinutes > min)
|
||
{
|
||
LogHelper.Info($"{logInfo}exectime:{exectime!.Value},开始重试!");
|
||
return true;
|
||
}
|
||
|
||
if (ReCallStatus.Contains(aihgrecoedStatus))
|
||
{
|
||
LogHelper.Info($"{logInfo},修改为等待重拨");
|
||
wxSzzyorder.AiHgrecordStatus = 6;
|
||
InitDB.zxdcrmDb.Updateable(wxSzzyorder).UpdateColumns(d => new { d.AiHgrecordStatus, d.AiHgrecordStatusname }).ExecuteCommand();
|
||
}
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查是否忽略,忽略更新Ai_hgrecord_status=4
|
||
/// </summary>
|
||
/// <param name="wxSzzyorder"></param>
|
||
/// <returns></returns>
|
||
public bool CheckOrderIgnore(WxSzzyorder wxSzzyorder)
|
||
{
|
||
bool Ignore = false;
|
||
var now = DateTime.Now;
|
||
//小于最小订单金额
|
||
if (wxSzzyorder.Arrivalpay < genOrderCallConfig.MinAmount && !genOrderCallConfig.WhiteList.Contains(wxSzzyorder.Resid))
|
||
{
|
||
LogHelper.Info($"订单【{wxSzzyorder.Orderid}】金额【{wxSzzyorder.Arrivalpay}】小于外呼设置金额【{genOrderCallConfig.MinAmount}】跳过");
|
||
Ignore = true;
|
||
}
|
||
|
||
//忽略本次,不更新字段
|
||
DateTime stime;
|
||
DateTime etime;
|
||
if (DateTime.TryParse(wxSzzyorder.AiHgrecordStime, out stime) && DateTime.TryParse(wxSzzyorder.AiHgrecordEtime, out etime))
|
||
{
|
||
if (now.TimeOfDay < stime.TimeOfDay || now.TimeOfDay > etime.TimeOfDay)
|
||
{
|
||
LogHelper.Info($"订单【{wxSzzyorder.Orderid}回访时间【{wxSzzyorder.AiHgrecordStime}-{wxSzzyorder.AiHgrecordEtime}】不在范围之内当前时间:{now.TimeOfDay}");
|
||
return true;
|
||
}
|
||
}
|
||
|
||
if (!Ignore)
|
||
{
|
||
if (genOrderCallConfig.IgnoreHitConfigs != null)
|
||
{
|
||
foreach (var hitConfig in genOrderCallConfig.IgnoreHitConfigs)
|
||
{
|
||
//检查渠道
|
||
if (HitKey.Channel.ToString().Equals(hitConfig.HitKey))
|
||
{
|
||
//包含
|
||
if (hitConfig.Contain != null && hitConfig.Contain.Count > 0)
|
||
{
|
||
foreach (var item in hitConfig.Contain)
|
||
{
|
||
var channelitem = GetChannelItem(item);
|
||
if (wxSzzyorder.Channel >= channelitem.Min && wxSzzyorder.Channel <= channelitem.Max)
|
||
{
|
||
LogHelper.Info($"Ignore,hitConfig.Contain:Channel:{wxSzzyorder.Channel},Min:{channelitem.Min},Max:{channelitem.Max}");
|
||
Ignore = true;
|
||
}
|
||
else
|
||
{
|
||
Ignore = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
//不包含,结果会被不包含覆盖,不包含优先级更高
|
||
if (hitConfig.NoContain != null && hitConfig.NoContain.Count > 0)
|
||
{
|
||
foreach (var item in hitConfig.NoContain)
|
||
{
|
||
var channelitem = GetChannelItem(item);
|
||
if (wxSzzyorder.Channel < channelitem.Min || wxSzzyorder.Channel > channelitem.Max)
|
||
{
|
||
LogHelper.Info($"Ignore,resid: {wxSzzyorder.Resid}, orderid: {wxSzzyorder.Orderid}, hitConfig.NoContain:Channel:{wxSzzyorder.Channel},Min:{channelitem.Min},Max:{channelitem.Max}");
|
||
Ignore = true;
|
||
}
|
||
else
|
||
{
|
||
Ignore = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//检查产品Id
|
||
if (HitKey.Subproductid.ToString().Equals(hitConfig.HitKey) && !Ignore)
|
||
{ //包含
|
||
if (hitConfig.Contain != null && hitConfig.Contain.Count > 0)
|
||
{
|
||
if (hitConfig.Contain.Contains(wxSzzyorder.Subproductid!.Value.ToString()))
|
||
{
|
||
LogHelper.Info($"Ignore,resid: {wxSzzyorder.Resid}, orderid: {wxSzzyorder.Orderid}, hitConfig.Contain:Subproductid:{wxSzzyorder.Subproductid.ToString()}");
|
||
Ignore = true;
|
||
}
|
||
else
|
||
{
|
||
Ignore = false;
|
||
break;
|
||
}
|
||
}
|
||
//不包含,结果会被不包含覆盖,不包含优先级更高
|
||
if (hitConfig.NoContain != null && hitConfig.NoContain.Count > 0)
|
||
{
|
||
if (!hitConfig.NoContain.Contains(wxSzzyorder.Subproductid!.Value.ToString()))
|
||
{
|
||
LogHelper.Info($"Ignore,resid: {wxSzzyorder.Resid}, orderid: {wxSzzyorder.Orderid}, hitConfig.NoContain:Subproductid:{wxSzzyorder.Subproductid.ToString()}");
|
||
Ignore = true;
|
||
}
|
||
else
|
||
{
|
||
Ignore = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
//检查Resid
|
||
if (HitKey.Resid.ToString().Equals(hitConfig.HitKey) && !Ignore)
|
||
{ //包含
|
||
if (hitConfig.Contain != null && hitConfig.Contain.Count > 0)
|
||
{
|
||
if (hitConfig.Contain.Contains(wxSzzyorder.Resid!.ToString()))
|
||
{
|
||
LogHelper.Info($"Ignore,resid: {wxSzzyorder.Resid}, orderid: {wxSzzyorder.Orderid}, hitConfig.Contain:Resid:{wxSzzyorder.Resid!.ToString()}");
|
||
Ignore = true;
|
||
}
|
||
else
|
||
{
|
||
Ignore = false;
|
||
break;
|
||
}
|
||
}
|
||
//不包含,结果会被不包含覆盖,不包含优先级更高
|
||
if (hitConfig.NoContain != null && hitConfig.NoContain.Count > 0)
|
||
{
|
||
if (!hitConfig.NoContain.Contains(wxSzzyorder.Resid!.ToString()))
|
||
{
|
||
LogHelper.Info($"Ignore,resid: {wxSzzyorder.Resid}, orderid: {wxSzzyorder.Orderid}, hitConfig.NoContain:Resid:{wxSzzyorder.Resid!.ToString()}");
|
||
Ignore = true;
|
||
}
|
||
else
|
||
{
|
||
Ignore = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!Ignore)
|
||
{
|
||
//检查产品是否为不需要风控的自动开通产品
|
||
var subproduct = InitDB.zxdcrmDb.Queryable<WxSzzysubproduct>().Where(d => d.Subproductid == wxSzzyorder.Subproductid).First();
|
||
//如果不需要ai回访 则忽略
|
||
if (subproduct.NeedAi == 0)
|
||
{
|
||
LogHelper.Info($"Ignore,resid: {wxSzzyorder.Resid}, orderid: {wxSzzyorder.Orderid}, NeedAi:subproduct:{wxSzzyorder.Subproductid!.ToString()}");
|
||
Ignore = true;
|
||
}
|
||
/* if (subproduct != null && subproduct.AutomaticOpen == 1 && subproduct.NeedFK == 0)
|
||
{
|
||
LogHelper.Info($"Ignore,resid: {wxSzzyorder.Resid}, orderid: {wxSzzyorder.Orderid}, NotNeedFK:subproduct:{wxSzzyorder.Subproductid!.ToString()}");
|
||
Ignore = true;
|
||
}*/
|
||
}
|
||
|
||
if (Ignore)
|
||
{
|
||
wxSzzyorder.AiHgrecordStatus = -1;
|
||
LogHelper.Info($"Ignore,resid: {wxSzzyorder.Resid}, orderid: {wxSzzyorder.Orderid}, -1");
|
||
// wxSzzyorder.Ai_hgrecord_statusname = Ai_hgrecord_statusnameKV[wxSzzyorder.Ai_hgrecord_status];
|
||
InitDB.zxdcrmDb.Updateable(wxSzzyorder).UpdateColumns(d => new { d.AiHgrecordStatus, d.AiHgrecordStatusname }).ExecuteCommand();
|
||
}
|
||
|
||
return Ignore;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取channelItem
|
||
/// </summary>
|
||
/// <param name="ChannelStr"></param>
|
||
/// <returns></returns>
|
||
public static ChannelItem GetChannelItem(string ChannelStr)
|
||
{
|
||
ChannelItem channelItem = new ChannelItem { Max = 0, Min = 0 };
|
||
try
|
||
{
|
||
int min = 0;
|
||
int max = 0;
|
||
var c = ChannelStr.Split('|');
|
||
int.TryParse(c[0], out min);
|
||
int.TryParse(c[1], out max);
|
||
channelItem.Max = max;
|
||
channelItem.Min = min;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.Error($"ChannelStr:{ChannelStr}格式异常", ex);
|
||
return channelItem;
|
||
}
|
||
return channelItem;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取配置
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
/// <exception cref="Exception"></exception>
|
||
public static AI_CallTaskConfig GetConfig()
|
||
{
|
||
try
|
||
{
|
||
var test = new AI_CallTaskConfig();
|
||
test.IgnoreHitConfigs.Add(new HitConfig());
|
||
var s = SerializeHelper.ToJson(test);
|
||
InitConfig initConfig = new InitConfig();
|
||
|
||
genOrderCallConfig = initConfig.Get_CallTaskConfig();
|
||
|
||
if (string.IsNullOrEmpty(genOrderCallConfig.AppId))
|
||
{
|
||
var errmsg = "获取AI_CallTaskConfig失败:AppId 为空!";
|
||
LogHelper.Error(errmsg);
|
||
throw new Exception(errmsg);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.Error(ex, "AI_CallTaskConfig,配置出错");
|
||
}
|
||
|
||
return genOrderCallConfig;
|
||
}
|
||
|
||
#region 测试方法
|
||
|
||
public static AI_CallTaskConfig RefreshConfig()
|
||
{
|
||
genOrderCallConfig = GetConfig();
|
||
return genOrderCallConfig;
|
||
}
|
||
|
||
public string BuildProposTest(List<decimal> orderids)
|
||
{
|
||
var orderList = InitDB.zxdcrmDb.Queryable<WxSzzyorder>().Where(n => orderids.Contains(n.Orderid)).ToList();
|
||
var res = GetPropos(orderList);
|
||
return res;
|
||
}
|
||
|
||
#endregion 测试方法
|
||
|
||
/// <summary>
|
||
/// 人工手动拨打AI回访
|
||
/// </summary>
|
||
/// <param name="resid"></param>
|
||
/// <returns></returns>
|
||
public async Task<string> CreatAiOrder(string? resid)
|
||
{
|
||
if (resid == null)
|
||
{
|
||
return "resid不能为空!";
|
||
}
|
||
LogHelper.Info($"开始处理:resid:{resid}, 人工手动拨打AI回访!");
|
||
List<int> status = new List<int> { 0, 6 };
|
||
var aiHgrecordStatus = new List<int> { -2, 3, 7 };
|
||
status.AddRange(genOrderCallConfig.ReCallStatus);
|
||
var orderlist = await InitDB.zxdcrmDb.Queryable<WxSzzyorder>()
|
||
.Where(d => d.Resid == resid)
|
||
// .Select(d=>new WxSzzyorder { Orderid = d.Orderid,Cname=d.Cname,Idcard=d.Idcard,Subproductname=d.Subproductname,Subproductid=d.Subproductid,Arrivalpay=d.Arrivalpay, Opendays=d.Opendays,Giftdays=d.Giftdays,Giftdays2=d.Giftdays2, Resid = d.Resid, Ctime = d.Ctime, Channel = d.Channel, Contractctime = d.Contractctime,AiHgrecordStime=d.AiHgrecordStime,AiHgrecordEtime=d.AiHgrecordEtime })
|
||
.Where(d => d.Orderstatus!.Equals("200"))
|
||
.Where(x => x.AiHgrecordStatus != null && aiHgrecordStatus.Contains(x.AiHgrecordStatus.Value))
|
||
.Where(d => d.Contractctime >= startTime)
|
||
.Where(d => d.Idcard != null)
|
||
.Where(d => d.Hashgrecord == null || d.Hashgrecord != 1) //判断是否已经进行过合规
|
||
//.Where(d=>d.Orderid== 81118603)
|
||
.OrderBy(d => d.Orderid).ToListAsync();
|
||
if (orderlist == null || !orderlist.Any())
|
||
{
|
||
return "无订单可以进行回访!";
|
||
}
|
||
CheckOrder(orderlist);
|
||
orderlist.ForEach(d =>
|
||
{
|
||
d.AiHgrecordStatus = 6;
|
||
});
|
||
InitDB.zxdcrmDb.Updateable(orderlist).UpdateColumns(d => new { d.AiHgrecordStatus, d.AiHgrecordStatusname }).ExecuteCommand();
|
||
return $"成功发起任务【 {string.Join(",", orderlist.Select(x => x.Orderid).ToList())}】";
|
||
}
|
||
|
||
public async Task<string> CreatAiOrders(string? orderids)
|
||
{
|
||
if (orderids == null)
|
||
{
|
||
return "orderids不能为空!";
|
||
}
|
||
Log.Information($"开始处理:orderids:{orderids}, 人工手动拨打AI回访!");
|
||
try
|
||
{
|
||
var orderidList = orderids.Split(',').Select(x => int.Parse(x)).ToList();
|
||
List<int> status = new List<int> { 0, 6 };
|
||
var aiHgrecordStatus = new List<int> { -2, -1, 0, 3, 7 };
|
||
status.AddRange(genOrderCallConfig.ReCallStatus);
|
||
var orderlist = await InitDB.zxdcrmDb.Queryable<WxSzzyorder>()
|
||
.Where(d => orderidList.Contains(d.Orderid))
|
||
.Where(x => x.AiHgrecordStatus != null && aiHgrecordStatus.Contains(x.AiHgrecordStatus.Value))
|
||
.Where(d => d.Contractctime >= startTime)
|
||
.Where(d => d.Idcard != null)
|
||
.Where(d => d.Hashgrecord == null || d.Hashgrecord != 1)
|
||
.OrderBy(d => d.Orderid).ToListAsync();
|
||
if (orderlist == null || !orderlist.Any())
|
||
{
|
||
return "无订单可以进行回访!";
|
||
}
|
||
var sameuserlist = orderlist.GroupBy(d => new { d.Resid }, d => d);
|
||
foreach (var item in sameuserlist)
|
||
{
|
||
var wxSzzyorderslist = item.ToList();
|
||
CheckOrder(wxSzzyorderslist);
|
||
}
|
||
orderlist.ForEach(d =>
|
||
{
|
||
d.AiHgrecordStatus = 6;
|
||
});
|
||
InitDB.zxdcrmDb.Updateable(orderlist).UpdateColumns(d => new { d.AiHgrecordStatus, d.AiHgrecordStatusname }).ExecuteCommand();
|
||
return $"成功发起任务【 {string.Join(",", orderlist.Select(x => x.Orderid).ToList())}】";
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error(ex, "人工手动拨打AI回访");
|
||
return ex.Message;
|
||
}
|
||
}
|
||
}
|
||
} |