- 黑名单新增、删除、批量导入、批量移出在配置审批节点后,审批通过才生效 - 新增黑名单待提交后可提交审批;仅首节点未审批时可撤回,进入后续节点禁止撤回 - 增加黑名单审批列表、审批弹窗、审批操作日志及状态筛选 - 支持审批配置中的“黑名单审批”流程及对应菜单、模块权限、操作权限 - 黑名单审批中禁止同名记录覆盖备注;已在黑名单中的同名导入会明确提示本次将修改备注 - 未配置审批节点时保持原有直接生效行为 - 增加黑名单审批状态机单测,39/39 通过 - 修正撤回全部失败时仍提示“撤回审批成功”的问题
262 lines
12 KiB
C#
262 lines
12 KiB
C#
using BaseOUDAL;
|
|
using DocumentFormat.OpenXml.Spreadsheet;
|
|
using Qdp.Pricing.Library.Base.Utilities;
|
|
using YLErp.BLL;
|
|
using YLErp.CustomizedBizLogic;
|
|
using YLErp.Model.Enum;
|
|
|
|
namespace YLErp.Modules.ClientModule
|
|
{
|
|
/// <summary>
|
|
/// 客户审核流程服务
|
|
/// </summary>
|
|
public class ClientProcessService : ClientBaseService
|
|
{
|
|
public ClientProcessService(OptUserInfo userInfo) : base(userInfo)
|
|
{
|
|
}
|
|
|
|
public ClientProcessService(BaseService<ClientDBContext> baseService) : base(baseService)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// 提交审批
|
|
/// </summary>
|
|
public string SubmitProcess(int clientId, out Client client)
|
|
{
|
|
try
|
|
{
|
|
client = DbContext.client.FirstOrDefault(s => s.id == clientId);
|
|
|
|
var bankcardService = new ClientBankCardService(OptUser);
|
|
|
|
if (client == null)
|
|
{
|
|
throw new ServiceException("请先保存用户基本信息");
|
|
}
|
|
|
|
CheckModel(client);
|
|
|
|
if (PS.Config.IsGuoJun && client.SupProtocolDate == null && client.ConfirmBookMode == "单章版")
|
|
{
|
|
client.SupProtocolDate = client.ProtocolSignDate;
|
|
}
|
|
|
|
//未设置流程 直接设置成开户状态
|
|
var openProcess = yldb.approvalprocess.Where(s => s.processType == "OpenProcess").ToList();
|
|
if (openProcess.Count == 0)
|
|
{
|
|
client.ProcessStatus = "已开户";
|
|
client.ProcessOrderId = -2;
|
|
client.ProcessOptDate = DateTime.Now;
|
|
if (string.IsNullOrEmpty(client.Number))
|
|
{
|
|
BizLogicSingleton.Instance.GenerateClientCode(client, DbContext.client);
|
|
}
|
|
|
|
//每一个成功开户的客户(即首次从【开户管理】转到【客户列表】),系统会自动在【资信等级】页面对该客户留下第一条“资信等级”记录,
|
|
//但是具体等级是什么,适用期限(生效日期、到期日期)是什么,都空着,待风控人员来填写;
|
|
if (!DbContext.Client_Rating.Any(x => !x.IsDeleted && x.ClientId == clientId))
|
|
{
|
|
var emptyRating = new ClientRating
|
|
{
|
|
ClientId = client.id,
|
|
ClientName = client.Name,
|
|
ClientNumber = client.Number,
|
|
Comments = "开户成功生成",
|
|
OptId = UserId,
|
|
OptName = UserName,
|
|
OptDate = DateTime.Now,
|
|
|
|
RatingStartDate = valuedateBLL.ValueDate
|
|
};
|
|
emptyRating.RatingDeadLine = emptyRating.RatingStartDate.Value.AddYears(99);
|
|
var defaultRating = DbContext.credit_rating.Where(x => x.ValidState == "Valid").FirstOrDefault();
|
|
emptyRating.CreditRatingId = defaultRating?.id ?? 0;
|
|
emptyRating.CreditRatingStr = defaultRating?.CreditName;
|
|
emptyRating.ProcessStatus = "未审批";
|
|
emptyRating.ProcessOrderId = 0;
|
|
emptyRating.ProcessOptDate = DateTime.Now;
|
|
DbContext.Client_Rating.Add(emptyRating);
|
|
yldb.SaveChanges();
|
|
}
|
|
|
|
bankcardService.SetBankCardValidStateWhenClientReEnable((int)client.id, DbContext);
|
|
|
|
DbContext.SaveChanges();
|
|
|
|
return "已开户";
|
|
}
|
|
|
|
if (client.ProcessStatus == "已开户")
|
|
{
|
|
throw new ServiceException("已开户,无需再次提交");
|
|
}
|
|
|
|
if (client.ApprovalStatus == "审批中")
|
|
{
|
|
throw new ServiceException("正在审批中");
|
|
}
|
|
var oldApprovalStatus = client.ApprovalStatus;
|
|
var groupId = UserBLL.GetApprovalProcessGroup(UserId);
|
|
bool approvalBranch = openProcess.Any(x => x.approvalGroupId != 0);//审批流程有分支情况
|
|
client.ProcessOrderBranch = 0;
|
|
client.ApprovalOrderId = ProcessTradeLog.审批中;
|
|
client.ApprovalStatus = "审批中";
|
|
client.ApprovalOptDate = DateTime.Now;
|
|
client.ProcessOrderId = -1;
|
|
client.ProcessStatus = client.ProcessStatus == "未提交" ? "未开户" : client.ProcessStatus;
|
|
client.ProcessOptDate = DateTime.Now;
|
|
if (approvalBranch)//审批流程有分支情况
|
|
{
|
|
//该审批组属于流程的审批组或该审批组不属于流程审批组
|
|
var tradeProessBranchQuery = openProcess.FirstOrDefault(x => (x.approvalGroupId == groupId && x.approvalCondition == 1) || (x.approvalGroupId != groupId && x.approvalCondition == 2));
|
|
if (tradeProessBranchQuery == null)//都没有情况
|
|
{
|
|
throw new ServiceException("当前存在分支开户审批流程,检测到申请人不满足任意一个分支进入条件,无法提交审批,请更换申请人或调整审批组");
|
|
}
|
|
client.ApprovalOrderId = tradeProessBranchQuery.order > 1 ? 1 : tradeProessBranchQuery.order + 1;//第一个节点是分支需要跳过审批组那一级
|
|
client.ProcessOrderBranch = tradeProessBranchQuery.node ?? 1;//审批组分支
|
|
}
|
|
var clientauditlog = new ClientAuditLog
|
|
{
|
|
ClientId = client.id,
|
|
OptType = oldApprovalStatus == "已拒绝" ? "重新提交开户审批" : "提交开户审批",
|
|
Changes = string.Empty,
|
|
DataType = "00",
|
|
OptId = UserId,
|
|
OptName = UserName,
|
|
OptDate = DateTime.Now
|
|
};
|
|
DbContext.ClientAuditLog.Add(clientauditlog);
|
|
DbContext.SaveChanges();
|
|
client.ApprovalLogId = clientauditlog.id;
|
|
DbContext.SaveChanges();
|
|
|
|
if (oldApprovalStatus == "已拒绝")
|
|
{
|
|
return "已重新提交审批";
|
|
}
|
|
|
|
bankcardService.SetBankCardValidStateWhenClientReEnable((int)client.id, DbContext);
|
|
DbContext.SaveChanges();
|
|
|
|
return "已提交,正在审批中";
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogFactory.GetLogger<ClientProcessService>().Error("提交开户审批", ex);
|
|
throw new ServiceException("异常 提交开户审批失败:" + ex.Message);
|
|
}
|
|
}
|
|
|
|
private void CheckModel(Client req)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(req.Name))
|
|
{
|
|
throw new ServiceException("客户名称 必须填写");
|
|
}
|
|
|
|
if (DbContext.client_black.Any(c => c.Name == req.Name && ClientBlackApprovalPolicy.EffectiveStates.Contains(c.State)))
|
|
{
|
|
throw new ServiceException("该客户为黑名单客户,无法进行下一步操作");
|
|
}
|
|
|
|
if (DbContext.client.Any(c => c.id != req.id && c.Name == req.Name && (c.ProcessStatus == "已开户" || c.ApprovalStatus == "审批中" || c.ProcessStatus == "已休眠")))
|
|
{
|
|
throw new ServiceException("客户名称不能重复");
|
|
}
|
|
|
|
//if (string.IsNullOrWhiteSpace(req.LicenseCode))
|
|
//{
|
|
// throw new ServiceException("证照编号 必须填写");
|
|
//}
|
|
|
|
//if (!string.IsNullOrWhiteSpace(req.LicenseCode) && !CheckLicenseCode(req.LicenseCode) && req.LicenseType == LicenseTypeEnum.营业执照.ToString())
|
|
//{
|
|
// throw new ServiceException("证照编号 不合法");
|
|
//}
|
|
|
|
if (DbContext.client.Any(x => x.id != req.id && x.Number == req.Number && !string.IsNullOrEmpty(req.Number)))
|
|
{
|
|
throw new ServiceException("客户编号不能重复");
|
|
}
|
|
|
|
if (!PS.Config.Is国泰君安 && PS.Config.ComponentVersion == Configuration.ComponentVersion.Broker)
|
|
{
|
|
if (DbContext.client.Any(x => x.id != req.id && x.Code == req.Code && !string.IsNullOrEmpty(req.Code)))
|
|
{
|
|
throw new ServiceException("客户代码不能重复");
|
|
}
|
|
}
|
|
|
|
if (DbContext.client.Any(x => x.id != req.id && x.DefaultLoginName == req.DefaultLoginName && !string.IsNullOrEmpty(req.DefaultLoginName)))
|
|
{
|
|
throw new ServiceException("默认登录名不能重复");
|
|
}
|
|
|
|
if (req.id == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (req.ParentId > 0 && Treeleveldata(req.id).Any(c => c.id == req.ParentId))
|
|
{
|
|
throw new ServiceException("所属机构不能选择下一层");
|
|
}
|
|
|
|
//存在已审批或审批中的资质评级
|
|
if (PS.Config.ClientElement.IsCreditLimit && req.IsCreditOn != 1 && DbContext.Client_Rating.Where(t => !t.IsDeleted && t.ClientId == req.id
|
|
&& (t.ProcessStatus == "已审批" || t.ProcessStatus == "审批中")
|
|
&& (!t.RatingDeadLine.HasValue || t.RatingDeadLine >= valuedateBLL.ValueDate)).Any())
|
|
{
|
|
throw new ServiceException("存在已审批或审批中的资质评级, 请先处理相关资质评级记录");
|
|
}
|
|
|
|
//存在已审批或审批中的授信
|
|
if (PS.Config.ClientElement.IsCreditLimit && req.IsCreditOn != 1 && yldb.credit.Where(t => t.ClientId == req.id && (t.ProcessStatus == "已审批" || t.ProcessStatus == "审批中") && (!t.CreditDeadLine.HasValue || t.CreditDeadLine >= valuedateBLL.ValueDate)).Any())
|
|
{
|
|
throw new ServiceException("存在已审批或审批中的授信, 客户期权费授信不能为否,请先处理相关授信记录");
|
|
}
|
|
|
|
//产品用户投资者,如果存在收益互换权限 只有专业投资者权益百分比可以大于20%
|
|
if (req.ClientType == ClientTypeEnum.产品.ToString() && req.DerivativesInvestmentVarieties.Contains((int)DerivativesInvestmentVarietiesEnum.场外互换 + ""))
|
|
{
|
|
//获取产品投资人
|
|
var hasClientInvestors = DbContext.ClientInvestor.Where(t => t.ClientId == req.id && !"专业投资者".Equals(t.EligibilityType) && t.ShareRate > 0.2);
|
|
if (hasClientInvestors != null && hasClientInvestors.Count() > 0)
|
|
{
|
|
throw new ServiceException("本产品客户,存在非专业投资人权益比例大于20%情况,无法进行场外互换交易!");
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool CheckLicenseCode(string licenseCode)
|
|
{
|
|
//原来按网上的规则实现了对15位和18位营业执照的检查,后来又客户发现了规则例外,甚至有出现17位
|
|
//的营业执照编号,因此只能先放宽要求
|
|
return licenseCode.Length >= 15 && licenseCode.Length <= 18;
|
|
}
|
|
|
|
private List<Client> Treeleveldata(int clientid)
|
|
{
|
|
var resultList = new List<Client>();
|
|
var clientQuery = DataCacheProvider.GetClientDataSource().AsQueryable();
|
|
FoundChildNode(clientQuery, clientid, resultList);
|
|
return resultList;
|
|
}
|
|
|
|
private void FoundChildNode(IQueryable<Client> clientQuery, int parentId, List<Client> resultList)
|
|
{
|
|
var childItems = clientQuery.Where(c => c.ParentId == parentId).ToList();
|
|
foreach (var child in childItems)
|
|
{
|
|
resultList.Add(child);
|
|
|
|
FoundChildNode(clientQuery, child.id, resultList);
|
|
}
|
|
}
|
|
}
|
|
}
|