ComplianceServer/code/Hg.Core.Domain/OrderDomain.cs

1841 lines
91 KiB
C#
Raw Permalink 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 Hg.Core.Domain.Config;
using Hg.Core.Domain.Dto.Order;
using Hg.Core.Entity;
using OfficeOpenXml.Style;
using Oracle.ManagedDataAccess.Client;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Hg.Core.Domain
{
public class OrderDomain : IOrderDomain
{
private readonly IBaseRepository<ZxdDbContext> _repository;
private readonly IHttpClient _httpClient;
private readonly IMapper _mapper;
private readonly ICacheDomain _cacheDomain;
private readonly IConfiguration _configuration;
private readonly SystemConfig _systemConfig;
private readonly IProductDomain _productDomain;
private readonly IInneruserDomain _inneruserDomain;
private readonly IEmployeeDomain _employeeDomain;
private readonly IRedisManager _redisManager;
public OrderDomain(IConfiguration configuration,
IBaseRepository<ZxdDbContext> repository,
IHttpClient httpClient,
IMapper mapper,
ICacheDomain cacheDomain,
IProductDomain productDomain,
IInneruserDomain inneruserDomain,
IEmployeeDomain employeeDomain,
IRedisManager redisManager
)
{
_systemConfig = configuration.GetSection("SystemConfig").Get<SystemConfig>();
_configuration = configuration;
_repository = repository;
_httpClient = httpClient;
_mapper = mapper;
_cacheDomain = cacheDomain;
_productDomain = productDomain;
_inneruserDomain = inneruserDomain;
_employeeDomain = employeeDomain;
_redisManager = redisManager;
}
public async Task<List<WXSzzyOrderDto>> GetOrderListByResid(string resid)
{
List<WXSzzyOrderDto> res = new List<WXSzzyOrderDto>();
if (string.IsNullOrWhiteSpace(resid))
{
return res;
}
var companyList = await _cacheDomain.GetCompanyVirtualList();
var resIdList = resid.Split(",").ToList();
var list = await _repository.GetRepository<WX_SZZYORDER>().Query().Where(x => resIdList.Contains(x.RESID)).ToListAsync();//在坐席中对应的关系
foreach (var item in resIdList)
{
var rOList = list.Where(n => n.RESID == item).ToList();
var orderList = _mapper.Map<WX_SZZYORDER, WXSzzyOrderDto>(rOList);
foreach (var order in orderList)
{
order.ChannelName = ConvertChannelName(companyList, order.CHANNEL);
}
res.AddRange(orderList);
}
return res;
}
/// <summary>
/// 转换事业部
/// </summary>
/// <param name="channelList"></param>
/// <param name="channel"></param>
/// <returns></returns>
private string ConvertChannelName(List<Bas_CompanyVirtual> channelList, int? channel)
{
foreach (var item in channelList)
{
var channelStr = item.Channel.Split('|').ToList();
foreach (var str in channelStr)
{
var a = str.Split(',');
var min = Convert.ToInt32(a[0]);
var max = Convert.ToInt32(a[1]);
if (channel >= min && channel <= max)
{
return item.CompanyName;
}
}
}
return "";
}
public async Task<List<HHUserDto>> GetHHUserByResId(string resids)
{
List<HHUserDto> res = new List<HHUserDto>();
if (string.IsNullOrWhiteSpace(resids))
{
return res;
}
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var resIdList = resids.Split(",").ToList();
var customerQuery = _repository.GetRepository<RES_CUSTOMER>().Query();
var allCustomer = customerQuery.Where(n => resIdList.Contains(n.RESID)).ToList();
//var custFilter = allCustomer.Select(p => n.CUSTOMERID).
var otherCust = customerQuery.Where(n => allCustomer.Select(p => p.CUSTOMERID).Contains(n.CUSTOMERID)).ToList();
allCustomer.AddRange(otherCust);
var extQuery = _repository.GetRepository<Ww_Extuser_Resid>().Query().Where(n => allCustomer.Select(p => p.RESID).Contains(n.resid)).ToList();
List<HHUserDto> extlist = new List<HHUserDto>();
stopwatch.Stop();
Log.Information($"花费时间【{stopwatch.ElapsedMilliseconds}】ms");
stopwatch.Restart();
foreach (var resId in resIdList)
{
var resfilter = allCustomer.Where(n => n.RESID == resId || n.CUSTOMERID == resId).ToList();
var extUser = extQuery.Where(n => resfilter.Select(n => n.RESID).Contains(n.resid) || resfilter.Select(p => p.CUSTOMERID).Contains(n.resid)).ToList();
foreach (var ax in extUser)
{
var ext = _mapper.Map<Ww_Extuser_Resid, HHUserDto>(ax);
ext.ResId = resId;
extlist.Add(ext);
}
}
stopwatch.Stop();
Log.Information($"花费时间【{stopwatch.ElapsedMilliseconds}】ms");
stopwatch.Restart();
// var wxuserlist = await _repository.GetRepository<Wx_Username_Resid>().Query().Where(x => resIdList.Contains(x.resid)).ToListAsync();//在坐席中对应的关系
foreach (var item in resIdList)
{
var ext = extlist.Where(m => m.ResId == item).ToList();
var orderList = ext;
res.AddRange(orderList);
}
stopwatch.Stop();
Log.Information($"花费时间【{stopwatch.ElapsedMilliseconds}】ms");
return res;
}
/// <summary>
/// 合同审核
/// </summary>
/// <returns></returns>
public async Task ContractAudit(ContractAuditDto dto)
{
var order = await _repository.GetRepository<WX_SZZYORDER>().Query()
.FirstOrDefaultAsync(x => x.ORDERID == dto.OrderId);
var systemConfig = _configuration.GetSection("SystemConfig").Get<SystemConfig>();
var accessKey = systemConfig.GetAccessKey("UPWEBSITE");
if (order == null)
{
throw new ApiException("订单不存在或已删除!");
}
order.ContractStatus = dto.Status;
order.ContractRemark = dto.Remark;
var data = new
{
orderId = order.SZZYORDERID,
status = dto.Status == 1 ? 0 : -1,
contractStatus = dto.Status
};
var content = SecurityHelper.EncyptData(data.ToJson(), accessKey);
var sign = SecurityHelper.SignData(content, accessKey);
var updateContractStatusUrl = systemConfig.PostContractStatus(HttpUtility.UrlEncode(content), HttpUtility.UrlEncode(sign), "UPWEBSITE");
var res = await _httpClient.PostAsync<ApiResult>(updateContractStatusUrl);
if (res.Code == 0)
{
await _repository.GetRepository<WX_SZZYORDER>().UpdateAsync(order);
}
else
{
throw new ApiException(res.Message);
}
}
/// <summary>
/// 更新合同状态
/// </summary>
/// <param name="content"></param>
/// <param name="sign"></param>
/// <param name="clientId"></param>
/// <returns></returns>
public async Task<bool> UpdateContractStatus(string content, string sign, string clientId)
{
try
{
var accessKey = _systemConfig.GetAccessKey(clientId);
if (sign != SecurityHelper.SignData(content, accessKey))
{
throw new ApiException("签名不正确");
}
var json = SecurityHelper.DecyptData(content, accessKey);
var data = JsonSerializer.Deserialize<UpdateTraceContractStatusDto>(json);
if (data == null || string.IsNullOrEmpty(data.SzzyOrderId))
{
throw new ApiException("请输入orderid");
}
if (!long.TryParse(data.SzzyOrderId, out long szzyOrderId))
{
throw new ApiException("请输入正确的orderid");
}
Console.WriteLine("更新这个订单的合同审核状态为未审核:" + szzyOrderId);
var order = await _repository.GetRepository<WX_SZZYORDER>().Query()
.FirstOrDefaultAsync(x => x.SZZYORDERID == szzyOrderId);
if (order != null && (!order.ContractStatus.HasValue || order.ContractStatus == 0))
{
order.ContractStatus = null;
await _repository.GetRepository<WX_SZZYORDER>().UpdateAsync(order, x => new { x.ContractStatus });
}
return true;
}
catch (Exception ex)
{
Log.Error(ex, "更改合同状态失败!");
throw;
}
}
/// <summary>
/// 更新实名信息
/// </summary>
/// <param name="content"></param>
/// <param name="sign"></param>
/// <param name="clientId"></param>
/// <returns></returns>
public async Task<bool> UpdateRealName(string content, string sign, string clientId)
{
try
{
var deptments = await _cacheDomain.GetDeptments();
var accessKey = _systemConfig.GetAccessKey(clientId);
if (sign != SecurityHelper.SignData(content, accessKey))
{
throw new ApiException("签名不正确");
}
var json = SecurityHelper.DecyptData(content, accessKey);
Log.Information($"更新的实名信息,{json}");
var data = JsonSerializer.Deserialize<UpdateRealNameDto>(json);
if (data == null || string.IsNullOrEmpty(data.Resid))
{
throw new ApiException("请输入resid");
}
var customerid = await _repository.GetRepository<RES_CUSTOMER>().Query()
.Where(x => x.RESID == data.Resid).Select(x => x.CUSTOMERID).FirstOrDefaultAsync();
var resids = await _repository.GetRepository<RES_CUSTOMER>().Query()
.Where(x => x.CUSTOMERID == customerid).Select(x => x.RESID).ToListAsync();
var orders = await _repository.GetRepository<WX_SZZYORDER>().Query()
.Where(x => resids.Contains(x.RESID) && (x.ORDERSTATUS == "200" || x.ORDERSTATUS == "180" || x.ORDERSTATUS == "190")).ToListAsync();
var userProtocols = await _repository.GetRepository<SysUserProtocol>().Query()
.Where(x => resids.Contains(x.Resid) && x.Protocoltype == 6 && new int[] { 0, 1 }.Contains(x.Status)).ToListAsync();
var transaction = await _repository.BeginTransactionAsync();
try
{
if (orders.Count > 10) return false;
if (orders != null && orders.Any())
{
orders.ForEach(order =>
{
order.CNAME = data.Cname;
order.idcard = data.Idcard;
});
await _repository.GetRepository<WX_SZZYORDER>().BatchUpdateAsync(orders, x => new { x.CNAME, x.idcard });
if (userProtocols != null && userProtocols.Any())
{
userProtocols.ForEach(protocol =>
{
protocol.Username = data.Cname;
});
await _repository.GetRepository<SysUserProtocol>().BatchUpdateAsync(userProtocols, x => new { x.Username });
}
var deptid = orders.Select(x => x.deptid).Distinct().First();
var appid = deptments.Where(x => deptid == x.Id).Select(x => x.Appid).First();
var request = new
{
Orderids = orders.Select(x => x.ORDERID).ToList(),
RealName = data.Cname
};
var result = await _httpClient.PostAsync<ApiResult>(_systemConfig.UpdateOrderRealName(), request, appid);
if (result.Code == 0)
{
await transaction.CommitAsync();
}
else
{
throw new ApiException(result.Message);
}
}
}
catch (Exception ex)
{
Log.Error(ex, "更新的实名信息失败!");
await transaction.RollbackAsync();
await transaction.DisposeAsync();
throw;
}
return true;
}
catch (Exception ex)
{
Log.Error(ex, "更新的实名信息失败!");
throw;
}
}
public async Task<PageResult<OrderDto>> GetPage(OrderSearchDto dto)
{
var products = await _productDomain.GetProductList();
var subproducts = await _productDomain.GetSubProductListByProductId(0, 0, null);
var config = await _cacheDomain.GetValueParameter<AICallTaskConfig>("AI_CallTaskConfig");
var recall = config.ReCallMins.Count > 0 ? true : false;
//替换resid
if (!string.IsNullOrEmpty(dto.UMID) && string.IsNullOrEmpty(dto.ResId))
{
dto.ResId = await QueryResidByUMID(dto.UMID);
}
#region
if (!string.IsNullOrEmpty(dto.Mobile))
{
dto.ResId = ResUtil.CreateResId(dto.Mobile);
}
var query = _repository.GetRepository<WX_SZZYORDER>().Query().Where(m => m.Contractstatus == 1)
.If(dto.OrderId.HasValue, x => x.Where(m => m.ORDERID == dto.OrderId.Value))
.If(dto.OrderType.HasValue, x => x.Where(m => m.ORDERTYPE == dto.OrderType))
.If(dto.Stime.HasValue, x => x.Where(m => m.ARRIVALTIME >= dto.Stime.Value))
.If(dto.Etime.HasValue, x => x.Where(m => m.ARRIVALTIME < dto.Etime.Value.AddDays(1).AddMilliseconds(-1)))
.If(!string.IsNullOrEmpty(dto.SubProduct), x => x.Where(m => m.SUBPRODUCTNAME.Contains(dto.SubProduct)))
.If(!string.IsNullOrEmpty(dto.ResId), x => x.Where(m => m.RESID == dto.ResId))
.If(!string.IsNullOrWhiteSpace(dto.CompanyCode), x => x.Where(m => m.companycode == dto.CompanyCode))
.If(dto.SzzyOrderId.HasValue, x => x.Where(m => m.SZZYORDERID == dto.SzzyOrderId))
.If(dto.ProductId.HasValue && dto.ProductId > 0, x => x.Where(m => m.PRODUCTID == dto.ProductId))
.If(dto.SubProductId.HasValue, x => x.Where(m => m.SUBPRODUCTID == dto.SubProductId))
.If(!string.IsNullOrEmpty(dto.OutOrderNo), x => x.Where(m => m.outorderno == dto.OutOrderNo))
.If(!string.IsNullOrEmpty(dto.Cname), x => x.Where(m => m.CNAME == dto.Cname))
.If(dto.Needpay.HasValue, x => x.If(dto.NeedpayType == "1", x => x.Where(p => p.NEEDPAY > dto.Needpay))
.If(dto.NeedpayType == "2", x => x.Where(p => p.NEEDPAY < dto.Needpay))
.If(dto.NeedpayType != "1" && dto.NeedpayType != "2", x => x.Where(p => p.NEEDPAY == dto.Needpay)))
.If(!string.IsNullOrEmpty(dto.Softusername), x => x.Where(p => p.SOFTUSERNAME == dto.Softusername))
.If(!string.IsNullOrEmpty(dto.WXShopOrderNo), x => x.Where(p => p.wXShopOrderNo == dto.WXShopOrderNo))
.If(dto.Xstime.HasValue, x => x.Where(m => m.CTIME >= dto.Xstime))
.If(dto.Xetime.HasValue, x => x.Where(m => m.CTIME < dto.Xetime.Value.AddDays(1).AddMilliseconds(-1)))
.If(dto.Kstime.HasValue, x => x.Where(m => m.OTIME >= dto.Kstime))
.If(dto.Ketime.HasValue, x => x.Where(m => m.OTIME < dto.Ketime.Value.AddDays(1).AddMilliseconds(-1)))
.If(dto.Hastime.HasValue && dto.Hastime.Value == 1, x => x.Where(m => m.OTIME == null));
if (dto.ProductId1.HasValue && dto.ProductId.HasValue && !dto.ProductId2.HasValue && !dto.SubProductId.HasValue)
{
var arr1 = products.Where(p => p.Parentid == dto.ProductId1.Value).Select(p => p.Productid).ToList();
var arr = subproducts.Where(p => arr1.Contains(p.MidProductId.Value)).Select(p => p.SUBPRODUCTID).ToList();
query = query.Where(m => arr.Contains(m.SUBPRODUCTID));
//where = where.And(m => arr.Contains(m.SUBPRODUCTID));
}
if (dto.ProductId2.HasValue && dto.ProductId.HasValue && dto.ProductId1.HasValue && !dto.SubProductId.HasValue)
{
var arr = subproducts.Where(p => p.MidProductId == dto.ProductId2.Value).Select(p => p.SUBPRODUCTID).ToList();
query = query.Where(m => arr.Contains(m.SUBPRODUCTID));
//where = where.And(m => arr.Contains(m.SUBPRODUCTID));
}
if (!string.IsNullOrWhiteSpace(dto.OrderStatus))
{
if (dto.OrderStatus == "1")
{
string[] arr = { "180", "190", "195", "200", "220", "205", "90", "80" };
query = query.Where(m => arr.Contains(m.ORDERSTATUS));
//where = where.And(m => arr.Contains(m.ORDERSTATUS));
}
else
{
if (dto.OrderStatus == "201")
{
dto.OrderStatus = "200";
dto.RiskctrlStatus = 2;
}
var arr = dto.OrderStatus.Split(',');
if (arr.Length > 1)
{
query = query.Where(m => arr.Contains(m.ORDERSTATUS));
}
else
{
query = query.Where(m => m.ORDERSTATUS == dto.OrderStatus);
}
}
}
if (!string.IsNullOrEmpty(dto.Channel))
{
if (dto.Channel.Split(',').Length != 1)
{
var predicates = new List<Expression<Func<WX_SZZYORDER, bool>>>();
foreach (var channel in dto.Channel.Split(','))
{
var arr0 = channel.Split('|');
foreach (var item in arr0)
{
var a = item.Split(';');
var min = Convert.ToInt32(a[0]);
var max = Convert.ToInt32(a[1]);
predicates.Add(m => m.CHANNEL >= min && m.CHANNEL <= max);
}
}
query = query.WhereOR(predicates.ToArray());
}
else
{
foreach (var channel in dto.Channel.Split(','))
{
var arr0 = channel.Split('|');
if (arr0.Length > 1)
{
var predicates = new List<Expression<Func<WX_SZZYORDER, bool>>>();
foreach (var item in arr0)
{
var a = item.Split(';');
var min = Convert.ToInt32(a[0]);
var max = Convert.ToInt32(a[1]);
predicates.Add(m => m.CHANNEL >= min && m.CHANNEL <= max);
}
query = query.WhereOR(predicates.ToArray());
}
else
{
var arr = channel.Split(';');
var min = Convert.ToInt32(arr[0]);
var max = Convert.ToInt32(arr[1]);
query = query.Where(m => m.CHANNEL >= min && m.CHANNEL <= max);
}
}
}
}
if (dto.RiskctrlStatus.HasValue)
{
if (dto.RiskctrlStatus.Value == -2)
{
query = query.Where(m => m.Contractstatus == 0);
}
else
{
if (dto.RiskctrlStatus.Value == 2)
query = query.Where(m => m.RISKCTRLSTATUS == dto.RiskctrlStatus.Value && m.Contractstatus == 1);
else if (dto.RiskctrlStatus.Value == -1)
query = query.Where(m => m.RISKCTRLSTATUS == dto.RiskctrlStatus.Value && m.Contractstatus == 1);
else
query = query.Where(m => m.RISKCTRLSTATUS != 2 && m.RISKCTRLSTATUS != -1 && m.Contractstatus == 1);
}
}
var queryList = from q in query
join c in _repository.GetRepository<WxComplianceConfirm>().Query().Select(x => x.SzzyOrderId) on q.SZZYORDERID equals c into tmpQC
from qc in tmpQC.DefaultIfEmpty()
join d in _repository.GetRepository<WX_SZZYORDER_EXTEND>().Query() on q.ORDERID equals d.ORDERID into tmpd
from qd in tmpd.DefaultIfEmpty()
//join u in _repository.GetRepository<RES_CUSTOMER>().Query() on q.RESID equals u.RESID into ruc
//from uc in ruc.DefaultIfEmpty()
select new OrderDto()
{
ORDERID = q.ORDERID,
PRODUCTNAME = q.PRODUCTNAME,
SUBPRODUCTNAME = q.SUBPRODUCTNAME,
ORDERTYPE = q.ORDERTYPE,
UPGRADEORDERIDS = q.UPGRADEORDERIDS,
NEEDPAY = q.NEEDPAY,
SZZYORDERID = q.SZZYORDERID,
ORDERSTATUS = q.ORDERSTATUS,
CTIME = q.CTIME,
CONTRACTCODE = q.CONTRACTCODE,
contractctime = q.contractctime,
OTIME = q.OTIME,
ENDTIME = q.ENDTIME,
RESID = q.RESID,
//UMID= uc.UMID,
FINALPAY = q.FINALPAY,
BALANCEPAY = q.BALANCEPAY,
ORIGINPAY = q.ORIGINPAY,
ORDERSTATUSNAME = q.ORDERSTATUSNAME,
UPDATEORDERTIME = q.UPDATEORDERTIME,
ISOPEN = q.ISOPEN,
ARRIVALPAY = q.ARRIVALPAY,
ARRIVALTIME = q.ARRIVALTIME,
CNAME = q.CNAME,
OPENDAYS = q.OPENDAYS,
SOFTUSERNAME = q.SOFTUSERNAME,
CHANNEL = q.CHANNEL,
RISKCTRLSTATUS = q.RISKCTRLSTATUS,
companycode = q.companycode,
contractstatus = q.Contractstatus,
hashgrecord = q.hashgrecord,
outorderno = q.outorderno,
giftdays = q.giftdays,
giftdays2 = q.giftdays2,
external_userid = q.external_userid,
wework_remoteid = q.wework_remoteid,
CUSTOMERUSERNAME = q.CUSTOMERUSERNAME,
INNERUSERID = q.INNERUSERID,
SUBPRODUCTID = q.SUBPRODUCTID,
SOURCE = q.SOURCE,
rejectremark = q.rejectremark,
CpConfirmOrderId = qc,
fujian = q.fujian,
ret = q.RET,
estimateotime = q.estimateotime,
productcode = q.PRODUCTCODE,
ai_hgrecord_status = q.ai_hgrecord_status,
ai_hgrecord_statusname = q.ai_hgrecord_statusname,
hasaiaudio = q.hasaiaudio,
ai_hgrecord_stime = q.ai_hgrecord_stime,
ai_hgrecord_etime = q.ai_hgrecord_etime,
eid = q.eid,
contract_status = q.ContractStatus,
MarkStatus = !(q.external_userid == null
&& q.wework_remoteid == null
&& q.CUSTOMERUSERNAME == null
&& q.fujian == null
&& !_repository.GetRepository<Ww_Extuser_Resid>().Query().Any(x => x.resid == q.RESID)),
checkStatus = qd.CHECKSTATUS,
CheckRank = qd.CHECKRANK,
CheckRankTxt = qd.CHECKRANKTXT,
};
if (dto.checkStatus.HasValue)
{
if (dto.checkStatus != HGCheckStatus.)
{
queryList = from q in query
join c in _repository.GetRepository<WxComplianceConfirm>().Query().Select(x => x.SzzyOrderId) on q.SZZYORDERID equals c into tmpQC
from qc in tmpQC.DefaultIfEmpty()
join d in _repository.GetRepository<WX_SZZYORDER_EXTEND>().Query() on q.ORDERID equals d.ORDERID
select new OrderDto()
{
ORDERID = q.ORDERID,
PRODUCTNAME = q.PRODUCTNAME,
SUBPRODUCTNAME = q.SUBPRODUCTNAME,
ORDERTYPE = q.ORDERTYPE,
UPGRADEORDERIDS = q.UPGRADEORDERIDS,
NEEDPAY = q.NEEDPAY,
contractctime = q.contractctime,
SZZYORDERID = q.SZZYORDERID,
ORDERSTATUS = q.ORDERSTATUS,
CTIME = q.CTIME,
CONTRACTCODE = q.CONTRACTCODE,
OTIME = q.OTIME,
ENDTIME = q.ENDTIME,
RESID = q.RESID,
FINALPAY = q.FINALPAY,
BALANCEPAY = q.BALANCEPAY,
ORIGINPAY = q.ORIGINPAY,
ORDERSTATUSNAME = q.ORDERSTATUSNAME,
UPDATEORDERTIME = q.UPDATEORDERTIME,
ISOPEN = q.ISOPEN,
ARRIVALPAY = q.ARRIVALPAY,
ARRIVALTIME = q.ARRIVALTIME,
CNAME = q.CNAME,
OPENDAYS = q.OPENDAYS,
SOFTUSERNAME = q.SOFTUSERNAME,
CHANNEL = q.CHANNEL,
RISKCTRLSTATUS = q.RISKCTRLSTATUS,
companycode = q.companycode,
contractstatus = q.Contractstatus,
hashgrecord = q.hashgrecord,
outorderno = q.outorderno,
giftdays = q.giftdays,
giftdays2 = q.giftdays2,
external_userid = q.external_userid,
wework_remoteid = q.wework_remoteid,
CUSTOMERUSERNAME = q.CUSTOMERUSERNAME,
INNERUSERID = q.INNERUSERID,
SUBPRODUCTID = q.SUBPRODUCTID,
SOURCE = q.SOURCE,
rejectremark = q.rejectremark,
CpConfirmOrderId = qc,
fujian = q.fujian,
ret = q.RET,
estimateotime = q.estimateotime,
productcode = q.PRODUCTCODE,
ai_hgrecord_status = q.ai_hgrecord_status,
ai_hgrecord_statusname = q.ai_hgrecord_statusname,
hasaiaudio = q.hasaiaudio,
ai_hgrecord_stime = q.ai_hgrecord_stime,
ai_hgrecord_etime = q.ai_hgrecord_etime,
eid = q.eid,
contract_status = q.ContractStatus,
MarkStatus = !(q.external_userid == null
&& q.wework_remoteid == null
&& q.CUSTOMERUSERNAME == null
&& q.fujian == null
&& !_repository.GetRepository<Ww_Extuser_Resid>().Query().Any(x => x.resid == q.RESID)),
checkStatus = d.CHECKSTATUS,
CheckRank = d.CHECKRANK,
CheckRankTxt = d.CHECKRANKTXT
};
queryList = queryList.Where(n => n.checkStatus == dto.checkStatus);
if (dto.checkrank.HasValue)
{
queryList = queryList.Where(n => n.CheckRank == dto.checkrank);
}
}
else
{
queryList = queryList.Where(n => n.checkStatus != HGCheckStatus. && n.checkStatus != HGCheckStatus.);
}
}
if (dto.MarkStatus.HasValue)
{
if (dto.MarkStatus.Value)
{
queryList = queryList.Where(q => q.MarkStatus.Value);
}
else
{
queryList = queryList.Where(q => !q.MarkStatus.Value);
}
}
List<int> lev2Status = new List<int>
{
(int)EnumAiCallState.AI外呼失败未答完,
(int)EnumAiCallState.Ai外呼取消,
(int)EnumAiCallState.AI重拨失败,
};
List<int> waitStatus = new List<int>
{
(int)EnumAiCallState.AI外呼,
(int)EnumAiCallState.AI重拨,
(int)EnumAiCallState.AI外呼,
};
//如果有设置重拨 则 归类到 待ai外呼 否则归类到 需人工介入
if (recall && config.ReCallStatus.Count > 0)
{
waitStatus.AddRange(config.ReCallStatus);
}
else
{
lev2Status.Add((int)EnumAiCallState.AI外呼失败挂断);
lev2Status.Add((int)EnumAiCallState.AI外呼未接通);
}
if (!string.IsNullOrEmpty(dto.AiCallStatusList))
{
Expression<Func<OrderDto, bool>> expression = x => false;
foreach (var item in dto.AiCallStatusList.Split(',').Select(x => int.Parse(x)))
{
switch (item)
{
case -1:
case 9:
case 5:
expression = expression.Or(n => n.ai_hgrecord_status == item && n.CpConfirmOrderId == null);
break;
case 0:
expression = expression.Or(n => n.ai_hgrecord_status == item && n.CpConfirmOrderId == null);
break;
case 3:
expression = expression.Or(n => n.ai_hgrecord_status == item);
break;
case 2:
//var time = DateTime.Now.AddDays(-5);
expression = expression.Or(n => n.ai_hgrecord_status != null && lev2Status.Contains(n.ai_hgrecord_status.Value)
&& !new string[] { "90", "60" }.Contains(n.ORDERSTATUS)
);
break;
case 1:
expression = expression.Or(n => n.ai_hgrecord_status != null && waitStatus.Contains(n.ai_hgrecord_status.Value));
break;
case 4:
expression = expression.Or(n => n.CpConfirmOrderId != null);
break;
}
}
queryList = queryList.Where(expression);
}
if (dto.Aistime.HasValue || dto.Aietime.HasValue)
{
var aiQuery = _repository.GetRepository<CsvrAiCallTask>().Query();
if (dto.Aistime.HasValue)
{
aiQuery = aiQuery.Where(n => n.Ctime >= dto.Aistime);
}
if (dto.Aietime.HasValue)
{
dto.Aietime = dto.Aietime.Value.AddDays(1);
aiQuery = aiQuery.Where(n => n.Ctime <= dto.Aietime);
}
var orderList = from n in aiQuery
join b in _repository.GetRepository<CsvrAiCallTaskOrders>().Query()
on n.Id equals b.Taskid
select b.Orderid.Value;
var orderids = orderList.ToList();
queryList = queryList.Where(n => orderids.Contains(n.ORDERID));
}
#endregion
queryList = queryList.OrderByDescending(m => m.ORDERID);
var total = await queryList.CountAsync();
var data = await queryList
.Skip((dto.PageIndex - 1) * dto.PageSize)
.Take(dto.PageSize)
.ToListAsync();
var orderIds = data.Select(x => x.ORDERID).ToList();
if (orderIds != null && orderIds.Any())
{
//查询客户录屏数据
var userNames = data.Select(x => x.SOFTUSERNAME).Distinct().ToList();
var screenRecords = await _repository.GetRepository<ScreenRecord>().Query().Where(x => userNames.Contains(x.MasterId) || userNames.Contains(x.SlaveId)).ToListAsync();
var orderAudits = await _repository.GetRepository<WX_SZZYORDER_AUDIT_LOG>().Query().Where(x => orderIds.Contains(x.Orderid)).ToListAsync();
foreach (var item in data)
{
var orderAuditList = orderAudits.Where(x => x.Orderid == item.ORDERID).ToList();
if (orderAuditList != null && orderAuditList.Any())
{
var orderAudit = orderAuditList.OrderByDescending(x => x.CreateTime).FirstOrDefault();
item.auditor = orderAudit?.Auditor;
item.auditTime = orderAudit?.CreateTime;
}
var screenRecord = screenRecords.Where(x => x.MasterId == item.SOFTUSERNAME || x.SlaveId == item.SOFTUSERNAME);
item.ScreenRecordCount = screenRecord.Count();
}
}
var companyList = await _cacheDomain.GetCompanyVirtualList();
var eids = string.Join(",", data.Where(x => x.eid != null).Select(x => x.eid).ToList());
var innerusers = await _inneruserDomain.GetInnerusers(eids);
var resids = data.Select(x => x.RESID).ToList();
var myUMID = _repository.GetRepository<RES_CUSTOMER>().Query().Where(m => resids.Contains(m.RESID)).ToList();
var usernames = data.Select(x => x.SOFTUSERNAME).ToList();
var canopenorder = await _repository.GetRepository<WxCanopenorder>().Query().Where(x => usernames.Contains(x.Username))
.ToListAsync();
foreach (var item in data)
{
#region UMID
item.UMID = myUMID.FirstOrDefault(m => m.RESID == item.RESID)?.UMID;
#endregion UMID
item.checkStatus = item.checkStatus == null ? HGCheckStatus. : item.checkStatus;
item.Canopenorder = canopenorder.FirstOrDefault(x => x.Username == item.SOFTUSERNAME)?.Status == 1;
if (innerusers != null && innerusers.Any())
{
var inneruser = innerusers.FirstOrDefault(x => x.EId == item.eid);
if (inneruser != null)
{
item.innerUserName = inneruser.Name;
}
}
if (string.IsNullOrWhiteSpace(item.ai_hgrecord_statusname) && item.ai_hgrecord_status == 0)
{
item.ai_hgrecord_statusname = EnumAiCallState.AI外呼.ToString();
}
item.CHANNELNAME = ConvertChannelName(companyList, item.CHANNEL);
if (item.ai_hgrecord_status.HasValue && item.ai_hgrecord_status.Value == (int)EnumAiCallState.AI外呼成功)
{
item.ai_hgrecord_statusname = EnumAiCallState.AI外呼成功.ToString();
}
else if (item.CpConfirmOrderId != null)
{
item.ai_hgrecord_statusname = EnumAiCallState.访.ToString();
}
else if (lev2Status.Contains(item.ai_hgrecord_status.Value))
{
item.ai_hgrecord_statusname = "AI外呼需人工介入";
}
else if (waitStatus.Contains(item.ai_hgrecord_status.Value))
{
//等待ai外呼 再拆分
if (item.ai_hgrecord_status.Value == (int)EnumAiCallState.AI外呼)
{
item.ai_hgrecord_statusname = "等待AI外呼(首次拨打)";
}
else if (item.ai_hgrecord_status.Value == (int)EnumAiCallState.AI外呼)
{
item.ai_hgrecord_statusname = "等待AI外呼(已提交任务)";
}
else
{
item.ai_hgrecord_statusname = "等待AI外呼(重复拨打)";
}
item.hasBtn = 1;
}
var sp = subproducts.FirstOrDefault(p => p.SUBPRODUCTID == item.SUBPRODUCTID);
if (sp != null)
{
var pp = products.FirstOrDefault(p => p.Productid == sp.MidProductId);
if (pp != null)
{
item.MidProductName = pp.Productname;
}
}
if (!string.IsNullOrWhiteSpace(item.ai_hgrecord_stime) || !string.IsNullOrWhiteSpace(item.ai_hgrecord_etime))
{
item.ai_hgrecord_time = $"{item.ai_hgrecord_stime}-{item.ai_hgrecord_etime}";
}
else
{
item.ai_hgrecord_time = "不限制";
}
}
var curOrderSum = new OrderDto()
{
//RESID = "合计",
ORDERID = 1,
NEEDPAY = data.Sum(p => p.NEEDPAY),
FINALPAY = data.Sum(p => p.FINALPAY),
ARRIVALPAY = data.Sum(p => p.ARRIVALPAY),
ORDERTYPE = 0,
ORDERSTATUS = string.Empty
};
data.Add(curOrderSum);
return new PageResult<OrderDto>(dto.PageIndex, dto.PageSize, total, data);
}
public async Task<List<CheckOrderListModel>> GetCheckLog(QueryCheckDto dto)
{
List<CheckOrderListModel> res = new List<CheckOrderListModel>();
var log = await _repository.GetRepository<HG_CheckQualityLog>().Query().Where(n => n.ResId == dto.resid)
.Include(x => x.HG_CheckQualityLogRelation)
.Include(x => x.HG_CheckQualityLogDetail)
.ThenInclude(x => x.HG_CheckQualityLogSource)
.OrderByDescending(n => n.Id)
.ToListAsync();
foreach (var item in log)
{
CheckOrderListModel model = new CheckOrderListModel
{
Id = item.Id,
OrderIds = String.Join(",", item.HG_CheckQualityLogRelation.Select(n => n.orderid)),
CheckTime = item.CHECKTIME,
Ename = item.ENAME,
Row = item.HG_CheckQualityLogDetail.Count,
Result = item.CHECKSTATUS.GetDescription()
};
List<CheckDetail> checkDetailList = new List<CheckDetail>();
foreach (var detail in item.HG_CheckQualityLogDetail)
{
CheckDetail checkdetail = new CheckDetail
{
Id = detail.Id,
CheckType = detail.checktype,
CheckTypeName = ((HGCheckType)detail.checktype).GetDescription(),
condition = detail.condition.Split(',').Select(n => Convert.ToInt32(n)).ToList(),
content = detail.content,
suggest = detail.suggest,
//Source = detail.HG_CheckQualityLogSource.ToList(),
conditionText = detail.conditiontext
};
if (detail.checktype == (int)HGCheckType.)
{
checkdetail.ShowSource = String.Join(",", detail.HG_CheckQualityLogSource.Select(n => $"{n.appuserid}({n.externaluserid})[{n.appname}]"));
}
else
{
checkdetail.ShowSource = String.Join(",", detail.HG_CheckQualityLogSource.Select(n => $"{n.recordid}"));
}
checkDetailList.Add(checkdetail);
model.CheckDetails = checkDetailList;
}
res.Add(model);
}
return res;
}
public async Task<List<CheckNewOrderListModel>> GetNewCheckLog(QueryCheckDto dto)
{
List<CheckNewOrderListModel> res = new List<CheckNewOrderListModel>();
var resId = _repository.GetRepository<RES_CUSTOMER>().Query().FirstOrDefault(x => x.UMID == dto.resid)?.RESID;
var log = await _repository.GetRepository<HG_CheckQualityLog>().Query().Where(n => n.ResId == resId)
.Include(x => x.HG_CheckQualityLogRelation)
.Include(x => x.HG_CheckQualityLogDetail)
.ThenInclude(x => x.HG_CheckQualityLogSource)
.OrderByDescending(n => n.UTIME)
.ToListAsync();
foreach (var item in log)
{
List<CheckDetail> checkDetailList = new List<CheckDetail>();
if (item.HG_CheckQualityLogDetail.Count == 0)
{
CheckNewOrderListModel checkdetail = new CheckNewOrderListModel
{
Id = item.Id,
OrderIds = String.Join(",", item.HG_CheckQualityLogRelation.Select(n => n.orderid)),
CheckTime = item.CHECKTIME,
Ename = item.ENAME,
Row = item.HG_CheckQualityLogDetail.Count,
Result = item.CHECKSTATUS.GetDescription()
};
res.Add(checkdetail);
}
foreach (var detail in item.HG_CheckQualityLogDetail)
{
CheckNewOrderListModel checkdetail = new CheckNewOrderListModel
{
DetailId = detail.Id,
CheckType = detail.checktype,
CheckTypeName = ((HGCheckType)detail.checktype).GetDescription(),
condition = detail.condition.Split(',').Select(n => Convert.ToInt32(n)).ToList(),
content = detail.content,
suggest = detail.suggest,
conditionText = detail.conditiontext,
Id = item.Id,
OrderIds = String.Join(",", item.HG_CheckQualityLogRelation.Select(n => n.orderid)),
CheckTime = item.CHECKTIME,
Ename = item.ENAME,
Row = item.HG_CheckQualityLogDetail.Count,
Result = item.CHECKSTATUS.GetDescription()
};
if (detail.checktype == (int)HGCheckType.)
{
List<string> showSource = new List<string>();
foreach (var soul in detail.HG_CheckQualityLogSource)
{
if (soul.eid > 0)
{
showSource.Add($"{soul.appuserid}({soul.eid}{soul.ename})");
}
else
{
showSource.Add($"{soul.appuserid}");
}
}
checkdetail.ShowSource = String.Join(",", showSource);
}
else
{
checkdetail.ShowSource = String.Join(",", detail.HG_CheckQualityLogSource.Select(n => $"{n.recordid}"));
}
res.Add(checkdetail);
}
}
return res;
}
/// <summary>
/// 获取近7天的订单合规情况和最新的操作
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
public async Task<CheckEditModel> GetCheckEditLog(CheckEditDto dto)
{
CheckEditModel res = new CheckEditModel();
var resId = _repository.GetRepository<RES_CUSTOMER>().Query().FirstOrDefault(x => x.UMID == dto.ResId)?.RESID;
var query = _repository.GetRepository<WX_SZZYORDER>().Query().Where(n => n.RESID == resId);
var orderList = query.ToList();
var checkOrders = from n in query
join b in _repository.GetRepository<WX_SZZYORDER_EXTEND>().Query()
on n.ORDERID equals b.ORDERID into tmp
from qd in tmp.DefaultIfEmpty()
select new CheckOrderModel
{
CTIME = n.CTIME,
value = n.ORDERID,
name = qd != null ? $"{n.ORDERID}({n.ORDERSTATUSNAME})({qd.CHECKSTATUS.GetDescription()})" : $"{n.ORDERID}({n.ORDERSTATUSNAME})({HGCheckStatus.未质检.GetDescription()})",
Exuserid = n.external_userid
};
List<string> exteruserName = new List<string>();
var exteruserList = await _repository.GetRepository<Ww_Extuser_Resid>().Query().Where(n => n.resid == resId).ToListAsync();
exteruserName.AddRange(exteruserList.Select(n => n.userid).ToList());
exteruserName.Add(checkOrders.FirstOrDefault(n => n.value == dto.OrderId)?.Exuserid);
exteruserName = exteruserName.Where(n => !string.IsNullOrEmpty(n)).Distinct().ToList();
res.CheckOrders = checkOrders.OrderByDescending(n => n.CTIME).Take(500).ToList();
/* if (!res.CheckOrders.Select(n => n.value).Contains(dto.OrderId))
{
throw new Exception($"当前订单未开通,无法质检");
}
if (res.CheckOrders.Count == 0)
{
throw new Exception($"当前客户不存在已开通的订单");
}*/
var setting = await _repository.GetRepository<BasParameter>().Query().FirstOrDefaultAsync(n => n.PARAKEY == "HgCheckSetting");
if (setting != null)
{
res.HgCheckSetting = setting.PARAVALUE;
}
var qiweiHost = await _repository.GetRepository<BasParameter>().Query().FirstOrDefaultAsync(n => n.PARAKEY == "QiWeiHost");
res.OrderInfo = new OrderInfo
{
OrderId = new List<int> { dto.OrderId.Value },
QiWeiUrl = $"{qiweiHost.PARAVALUE.Split('$').FirstOrDefault().Trim('/')}/Admin/OutHHuser/User_extuserList?exuserid={string.Join(";", exteruserName)}&isHg=true&resid={resId}&isChoose=true",
Exuserid = exteruserName
};
return res;
}
/// <summary>
/// 保存
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
public async Task<bool> CheckSave(CheckSaveDto dto)
{
try
{
var setting = await _repository.GetRepository<BasParameter>().Query().FirstOrDefaultAsync(n => n.PARAKEY == "HgCheckSetting");
var hgSetting = JsonHelper.FromJson<List<HgCheckSetting>>(setting.PARAVALUE);
var orderList = await _repository.GetRepository<WX_SZZYORDER>().Query().Where(n => dto.orderids.Contains(n.ORDERID)).ToListAsync();
var resid = orderList.FirstOrDefault(n => n.ORDERID == dto.orderids.FirstOrDefault())?.RESID;
HG_CheckQualityLog log = new HG_CheckQualityLog();
List<HG_CheckQualityLogRelation> delRelation = new List<HG_CheckQualityLogRelation>();
List<HG_CheckQualityLogDetail> delLogdetail = new List<HG_CheckQualityLogDetail>();
List<HG_CheckQualityLogSource> delLogsource = new List<HG_CheckQualityLogSource>();
if (dto.Id.HasValue && dto.Id > 0)
{
log = await _repository.GetRepository<HG_CheckQualityLog>().Query().Where(n => n.Id == dto.Id)
.Include(x => x.HG_CheckQualityLogRelation)
.Include(x => x.HG_CheckQualityLogDetail)
.ThenInclude(x => x.HG_CheckQualityLogSource)
.OrderByDescending(n => n.Id)
.FirstOrDefaultAsync();
log.CHECKSTATUS = dto.checkstatus;
log.CHECKTIME = DateTime.Now;
log.UTIME = DateTime.Now;
log.EID = dto.eid;
log.ResId = resid;
log.ENAME = dto.ename;
await _repository.GetRepository<HG_CheckQualityLog>().UpdateAsync(log);
foreach (var item in log.HG_CheckQualityLogRelation)
{
delRelation.Add(item);
}
foreach (var detail in log.HG_CheckQualityLogDetail)
{
delLogdetail.Add(detail);
foreach (var source in detail.HG_CheckQualityLogSource)
{
delLogsource.Add(source);
}
}
}
//插入日志
using var transaction = await _repository.BeginTransactionAsync();
if (!dto.Id.HasValue || dto.Id == 0)
{
log = new HG_CheckQualityLog
{
CHECKSTATUS = dto.checkstatus,
CHECKTIME = DateTime.Now,
CTIME = DateTime.Now,
EID = dto.eid,
ResId = resid,
ENAME = dto.ename,
UTIME = DateTime.Now
};
await _repository.GetRepository<HG_CheckQualityLog>().InsertAsync(log);
}
//插入扩展表
var orderextendList = await _repository.GetRepository<WX_SZZYORDER_EXTEND>().Query().Where(n => dto.orderids.Contains(n.ORDERID)).ToListAsync();
List<WX_SZZYORDER_EXTEND> insertExtendList = new List<WX_SZZYORDER_EXTEND>();
List<WX_SZZYORDER_EXTEND> updateExtendList = new List<WX_SZZYORDER_EXTEND>();
List<HG_CheckQualityLogRelation> inRelationList = new List<HG_CheckQualityLogRelation>();
List<HG_CheckQualityLogSource> insource = new List<HG_CheckQualityLogSource>();
int? checkrank = null;
var checkranktxt = string.Empty;
foreach (var detail in dto.children)
{
if (detail.condition.Count == 0)
{
throw new Exception("合规情况必填");
}
List<string> conditionText = new List<string>();
foreach (var set in hgSetting)
{
if (set.children == null || set.children.Count == 0)
{
if (detail.condition.Contains(set.value))
{
conditionText.Add(set.name);
}
continue;
}
var hafirstStr = false;
var conditStr = "";
foreach (var con in detail.condition)
{
var cren = set.children.FirstOrDefault(n => n.value == con);
if (cren != null)
{
if (hafirstStr)
{
conditStr += $",{cren.name}";
}
else
{
if (!checkrank.HasValue)
{
checkrank = set.value;
checkranktxt = set.name;
}
conditStr += $"{set.name}({cren.name}";
hafirstStr = true;
}
}
}
if (!string.IsNullOrWhiteSpace(conditStr))
{
conditStr += ")";
conditionText.Add(conditStr);
}
}
HG_CheckQualityLogDetail newDetail = new HG_CheckQualityLogDetail
{
logid = log.Id,
checktype = detail.checktype,
condition = String.Join(",", detail.condition),
conditiontext = String.Join(",", conditionText),
suggest = detail.suggest,
content = detail.content,
ctime = DateTime.Now
};
await _repository.GetRepository<HG_CheckQualityLogDetail>().InsertAsync(newDetail);
if (detail.checktype == (int)HGCheckType.)
{
if (detail.qiMsg.Count == 0)
{
throw new Exception("企微微信聊天记录不能为空");
}
foreach (var item in detail.qiMsg)
{
HG_CheckQualityLogSource source = new HG_CheckQualityLogSource
{
logdetailid = newDetail.Id,
logid = log.Id,
checktype = detail.checktype,
appid = item.corpid,
appname = item.corpname,
appuserid = item.userid,
externaluserid = item.extuserid,
ctime = DateTime.Now,
eid = item.eid,
ename = item.ename
};
insource.Add(source);
}
}
else
{
if (detail.audio.Count == 0)
{
throw new Exception("违规录音不能为空");
}
foreach (var item in detail.audio)
{
HG_CheckQualityLogSource source = new HG_CheckQualityLogSource
{
logdetailid = newDetail.Id,
logid = log.Id,
checktype = detail.checktype,
recordid = item.recordid,
ctime = DateTime.Now
};
insource.Add(source);
}
}
}
foreach (var orderid in dto.orderids)
{
var existExtend = orderextendList.FirstOrDefault(n => n.ORDERID == orderid);
if (existExtend == null)
{
WX_SZZYORDER_EXTEND order = new WX_SZZYORDER_EXTEND
{
ORDERID = orderid,
RESID = resid,
CHECKSTATUS = dto.checkstatus,
CHECKTIME = log.CHECKTIME,
EID = dto.eid,
ENAME = dto.ename,
CTIME = DateTime.Now,
CHECKRANK = checkrank,
CHECKRANKTXT = checkranktxt
};
insertExtendList.Add(order);
}
else
{
existExtend.CHECKSTATUS = log.CHECKSTATUS;
existExtend.CHECKTIME = log.CHECKTIME;
existExtend.EID = log.EID;
existExtend.ENAME = log.ENAME;
existExtend.UTIME = log.UTIME;
existExtend.CHECKRANK = checkrank;
existExtend.CHECKRANKTXT = checkranktxt;
updateExtendList.Add(existExtend);
}
inRelationList.Add(new HG_CheckQualityLogRelation
{
logid = log.Id,
orderid = orderid,
resid = resid,
CTIME = DateTime.Now
});
}
if (insertExtendList.Count() > 0)
{
await _repository.GetRepository<WX_SZZYORDER_EXTEND>().BatchInsertAsync(insertExtendList);
}
if (updateExtendList.Count > 0)
{
await _repository.GetRepository<WX_SZZYORDER_EXTEND>().BatchUpdateAsync(updateExtendList);
}
if (inRelationList.Count > 0)
{
await _repository.GetRepository<HG_CheckQualityLogRelation>().BatchInsertAsync(inRelationList);
}
if (insource.Count > 0)
{
await _repository.GetRepository<HG_CheckQualityLogSource>().BatchInsertAsync(insource);
}
if (delRelation.Count > 0)
{
await _repository.GetRepository<HG_CheckQualityLogRelation>().BatchDeleteAsync(delRelation);
}
if (delLogdetail.Count > 0)
{
await _repository.GetRepository<HG_CheckQualityLogDetail>().BatchDeleteAsync(delLogdetail);
}
if (delLogsource.Count > 0)
{
await _repository.GetRepository<HG_CheckQualityLogSource>().BatchDeleteAsync(delLogsource);
}
await transaction.CommitAsync();
}
catch (Exception ex)
{
Log.Error($"质检保存失败{ex.Message}");
throw ex;
}
return true;
}
public async Task<InitEditModel> initEditModel(QueryCheckDto dto)
{
InitEditModel res = new InitEditModel();
CheckSaveDto editModel = new CheckSaveDto();
if (!dto.id.HasValue)
{
//取最早那一条记录
var logList = await _repository.GetRepository<HG_CheckQualityLogRelation>().Query().Where(n => n.orderid == dto.orderid).OrderByDescending(n => n.logid).FirstOrDefaultAsync();
dto.id = logList.logid;
}
List<int> orderfilter = new List<int>();
if (dto.id.HasValue)
{
var log = await _repository.GetRepository<HG_CheckQualityLog>().Query().Where(n => n.Id == dto.id)
.Include(x => x.HG_CheckQualityLogRelation)
.Include(x => x.HG_CheckQualityLogDetail)
.ThenInclude(x => x.HG_CheckQualityLogSource)
.OrderByDescending(n => n.Id)
.FirstOrDefaultAsync();
if (log != null)
{
editModel.Id = log.Id;
editModel.ename = log.ENAME;
editModel.checkstatus = log.CHECKSTATUS;
editModel.checktime = log.CHECKTIME.Value.ToString("yyyy-MM-dd HH:mm:ss");
editModel.orderids = log.HG_CheckQualityLogRelation.Select(n => Convert.ToInt32(n.orderid)).ToList();
editModel.eid = log.EID;
List<CheckLogDetail> detailList = new List<CheckLogDetail>();
foreach (var item in log.HG_CheckQualityLogDetail)
{
CheckLogDetail checkLogDetail = new CheckLogDetail
{
id = item.Id,
checktype = item.checktype,
condition = item.condition.Split(",").Select(n => Convert.ToInt32(n)).ToList(),
content = item.content,
suggest = item.suggest
};
if (item.checktype == (int)HGCheckType.)
{
List<AuditDetail> auditDetailList = new List<AuditDetail>();
foreach (var audio in item.HG_CheckQualityLogSource)
{
AuditDetail auditDetail = new AuditDetail
{
recordid = audio.recordid,
};
auditDetailList.Add(auditDetail);
}
checkLogDetail.audio = auditDetailList;
}
else
{
List<QiWeMsg> qiwei = new List<QiWeMsg>();
foreach (var audio in item.HG_CheckQualityLogSource)
{
QiWeMsg msg = new QiWeMsg
{
corpid = audio.appid,
corpname = audio.appname,
userid = audio.appuserid,
extuserid = audio.externaluserid,
eid = audio.eid,
ename = audio.ename,
};
qiwei.Add(msg);
}
checkLogDetail.qiMsg = qiwei;
}
detailList.Add(checkLogDetail);
}
editModel.children = detailList;
dto.resid = log.ResId;
orderfilter = log.HG_CheckQualityLogRelation.Select(n => n.orderid).Distinct().ToList();
}
}
//列表
QueryCheckDto queryCheckDto = new QueryCheckDto()
{
resid = dto.resid
};
CheckEditModel setting = new CheckEditModel();
var query = _repository.GetRepository<WX_SZZYORDER>().Query().Where(n => n.RESID == dto.resid);
var checkOrders = from n in query
join b in _repository.GetRepository<WX_SZZYORDER_EXTEND>().Query()
on n.ORDERID equals b.ORDERID into tmp
from qd in tmp.DefaultIfEmpty()
select new CheckOrderModel
{
CTIME = n.CTIME,
value = n.ORDERID,
name = qd != null ? $"{n.ORDERID}({n.ORDERSTATUSNAME})({qd.CHECKSTATUS.GetDescription()})" : $"{n.ORDERID}({n.ORDERSTATUSNAME})({HGCheckStatus.未质检.GetDescription()})",
Exuserid = n.external_userid
};
List<string> exteruserName = new List<string>();
var exteruserList = await _repository.GetRepository<Ww_Extuser_Resid>().Query().Where(n => n.resid == dto.resid).ToListAsync();
exteruserName.AddRange(exteruserList.Select(n => n.userid).ToList());
exteruserName.Add(checkOrders.FirstOrDefault(n => n.value == dto.orderid)?.Exuserid);
exteruserName = exteruserName.Where(n => !string.IsNullOrEmpty(n)).Distinct().ToList();
setting.CheckOrders = checkOrders.OrderByDescending(n => n.CTIME).ToList();
var checkSetting = await _repository.GetRepository<BasParameter>().Query().FirstOrDefaultAsync(n => n.PARAKEY == "HgCheckSetting");
if (setting != null)
{
setting.HgCheckSetting = checkSetting.PARAVALUE;
}
var qiweiHost = await _repository.GetRepository<BasParameter>().Query().FirstOrDefaultAsync(n => n.PARAKEY == "QiWeiHost");
setting.OrderInfo = new OrderInfo
{
//OrderId = new List<int> { dto.orderid },
QiWeiUrl = $"{qiweiHost.PARAVALUE.Split('$').FirstOrDefault().Trim('/')}/Admin/OutHHuser/User_extuserList?exuserid={string.Join(";", exteruserName)}&isHg=true&resid={dto.resid}&isChoose=true",
Exuserid = exteruserName
};
res.Setting = setting;
res.CheckNewOrderListModel = await GetNewCheckLog(queryCheckDto);
res.CheckSaveDto = editModel;
return res;
}
public async Task<PageResult<CheckOrderList>> GetCheckOrderList(CheckOrderQueryDto dto)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var isorderFilter = false;
//替换resid
if (!string.IsNullOrEmpty(dto.UMID) && string.IsNullOrEmpty(dto.resId))
{
dto.resId = await QueryResidByUMID(dto.UMID);
}
var resCustomer = _repository.GetRepository<RES_CUSTOMER>().Query();
var _orderquery = _repository.GetRepository<WX_SZZYORDER>().Query()
.If(dto.orderId.HasValue, x => x.Where(m => m.ORDERID == dto.orderId.Value))
.If(!string.IsNullOrEmpty(dto.cname), x => x.Where(m => m.CNAME == dto.cname))
.If(dto.cstart.HasValue, x => x.Where(m => m.CTIME >= dto.cstart))
.If(dto.cend.HasValue, x => x.Where(m => m.CTIME < dto.cend.Value.AddDays(1).AddMilliseconds(-1)))
.If(dto.kstime.HasValue, x => x.Where(m => m.OTIME >= dto.kstime))
.If(dto.ketime.HasValue, x => x.Where(m => m.OTIME < dto.ketime.Value.AddDays(1).AddMilliseconds(-1)));
if (dto.orderId.HasValue || !string.IsNullOrEmpty(dto.cname) || dto.cstart.HasValue || dto.cend.HasValue || dto.kstime.HasValue || dto.ketime.HasValue)
{
isorderFilter = true;
}
if (!string.IsNullOrWhiteSpace(dto.auditname))
{
isorderFilter = true;
var orderfilter = _repository.GetRepository<WX_SZZYORDER_AUDIT_LOG>().Query().Where(n => n.Auditor == dto.auditname).Select(n => n.Orderid);
_orderquery = _orderquery.Where(n => orderfilter.Contains(n.ORDERID));
}
if (!string.IsNullOrEmpty(dto.channel))
{
isorderFilter = true;
if (dto.channel.Split(',').Length != 1)
{
var predicates = new List<Expression<Func<WX_SZZYORDER, bool>>>();
foreach (var channel in dto.channel.Split(','))
{
var arr0 = channel.Split('|');
foreach (var item in arr0)
{
var a = item.Split(';');
var min = Convert.ToInt32(a[0]);
var max = Convert.ToInt32(a[1]);
predicates.Add(m => m.CHANNEL >= min && m.CHANNEL <= max);
}
}
_orderquery = _orderquery.WhereOR(predicates.ToArray());
}
else
{
foreach (var channel in dto.channel.Split(','))
{
var arr0 = channel.Split('|');
if (arr0.Length > 1)
{
var predicates = new List<Expression<Func<WX_SZZYORDER, bool>>>();
foreach (var item in arr0)
{
var a = item.Split(';');
var min = Convert.ToInt32(a[0]);
var max = Convert.ToInt32(a[1]);
predicates.Add(m => m.CHANNEL >= min && m.CHANNEL <= max);
}
_orderquery = _orderquery.WhereOR(predicates.ToArray());
}
else
{
var arr = channel.Split(';');
var min = Convert.ToInt32(arr[0]);
var max = Convert.ToInt32(arr[1]);
_orderquery = _orderquery.Where(m => m.CHANNEL >= min && m.CHANNEL <= max);
}
}
}
}
var query = _repository.GetRepository<HG_CheckQualityLog>().Query()
.If(!string.IsNullOrEmpty(dto.resId), x => x.Where(m => m.ResId == dto.resId))
.If(dto.checktype.HasValue, n => n.Where(n => n.HG_CheckQualityLogDetail.Any(s => s.checktype == dto.checktype)))
.If(dto.ckstime.HasValue, x => x.Where(m => m.CHECKTIME >= dto.ckstime))
.If(dto.cketime.HasValue, x => x.Where(m => m.CHECKTIME < dto.cketime.Value.AddDays(1).AddMilliseconds(-1)))
.If(dto.checkStatus.HasValue, x => x.Where(m => (int)m.CHECKSTATUS == dto.checkStatus))
.If(isorderFilter, x => x.Where(n => n.HG_CheckQualityLogRelation.Any(s => _orderquery.Select(n => n.ORDERID).Contains(s.orderid))))
.If(!string.IsNullOrWhiteSpace(dto.checkname), x => x.Where(m => m.ENAME == dto.checkname));
if (!string.IsNullOrEmpty(dto.condition))
{
var logdetail = _repository.GetRepository<HG_CheckQualityLogDetail>().Query();
var predicates = new List<Expression<Func<HG_CheckQualityLogDetail, bool>>>();
foreach (var cond in dto.condition.Split(','))
{
predicates.Add(m => m.condition.Contains(cond));
}
logdetail = logdetail.WhereOR(predicates.ToArray());
query = query.If(!string.IsNullOrEmpty(dto.condition), n => n.Where(s => s.HG_CheckQualityLogDetail.Any(sq => logdetail.Contains(sq))));
}
var total = await query.CountAsync();
var logQuery = await query.OrderByDescending(n => n.UTIME)
.Skip((dto.PageIndex - 1) * dto.PageSize)
.Take(dto.PageSize)
.Include(x => x.HG_CheckQualityLogRelation)
.Include(x => x.HG_CheckQualityLogDetail)
.ThenInclude(x => x.HG_CheckQualityLogSource)
.ToListAsync();
stopwatch.Stop();
Log.Information($"查询质检明细耗时{stopwatch.ElapsedMilliseconds}ms");
stopwatch.Restart();
var orderids = logQuery.SelectMany(n => n.HG_CheckQualityLogRelation.Select(s => s.orderid)).ToList();
var orderAudits = _repository.GetRepository<WX_SZZYORDER_AUDIT_LOG>().Query();
var orderQuery = _repository.GetRepository<WX_SZZYORDER>().Query();
var orderAuditQyery = from n in orderQuery
join b in orderAudits on n.ORDERID equals b.Orderid into tmpd
from qd in tmpd.DefaultIfEmpty()
where orderids.Contains(n.ORDERID)
select new { order = n, auditlog = qd };
var orderList = orderAuditQyery.ToList();
var orderresCustomer = resCustomer.Where(m => logQuery.Select(l => l.ResId).Contains(m.RESID)).ToList();
var ocDic = orderresCustomer.GroupBy(m => m.RESID).ToDictionary(m => m.Key, n => n.First().UMID);//匹配UMID
var eids = string.Join(",", orderList.Where(x => x.order.eid != null).Select(x => x.order.eid).ToList());
var innerusers = await _inneruserDomain.GetInnerusers(eids);
List<CheckOrderList> res = new List<CheckOrderList>();
foreach (var item in logQuery)
{
var orderaudit = orderList.Where(s => item.HG_CheckQualityLogRelation.Select(n => n.orderid).Contains(s.order.ORDERID)).ToList();
var orderitem = orderaudit.Select(n => n.order).Distinct().ToList();
var oids = orderitem.Select(n => n.ORDERID).ToList();
var orderAuditList = orderaudit.Where(n => n.auditlog != null).Select(n => n.auditlog).ToList();
var UMID = ocDic.ContainsKey(item.ResId) ? ocDic[item.ResId] : "";
CheckOrderList newModel = new CheckOrderList
{
Id = item.Id,
ResId = item.ResId,
UMID = UMID,
CNAME = orderitem.FirstOrDefault()?.CNAME,
CHANNELNAME = String.Join(",", orderitem.Select(n => n.deptname).Distinct()),
checkStatus = item.CHECKSTATUS,
OrderIds = string.Join(",", oids),
CTime = string.Join(",", orderitem.Select(n => n.CTIME.Value.ToString("yyyy-MM-dd HH:mm:ss"))),
CheckTime = item.CHECKTIME,
Ename = item.ENAME,
AuditTime = String.Join(",", orderitem.Where(n => n.OTIME.HasValue).Select(n => n.OTIME.Value.ToString("yyyy-MM-dd HH:mm:ss")))
};
List<string> innerUserName = new List<string>();
if (innerusers != null && innerusers.Any())
{
var inneruser = innerusers.Where(x => orderitem.Select(n => n.eid).Contains(x.EId));
innerUserName = inneruser.Select(n => n.Name).Distinct().ToList();
if (inneruser != null)
{
newModel.innerUserName = String.Join(",", innerUserName);
}
}
if (orderAuditList != null && orderAuditList.Any())
{
List<string> inneraudit = new List<string>();
foreach (var ad in oids)
{
var firstAd = orderAuditList.OrderByDescending(n => n.CreateTime).FirstOrDefault(n => n.Orderid == ad);
if (firstAd != null && !string.IsNullOrWhiteSpace(firstAd.Auditor))
{
inneraudit.Add(firstAd.Auditor);
}
}
newModel.AuditName = string.Join(",", inneraudit);
}
if (item.HG_CheckQualityLogDetail.Count == 0)
{
res.Add(newModel);
continue;
}
foreach (var detail in item.HG_CheckQualityLogDetail)
{
newModel.CheckType = detail.checktype;
newModel.CheckTypeName = ((HGCheckType)detail.checktype).GetDescription();
newModel.condition = detail.condition.Split(',').Select(n => Convert.ToInt32(n)).ToList();
newModel.content = detail.content;
newModel.suggest = detail.suggest;
newModel.conditionText = detail.conditiontext;
if (detail.checktype == (int)HGCheckType.)
{
List<string> showSource = new List<string>();
foreach (var soul in detail.HG_CheckQualityLogSource)
{
if (soul.eid > 0)
{
showSource.Add($"{soul.appuserid}({soul.eid}{soul.ename})");
}
else
{
showSource.Add($"{soul.appuserid}");
}
}
newModel.ShowSource = String.Join(",", showSource);
}
else
{
newModel.ShowSource = String.Join(",", detail.HG_CheckQualityLogSource.Select(n => $"{n.recordid}"));
}
res.Add(newModel);
}
}
var result = new PageResult<CheckOrderList>(dto.PageIndex, dto.PageSize, total, res);
stopwatch.Stop();
Log.Information($"构建质检明细耗时{stopwatch.ElapsedMilliseconds}ms");
return result;
}
private async Task<string> QueryResidByUMID(string UMID)
{
var UMIDMain = await _repository.GetRepository<RES_CUSTOMER>().Query().FirstOrDefaultAsync(m => m.UMID == UMID);
if (UMIDMain != null)
{
return UMIDMain.RESID;
}
else
{
return "NULL_RESID";
}
}
private async Task<string> GetNoticeNo()
{
var noticeId = $@"ZJ{DateTime.Now.Year}{DateTime.Now.Month}{DateTime.Now.Day}";
string keyName = CacheKeys.CheckNoticeNo + DateTime.Now.ToString("yyyyMMdd");
if (!await _redisManager.ExistsAsync(keyName))
{
await _redisManager.SetAsync(keyName, 1, TimeSpan.FromHours(24));
return noticeId + GetNumberStr(1);
}
else
{
var no = _redisManager.Get<int>(keyName) + 1;
await _redisManager.SetAsync(keyName, no, TimeSpan.FromHours(24));//加1
return noticeId + GetNumberStr(no);
}
}
private string GetNumberStr(int no)
{
if (no < 10)
return "00" + no;
if (no >= 10 && no < 100)
return "0" + no;
else
return no.ToString();
}
public async Task<bool> AddCheckNotice(HgCheckQualityNoticeDto dto)
{
try
{
// 创建新的通知
Log.Information("创建违规单 ");
Log.Information("HgCheckQualityNoticeDto " + dto.ToJson());
DepartmentInfo info = _employeeDomain.GetAllDeptInfos(dto.NoticeCreator);
CenterInfo signInfo = await _employeeDomain.GetCenterNameAsync(dto.ToEid);
Log.Information("signInfo " + signInfo.ToJson());
var notice = new Hg_CheckQuality_Notice
{
NoticeNo = await GetNoticeNo(),//获取合同号
NoticeDate = DateTime.Now,
FromDept = info.deptmentIds,//合规部门
FromDeptName = info.deptmentNames,//合规部门
ToEid = dto.ToEid,
ToDept = signInfo.deptId.ToString(),//业务部门
ToDeptName = signInfo.centerName,//业务部门
Content = dto.Content,
NoticeCreator = dto.NoticeCreator,
NoticeCreatorName = dto.NoticeCreatorName,
NoticeCtime = DateTime.Now,
isDelete = 0
};
// 插入通知到数据库
await _repository.GetRepository<Hg_CheckQuality_Notice>().InsertAsync(notice);
// 为每个通知人员创建签名记录
foreach (var signer in dto.PersonList)
{
var noticeSign = new Hg_CheckQuality_NoticeSign
{
NoticeId = notice.id,
NoticeNo = notice.NoticeNo,
NoticeLevel = signer.NoticeLevel, // 假设签名者有一个等级属性
eid = signer.Eid,
Name = _employeeDomain.GetEmpoyeeName(signer.Eid),
Sign = 0 // 默认未签名
};
// 插入签名记录到数据库
await _repository.GetRepository<Hg_CheckQuality_NoticeSign>().InsertAsync(noticeSign);
}
return true;
}
catch (Exception ex)
{
Log.Error($"添加检查通知失败: {ex.Message}");
throw;
}
}
public async Task<bool> EditCheckNotice(EditHgCheckQualityNoticeDto dto)
{
try
{
// 创建新的通知
Log.Information("更新违规单 ");
Log.Information("HgCheckQualityNoticeDto id" + dto.Id.ToString());
var notice = await GetHgCheckQualityNoticeModel(dto.Id);
notice.Content = dto.Content;
// 插入通知到数据库
await _repository.GetRepository<Hg_CheckQuality_Notice>().UpdateAsync(notice);
return true;
}
catch (Exception ex)
{
Log.Error($"添加检查通知失败: {ex.Message}");
throw;
}
}
public async Task<bool> DelCheckNotice(int id)
{
try
{
var info = await this.GetHgCheckQualityNoticeModel(id);
info.isDelete = 1;
// 插入通知到数据库
await _repository.GetRepository<Hg_CheckQuality_Notice>().UpdateAsync(info, m => new { m.isDelete });//修改删除状态
return true;
}
catch (Exception ex)
{
Log.Error($"添加检查通知失败: {ex.Message}");
throw;
}
}
private async Task<Hg_CheckQuality_Notice> GetHgCheckQualityNoticeModel(int id)
{
return await _repository.GetRepository<Hg_CheckQuality_Notice>().FirstOrDefaultAsync(m => m.id == id);
}
private async Task<Hg_CheckQuality_NoticeSign> GetHgCheckQualityNoticeOptionModel(int id, string NoticeLevel)
{
return await _repository.GetRepository<Hg_CheckQuality_NoticeSign>().FirstOrDefaultAsync(m => m.NoticeId == id && m.NoticeLevel == NoticeLevel);
}
public async Task<bool> AddQualityNoticeOption(QualityNoticeOption dto)
{
var info = await this.GetHgCheckQualityNoticeModel(dto.id);
if (info == null)
{
throw new Exception("参数错误");
}
var option = await this.GetHgCheckQualityNoticeOptionModel(dto.id, dto.NoticeLevel);
var noticeSign = new Hg_CheckQuality_NoticeSign
{
NoticeId = dto.id,
NoticeNo = info.NoticeNo,
NoticeLevel = dto.NoticeLevel, // 假设签名者有一个等级属性
eid = dto.eid,
Name = _employeeDomain.GetEmpoyeeName(dto.eid),
Sign = 1,
Opinion = dto.opinion,
SignTime = DateTime.Now,
};
if (option == null)
// 插入签名记录到数据库
await _repository.GetRepository<Hg_CheckQuality_NoticeSign>().InsertAsync(noticeSign);
else
{
//noticeSign.id = option.id;
option.Sign = 1;
option.Opinion = noticeSign.Opinion;
option.SignTime = noticeSign.SignTime;
option.eid = noticeSign.eid;
option.Name = noticeSign.Name;
await _repository.GetRepository<Hg_CheckQuality_NoticeSign>().UpdateAsync(option, x => new { x.eid, x.Name, x.Sign, x.Opinion, x.SignTime });
}
return true;
}
public async Task<PageResult<Hg_CheckQuality_Notice>> GetCheckQualityNotice(HgCheckQualitySearchDto dto)
{
var query = _repository.GetRepository<Hg_CheckQuality_Notice>().Query().Where(m => m.isDelete == 0);
if (dto.stime.HasValue)
{
query = query.Where(m => m.NoticeCtime >= dto.stime.Value);
}
if (dto.etime.HasValue)
{
query = query.Where(m => m.NoticeCtime < dto.etime.Value);
}
if (!string.IsNullOrEmpty(dto.toDept))
{
query = query.Where(m => m.ToDept == dto.toDept);
}
if (!string.IsNullOrEmpty(dto.noticeNo))
{
query = query.Where(m => m.NoticeNo == dto.noticeNo);
}
if (dto.eid.HasValue)//如果传了工号,那么就要工号过滤
{
var query1 = _repository.GetRepository<Hg_CheckQuality_NoticeSign>().Query().Where(m => m.NoticeLevel == "manage");
var einfo = from a in query
join b in query1 on a.id equals b.NoticeId into jiontemp
from sign in jiontemp.DefaultIfEmpty()//左关联(用户组/部门 关系表)
where a.ToEid == dto.eid.Value || sign.eid == dto.eid.Value
select a;
var list = await einfo.OrderByDescending(x => x.NoticeCtime)
.Skip((dto.PageIndex - 1) * dto.PageSize)
.Take(dto.PageSize).Include(m => m.Hg_CheckQuality_NoticeSigns)
.ToListAsync();
var total = await einfo.CountAsync();
PageResult<Hg_CheckQuality_Notice> dataList = new PageResult<Hg_CheckQuality_Notice>(dto.PageIndex, dto.PageSize, total, list);
return dataList;
}
else
{
var list = await query.OrderByDescending(x => x.NoticeCtime)
.Skip((dto.PageIndex - 1) * dto.PageSize)
.Take(dto.PageSize).Include(m => m.Hg_CheckQuality_NoticeSigns)
.ToListAsync();
var total = await query.CountAsync();
PageResult<Hg_CheckQuality_Notice> dataList = new PageResult<Hg_CheckQuality_Notice>(dto.PageIndex, dto.PageSize, total, list);
return dataList;
}
}
/// <summary>
/// 查找违规通知单明细
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<Hg_CheckQuality_Notice> GetCheckQualityInfo(int id)
{
var info = await _repository.GetRepository<Hg_CheckQuality_Notice>().Query().Where(m => m.id == id).Include(m => m.Hg_CheckQuality_NoticeSigns).FirstOrDefaultAsync();
return info;
}
/// <summary>
/// 添加处罚单
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public async Task<bool> AddQualityPunish(QualityPunish dto)
{
var info = await this.GetHgCheckQualityNoticeModel(dto.id);
if (info == null)
{
throw new Exception("参数错误");
}
info.PunishContent = dto.content;
info.PunishCreator = dto.eid;
info.PunishCreatorName = _employeeDomain.GetEmpoyeeName(dto.eid);
info.PunishCtime = DateTime.Now;
info.PunishNo = "F-" + await GetNoticeNo();//处罚单前面加一个f
await _repository.GetRepository<Hg_CheckQuality_Notice>().UpdateAsync(info, x => new { x.PunishContent, x.PunishCreator, x.PunishCreatorName, x.PunishCtime, x.PunishNo });
return true;
}
}
}