Files
zszq-trs/YLErpDAL/Modules/ClientModule/ClientBlackService.cs
T
tengyufan 8701bd8c44 fix(ClientBlack): 修正黑名单删除结果提示
- 根据本次实际进入删除审批的记录数返回删除结果
- 未提交、新增已拒绝直接删除时提示“删除成功”
- 已生效记录进入删除审批时提示“已经提交删除审批”
- 批量混合删除时提示部分记录已提交删除审批
2026-08-19 10:16:51 +08:00

640 lines
26 KiB
C#

using BaseOUDAL;
using Microsoft.Extensions.DependencyInjection;
using Org.BouncyCastle.Crypto.Tls;
using Qdp.Foundation.Utilities;
using System.Data;
using YieldChain.Commons;
using YLErp.Abstract;
using YLErp.Commons;
using YLErp.Model;
using YLErp.Models.Tag;
using YLErp.Modules.ClientModule.Dto;
using YLErp.Modules.TagModule;
namespace YLErp.Modules.ClientModule
{
/// <summary>
/// 客户黑名单服务
/// </summary>
public class ClientBlackService : ClientBaseService
{
private IKafkaProduce _kafkaProduce;
public ClientBlackService(OptUserInfo userInfo) : base(userInfo)
{
_kafkaProduce = YLServiceLocator.ServiceProvider.GetService<IKafkaProduce>();
}
/// <summary>
/// 查询黑名单列表
/// </summary>
public SearchListResult<client_black> SearchList(ClientBlackReq req)
{
var predicate = PredicateBuilder.True<client_black>();
if (req.ids != null && req.ids.Any())
{
predicate = PredicateBuilder.Create<client_black>(n => req.ids.Contains(n.id));
}
else
{
if (!string.IsNullOrEmpty(req.Name))
{
predicate = predicate.And(d => d.Name.Contains(req.Name));
}
if (!string.IsNullOrEmpty(req.ClientBlackStates))
{
var states = req.ClientBlackStates.Split(',', StringSplitOptions.RemoveEmptyEntries);
predicate = predicate.And(d => states.Contains(d.State));
}
if (req.DateFromOptDate.HasValue)
{
predicate = predicate.And(d => d.OptDate >= req.DateFromOptDate.Value);
}
if (req.DateToOptDate.HasValue)
{
predicate = predicate.And(d => d.OptDate < req.DateToOptDate.Value.AddDays(1));
}
}
var query = DbContext.client_black.AsNoTracking().Where(predicate);
if (string.IsNullOrEmpty(req.sidx))
{
req.sidx = "id";
req.sord = "asc";
}
var retListResult = query.ToSearchList(req);
if (retListResult != null && retListResult.rows != null && retListResult.rows.Any())
{
var names = retListResult.rows.Select(p => p.Name).Distinct().ToList();
var clients = DbContext.client.AsNoTracking().Where(p => names.Contains(p.Name)).Select(p => new ClientSimpleDto { id = p.id, Name = p.Name }).ToList();
if (clients != null && clients.Count > 0)
{
Dictionary<int, List<TagDto>> clientTagList = null;
if (clients != null && clients.Any())
{
using (var tagService = new TagService(OptUser))
{
clientTagList = tagService.GetTagByClientIds(clients.Select(p => p.id).Distinct().ToList());
}
}
if (clientTagList == null)
{
clientTagList = new Dictionary<int, List<TagDto>>();
}
clients.ForEach(p =>
{
var retInfo = retListResult.rows.FirstOrDefault(d => d.Name.Equals(p.Name));
if (retInfo != null)
{
//拼装标签值
if (clientTagList.ContainsKey(p.id))
{
retInfo.Tags = clientTagList[p.id];
retInfo.OutputTags = TagService.GetOutputTagsStr(retInfo.Tags);
}
}
});
}
}
return retListResult;
}
public List<approvalprocess> ProcessList()
{
return DbContextFactory.GetYLDbContext().approvalprocess
.Where(s => s.processType == "ClientBlackProcess")
.OrderBy(s => s.order)
.ToList();
}
public int DeleteClientBlack(IEnumerable<int> ids)
{
var idList = ids?.Distinct().ToList() ?? new List<int>();
if (idList.Count == 0)
{
throw new ServiceException("请选择要移出的黑名单客户");
}
var rows = DbContext.client_black.Where(x => idList.Contains(x.id)).ToList();
if (rows.Count != idList.Count)
{
throw new ServiceException("未找到要删除的数据");
}
var hasProcess = ProcessList().Any();
var submitRemovalApprovalCount = 0;
foreach (var row in rows)
{
if (ClientBlackApprovalPolicy.CanDeleteDraft(row.State))
{
DbContext.client_black.Remove(row);
ClientBlackCategoryLog(row.id, "已删除");
continue;
}
if (!ClientBlackApprovalPolicy.CanRequestRemoval(row.State))
{
throw new ServiceException($"黑名单客户{row.Name}当前状态不允许移出");
}
if (hasProcess)
{
var result = ClientBlackApprovalPolicy.GetRemovalResult(true);
row.State = result.State;
row.ApprovalProcess = result.ApprovalProcess;
row.ApprovalOptName = UserName;
row.ApprovalOptDate = DateTime.Now;
ClientBlackCategoryLog(row.id, client_black.删除审批中);
submitRemovalApprovalCount++;
}
else
{
RemoveEffectiveBlack(row);
}
}
DbContext.SaveChanges();
return submitRemovalApprovalCount;
}
public void WithdrawApprovalClientBlack(List<int> ids, out int withdrawCount, out string msg)
{
withdrawCount = 0;
msg = "";
var rows = DbContext.client_black.Where(x => ids.Contains(x.id)).ToList();
foreach (var row in rows)
{
if (!ClientBlackApprovalPolicy.CanWithdraw(row.State, row.ApprovalProcess))
{
if (row.ApprovalProcess > 1)
{
msg += row.Name + ",";
}
continue;
}
var result = ClientBlackApprovalPolicy.GetWithdrawResult(row.State);
row.State = result.State;
row.ApprovalProcess = result.ApprovalProcess;
row.ApprovalOptName = null;
row.ApprovalOptDate = null;
ClientBlackCategoryLog(row.id, row.State);
withdrawCount++;
}
DbContext.SaveChanges();
}
public void SubmitApprovalClientBlack(List<int> ids)
{
var rows = DbContext.client_black.Where(x => ids.Contains(x.id)).ToList();
var process = ProcessList();
foreach (var row in rows)
{
if (!ClientBlackApprovalPolicy.CanSubmitAddition(row.State))
{
continue;
}
if (process.Count == 0)
{
row.State = client_black.已加入;
row.ApprovalProcess = -2;
row.ApprovalOptName = UserName;
row.ApprovalOptDate = DateTime.Now;
var notifications = new List<(Client oldClient, Client newClient)>();
ApplyEffectiveAddition(row.Name, notifications);
ClientBlackCategoryLog(row.id, client_black.已加入, "未设置审批流程,直接通过");
DbContext.SaveChanges();
SendClientNotifications(notifications);
continue;
}
row.State = client_black.新增审批中;
row.ApprovalProcess = 1;
row.ApprovalOptName = UserName;
row.ApprovalOptDate = DateTime.Now;
ClientBlackCategoryLog(row.id, client_black.新增审批中);
}
DbContext.SaveChanges();
}
public string AuditClientBlack(ClientBlackAuditReq req, bool isBatch = false, string optType = "")
{
var row = DbContext.client_black.Find(req.id);
if (row == null)
{
throw new ServiceException("审批失败,系统中没有该黑名单记录");
}
if (row.State != client_black.新增审批中 && row.State != client_black.删除审批中)
{
throw new ServiceException("当前黑名单不在审批中");
}
var process = ProcessList();
var currentNode = process.FirstOrDefault(x => x.order == row.ApprovalProcess);
if (currentNode == null || !UserBLL.GetRolesByUserId(UserId).Any(x => x.Id == currentNode.roleId))
{
throw new ServiceException("当前用户无权审批该节点");
}
if (req.status == "reject")
{
row.State = ClientBlackApprovalPolicy.GetRejectedState(row.State);
row.ApprovalProcess = -1;
row.ApprovalOptDate = DateTime.Now;
row.OptId = UserId;
row.OptName = UserName;
row.OptDate = DateTime.Now;
ClientBlackCategoryLog(row.id, row.State, req.auditComment);
DbContext.SaveChanges();
return "提交成功";
}
if (req.status != "pass")
{
throw new ServiceException("status参数不支持:" + req.status);
}
var nextNode = process.FirstOrDefault(x => x.order > row.ApprovalProcess);
if (nextNode != null)
{
row.ApprovalProcess = nextNode.order;
row.ApprovalOptDate = DateTime.Now;
row.OptId = UserId;
row.OptName = UserName;
row.OptDate = DateTime.Now;
ClientBlackCategoryLog(row.id, row.State, req.auditComment);
DbContext.SaveChanges();
return "提交成功";
}
var final = ClientBlackApprovalPolicy.GetFinalResult(row.State);
if (final.ShouldDelete)
{
RemoveEffectiveBlack(row, req.auditComment, isBatch ? optType : null);
DbContext.SaveChanges();
}
else
{
row.State = final.State;
row.ApprovalProcess = -2;
row.ApprovalOptDate = DateTime.Now;
var notifications = new List<(Client oldClient, Client newClient)>();
ApplyEffectiveAddition(row.Name, notifications);
ClientBlackCategoryLog(row.id, isBatch ? optType : row.State, req.auditComment);
DbContext.SaveChanges();
SendClientNotifications(notifications);
}
return "提交成功";
}
public SearchListResult<ClientBlackApprovalQueryRes> ClientBlackApprovalQuery(ClientBlackReq req)
{
var process = ProcessList();
var predicate = PredicateBuilder.Create<client_black>(x => x.ApprovalProcess > 0);
if (!string.IsNullOrWhiteSpace(req.Name))
{
predicate = predicate.And(x => x.Name.Contains(req.Name));
}
var query = from row in DbContext.client_black.AsNoTracking().Where(predicate)
select new ClientBlackApprovalQueryRes
{
id = row.id,
EncryptId = row.EncryptId,
ProcessOrderId = row.ApprovalProcess,
ProcessRoleId = 0,
ProcessStatus = "审批中 流程" + (row.ApprovalProcess - 1) + "/" + process.Count,
State = row.State,
ClientName = row.Name,
Comments = row.Remarks,
ApprovalOptName = row.ApprovalOptName,
ApprovalOptDate = row.ApprovalOptDate,
creator_id = row.creator_id,
creator_name = row.creator_name,
creator_time = row.creator_time
};
if (string.IsNullOrEmpty(req.sidx))
{
req.sidx = "ApprovalOptDate";
req.sord = "desc";
}
var result = query.OrderByDescending(x => x.ApprovalOptDate).ToSearchList(req);
var roles = new ErpBaseContext().Roles
.Select(x => new { x.Id, x.Name })
.ToDictionary(x => x.Id, x => x.Name);
foreach (var item in result.rows)
{
var node = process.FirstOrDefault(x => x.order == item.ProcessOrderId);
if (node == null)
{
continue;
}
item.ProcessRoleId = node.roleId;
item.ProcessRoleName = roles.TryGetValue(node.roleId, out var roleName) ? roleName : string.Empty;
}
return result;
}
private void ApplyEffectiveAddition(string name, List<(Client oldClient, Client newClient)> notifications)
{
var client = DbContext.client.FirstOrDefault(c => c.Name == name);
if (client == null)
{
return;
}
var dt = DateTime.Now;
var oldClient = client.Clone();
if (client.ProcessStatus == "已开户")
{
client.ProcessOrderId = -4;
client.ProcessStatus = "已休眠";
client.OptId = UserId;
client.OptName = UserName;
client.OptDate = dt;
DbContext.ClientAuditLog.Add(new ClientAuditLog
{
ClientId = client.id,
OptType = "休眠",
Changes = string.Empty,
DataType = "00",
OptId = UserId,
OptName = UserName,
OptDate = dt
});
notifications.Add((oldClient, client));
}
DbContext.ClientAuditLog.Add(new ClientAuditLog
{
ClientId = client.id,
OptType = "加入黑名单",
Changes = string.Empty,
DataType = "00",
OptId = UserId,
OptName = UserName,
OptDate = dt
});
}
private void RemoveEffectiveBlack(client_black row, string changes = null, string optType = null)
{
var client = DbContext.client.FirstOrDefault(c => c.Name == row.Name);
if (client != null)
{
DbContext.ClientAuditLog.Add(new ClientAuditLog
{
ClientId = client.id,
OptType = "移除黑名单",
Changes = string.Empty,
DataType = "00",
OptId = UserId,
OptName = UserName,
OptDate = DateTime.Now
});
}
DbContext.client_black.Remove(row);
ClientBlackCategoryLog(row.id, optType ?? "已删除", changes);
}
private void SendClientNotifications(List<(Client oldClient, Client newClient)> notifications)
{
foreach (var (oldClient, newClient) in notifications)
{
new ClientKafkaService(_kafkaProduce).Send(newClient, oldClient);
}
}
public void ClientBlackCategoryLog(int clientblackId, string optType, string changes = null)
{
DbContext.client_blacklog.Add(new ClientBlackLog
{
ClientBlackId = clientblackId,
OptType = optType,
Changes = changes,
DataType = "00",
OptId = UserId,
OptName = UserName,
OptDate = DateTime.Now
});
}
/// <summary>
/// 客户黑名单导入
/// </summary>
public void ImportxlsxClientBlack(Stream stream, bool checkStatus)
{
//当前编码支持ansi和utf with bom
var ds = Office.ExcelHelper.ReadExcelAsDataSet(stream);
if (ds.Tables.Count < 1 || ds.Tables[0].Rows.Count < 1)
{
throw new ServiceException("读取导入数据失败:数据为空") { Tag = "111" };
}
var table = ds.Tables[0];
if (table.Rows.Count < 1)
{
throw new ServiceException("导入数据不能为空!");
}
var list = new List<client_black>();
foreach (DataRow row in table.Rows)
{
if (row.IsNull("客户名称"))
{
throw new ServiceException("导入客户名称不能为空!");
}
var importModel = new client_black
{
Name = row["客户名称"].ToString(),
Remarks = row.IsNull("备注") ? "" : row["备注"].ToString()
};
if (table.Columns.Contains("标签值") && !string.IsNullOrEmpty(row["标签值"].ToString()))
{
var tagStrArr = row["标签值"].ToString().Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
if (tagStrArr != null && tagStrArr.Length > 0)
{
importModel.Tags = tagStrArr.Select(p => new YLErp.Models.Tag.TagDto { Name = p }).ToList();
}
}
if (list.Where(x => x.Name == importModel.Name).Count() > 0)
throw new ServiceException($"第{row.Table.Rows.IndexOf(row) + 2}行客户名称:'{importModel.Name}'重复!");
else
list.Add(importModel);
}
var importHasTagClientNames = list.Where(p => p.Tags != null && p.Tags.Count > 0).Select(p => p.Name).Distinct().ToList();
if (importHasTagClientNames != null && importHasTagClientNames.Count > 0)
{
var dbClientNames = DbContext.client.AsNoTracking().Where(p => importHasTagClientNames.Contains(p.Name)).Select(p => p.Name).Distinct().ToList();
if (dbClientNames != null && dbClientNames.Count > 0)
{
dbClientNames.ForEach(p => { importHasTagClientNames.Remove(p); });
}
if (importHasTagClientNames.Count > 0)
{
throw new ServiceException(String.Join(",", importHasTagClientNames) + "不存在开户记录,无法设置标签值,请清除表格中对应客户的标签值再继续导入");
}
}
var importHasLongTagClientNames = list.Where(p => p.Tags != null && p.Tags.Any(d => d.Name.Length > 30)).Select(p => p.Name).Distinct().ToList();
if (importHasLongTagClientNames != null && importHasLongTagClientNames.Count > 0)
{
throw new ServiceException(String.Join(",", importHasLongTagClientNames) + "存在过长的标签值(每个标签值限制30个字符,多个以英文分号隔开),请调整完成后再导入");
}
AddClientBlack(list, checkStatus);
}
public void AddClientBlack(IEnumerable<client_black> list, bool checkStatus)
{
var inputList = list?.ToList() ?? new List<client_black>();
var errMsgList = new List<string>();
var nameList = inputList.Select(O => O.Name).ToList();
var dbList = DbContext.client_black.Where(O => nameList.Contains(O.Name)).ToList();
foreach (var item in dbList)
{
var obj = inputList.FirstOrDefault(O => O.Name.Equals(item.Name, StringComparison.OrdinalIgnoreCase));
if (obj == null)
{
continue;
}
if (!ClientBlackApprovalPolicy.CanReplaceRemarks(item.State))
{
throw new ServiceException("黑名单客户在审批中无法修改!");
}
if (checkStatus && !string.IsNullOrWhiteSpace(item.Remarks) && item.Remarks != obj.Remarks)
{
errMsgList.Add($"{item.Name}");
}
}
if (checkStatus)
{
if (errMsgList.Count > 0)
{
var msg = "";
if (errMsgList.Count <= 5)
{
msg = $"客户:{string.Join(",", errMsgList)}当前已在黑名单中,本次将修改备注,备注已存在,是否确认?";
}
else
{
msg = $"{string.Join(",", errMsgList.Take(5))} 等{errMsgList.Count}个客户当前已在黑名单中,本次将修改备注,备注已存在,是否确认?";
}
throw new ServiceException(msg);
}
}
// 在外部定义列表来保存需要通知的客户对
var clientsToNotify = new List<(Client oldClient, Client newClient)>();
var newItems = new List<client_black>();
var processList = ProcessList();
foreach (var item in inputList)
{
if (string.IsNullOrWhiteSpace(item.Name))
{
throw new ServiceException("导入客户名称不能为空!");
}
item.Name = item.Name?.ToString() ?? "";
item.Remarks = item.Remarks?.ToString() ?? "";
item.OptId = UserId;
item.OptName = UserName;
item.OptDate = DateTime.Now;
var existing = dbList.FirstOrDefault(x => x.Name.Equals(item.Name, StringComparison.OrdinalIgnoreCase));
if (existing != null)
{
var oldRemarks = existing.Remarks;
existing.Remarks = item.Remarks;
existing.OptId = UserId;
existing.OptName = UserName;
existing.OptDate = DateTime.Now;
if (oldRemarks != existing.Remarks)
{
ClientBlackCategoryLog(existing.id, "修改备注", $"备注:{oldRemarks ?? string.Empty} -> {existing.Remarks ?? string.Empty}");
}
continue;
}
var additionResult = ClientBlackApprovalPolicy.GetAdditionResult(processList.Any());
item.State = additionResult.State;
item.ApprovalProcess = additionResult.ApprovalProcess;
item.creator_id = UserId;
item.creator_name = UserName;
item.creator_time = DateTime.Now;
if (additionResult.IsEffective)
{
ApplyEffectiveAddition(item.Name, clientsToNotify);
}
newItems.Add(item);
}
DbContext.client_black.AddRange(newItems);
DbContext.SaveChanges();
foreach (var item in newItems)
{
ClientBlackCategoryLog(item.id, item.State);
}
DbContext.SaveChanges();
// 发送Kafka消息
foreach (var (oldClient, newClient) in clientsToNotify)
{
new ClientKafkaService(_kafkaProduce).Send(newClient, oldClient);
}
var importHasTagClientNames = inputList.Where(p => p.Tags != null && p.Tags.Count > 0).Select(p => p.Name).Distinct().ToList();
if (importHasTagClientNames != null && importHasTagClientNames.Count > 0)
{
var dbClients = DbContext.client.AsNoTracking().Where(p => importHasTagClientNames.Contains(p.Name)).Select(p => new ClientSimpleDto
{
id = p.id,
Name = p.Name
}).ToList();
if (dbClients != null && dbClients.Count > 0)
{
var tagService = new TagService(OptUser);
dbClients.ForEach(p =>
{
var importInfo = inputList.FirstOrDefault(d => d.Name.Equals(p.Name));
if (importInfo != null)
{
tagService.SetClientTagForClientImport(new TagModule.Dto.SetClientTagForClientEditRequest { ClientId = p.id, Tags = importInfo.Tags });
}
});
}
}
}
/// <summary>
/// 黑名单导出
/// </summary>
public byte[] ExportClientBlack(ClientBlackReq req)
{
if (req.ids == null || !req.ids.Any())
{
req.ids = null;
req.rows = 10000;
}
else
{
req.Name = null;
}
var slist = SearchList(req);
var dc = new List<ExcelHelper.DataColumnModel>
{
new ExcelHelper.DataColumnModel("客户名称", "Name"),
new ExcelHelper.DataColumnModel("备注", "Remarks",typeof(string))
};
new ExcelHelper().ListToExcel(dc.ToArray(), slist.rows.ToList(), "黑名单导出", true, out var buffer);
return buffer;
}
}
}