using YLErp.BLL; namespace YLErp.Modules.ClientModule { /// /// 客户授信保存服务 /// public class CreditTableService : YLBaseService { public CreditTableService(OptUserInfo userInfo) : base(userInfo) { } /// /// 保存子公司给予客户的授信额度 /// public CreditTable SaveCredit(CreditTable req) { if (req.CreditDeadLine < req.CreditStartDate) { throw new ServiceException("授信起始日不能早于授信到期日"); } //原始授信值 × 最大授信可用比例(NULL按1) 折算出最终授信值; //OriginalCredit 为空时不触碰 Credit,维持手工授信值(存量兼容) //比例服务端校验 0-1(BUG-10:此前仅前端校验,绕过前端可存负值或>1放大授信) if (req.MaxCreditUseRatio.HasValue && (req.MaxCreditUseRatio.Value < 0 || req.MaxCreditUseRatio.Value > 1)) { throw new ServiceException("最大授信可用比例须在0-1之间"); } if (req.OriginalCredit.HasValue) { req.Credit = req.OriginalCredit.Value * (req.MaxCreditUseRatio ?? 1); } if (req.Credit > req.AuditCredit) { throw new ServiceException("授信额度不能大于审批额度"); } if (req.StockEqvNotional > req.AuditStockEqvNotional) { throw new ServiceException("名义本金规模不能大于名义本金审批规模"); } GetAvailableCreditQuota(req); CreditTable dbModel; var isAddNew = req.id == 0; var updateComments = false; DateTime? createDate = DateTime.Now; int? creatorId = UserInfo.UserId; var creatorName = UserInfo.UserName; if (isAddNew) { dbModel = new CreditTable() { OptId = UserInfo.UserId, OptName = UserInfo.UserName, OptDate = DateTime.Now }; DbContext.credit.Add(dbModel); } else { dbModel = DbContext.credit.Find(req.id); if (dbModel == null) { throw new ServiceException("数据已不存在"); } updateComments = dbModel.Credit == req.Credit && dbModel.OriginalCredit == req.OriginalCredit && dbModel.MaxCreditUseRatio == req.MaxCreditUseRatio && dbModel.PFECredit == req.PFECredit && dbModel.IMCredit == req.IMCredit && dbModel.AuditCredit == req.AuditCredit && dbModel.MarginLimit == req.MarginLimit && dbModel.StockEqvNotional == req.StockEqvNotional && dbModel.AuditStockEqvNotional == req.AuditStockEqvNotional && dbModel.DeductStockEqvNotional == req.DeductStockEqvNotional && dbModel.CreditDeadLine == req.CreditDeadLine && dbModel.CreditStartDate == req.CreditStartDate && (dbModel.VarietyId ?? "") == (req.VarietyId ?? "") && dbModel.Type == req.Type && (dbModel.RoleId ?? -1) == (req.RoleId ?? -1) && dbModel.IsAll == (req.IsAll ?? false) && dbModel.IsVariety == (req.IsVariety ?? false) && dbModel.IsWhitelist == req.IsWhitelist; createDate = dbModel.CreateDate; creatorId= dbModel.CreatorId; creatorName= dbModel.CreatorName; } if (updateComments) { dbModel.Comments = req.Comments; DbContext.SaveChanges(); return dbModel; } UpdateChanges(dbModel, req); dbModel.CreatorName = creatorName; dbModel.CreatorId = creatorId; dbModel.CreateDate = createDate; if (dbModel.Type == CreditTable.ClientType) { //设置客户编号 var client = ClientDataQueryService.GetClient(dbModel.ClientId ?? 0, true); dbModel.ClientNumber = client.Number; dbModel.ClientName = client.Name; var query = from credit in DbContext.credit where credit.ClientId == dbModel.ClientId && credit.id != req.id && (credit.CreditDeadLine == null || !(req.CreditStartDate > credit.CreditDeadLine || req.CreditDeadLine < credit.CreditStartDate)) select credit; if (query.ToList().Any()) { throw new ServiceException("同一客户授信有效时间不能重合,请检查该客户已存在的授信记录"); } if (new ClientRatingService(UserInfo).IsCreditOverTheCreditLine(dbModel)) { throw new ServiceException("客户授信申请额度不能超过资信等级额度"); } } else if (dbModel.Type == CreditTable.RoleType) { if (isAddNew) { var cre = DbContext.credit.FirstOrDefault(c => c.Type == CreditTable.RoleType && c.RoleId == dbModel.RoleId); if (cre != null) { dbModel = cre; } } else { var exists = DbContext.credit.Where(c => c.id != dbModel.id && c.Type == CreditTable.RoleType && c.RoleId == dbModel.RoleId).ToArray(); if (exists.Any()) { DbContext.credit.RemoveRange(exists); } } } SetDBModelOpt(dbModel); if (req.IsAll == null) { req.IsAll = false; } dbModel.IsAll = req.IsAll; if (req.IsVariety == null) { req.IsVariety = false; } //设置品种 dbModel.VarietyId = req.VarietyId.TrimToEmpty(); if (req.IsAll == true) { dbModel.VarietyName = "全部"; } else if (dbModel.VarietyId.Length > 0) { var varityIds = req.VarietyId.Split(',').Select(v => Convert.ToInt32(v)).ToList(); var varieties = VarietyBLL.GetAllvarietyModel().Where(v => varityIds.Contains(v.id)).Select(v => v.VarietyName); dbModel.VarietyName = string.Join(",", varieties); } else { dbModel.VarietyName = ""; } dbModel.IsVariety = req.IsVariety; dbModel.OptDate = DateTime.Now; dbModel.ProcessStatus = "未审批"; dbModel.ProcessOrderId = 0; dbModel.ProcessOptDate = DateTime.Now; dbModel.Comments = req.Comments ?? ""; //如果是为交易员角色设置交易品种,则一定是白名单 if (req.Type == CreditTable.RoleType) { dbModel.IsWhitelist = 1; } DbContext.SaveChanges(); new ClientCreditService(UserInfo).CreditLog(dbModel.id, isAddNew ? "新增授信" : "修改授信"); return dbModel; } private Tuple GetParentClient(int clientId) { using (var clientDb = DbContextFactory.GetClientDbContext(OptUser)) { var query = from c in clientDb.client join cp in clientDb.client on c.ParentId equals cp.id where c.id == clientId select new { cp.id, cp.Name }; var data = query.FirstOrDefault(); return data == null ? null : Tuple.Create(data.id, data.Name); } } /// /// 根据区间时间查询授信 /// public List GetParentCredits(CreditTable req) { var parentClient = GetParentClient(req.ClientId ?? 0); if (parentClient != null) { (var parentId, var parentName) = parentClient; var parentCredit = DbContext.credit.Where(a => a.ClientId == parentId && ((a.CreditStartDate <= req.CreditDeadLine && a.CreditDeadLine >= req.CreditDeadLine) || (a.CreditStartDate <= req.CreditStartDate && a.CreditDeadLine >= req.CreditStartDate))); return parentCredit.ToList(); } return new List(); } /// /// 可用授信额度 /// /// /// public void GetAvailableCreditQuota(CreditTable req) { var parentCredits = GetParentCredits(req); if (parentCredits.Count == 0) { return; } var chlidClients = ClientDataQueryService.GetChlidClientIdsByParentId(parentCredits[0].ClientId ?? 0); List chlidCredit = null; if (chlidClients.Any()) { chlidCredit = DbContext.credit.Where(a => chlidClients.Contains((int)a.ClientId) && ((a.CreditStartDate <= req.CreditDeadLine && a.CreditDeadLine >= req.CreditDeadLine) || (a.CreditStartDate <= req.CreditStartDate && a.CreditDeadLine >= req.CreditStartDate)) ).ToList(); } if (chlidCredit == null || chlidCredit.Count == 0) { foreach (var parent in parentCredits) { if (parent.Credit < (req.Credit ?? 0)) { throw new ServiceException($"当前母公司【{parent.ClientName}】可用授信额度为【{parent.Credit}】,子公司授信额度之和不能大于母公司可用额度"); } } return; } var dates = chlidCredit .Select(O => O.CreditStartDate) .Concat(chlidCredit.Select(O => O.CreditDeadLine)) .Concat(parentCredits.Select(O => O.CreditStartDate)) .Concat(parentCredits.Select(O => O.CreditDeadLine)) .Concat(new[] { req.CreditStartDate, req.CreditDeadLine }) .OrderBy(O => O) .ToHashSet(); foreach (var date in dates) { var parent = parentCredits.Where(O => O.CreditStartDate <= date && O.CreditDeadLine >= date).FirstOrDefault(); if (parent == null) { continue; } var chlid = chlidCredit.Where(O => O.CreditStartDate <= date && O.CreditDeadLine >= date); double chlidCreditSum = 0, creditQuota = 0; if (chlid.Any()) { chlidCreditSum = chlid.Sum(a => a.Credit ?? 0); } creditQuota = (parent.Credit ?? 0) - chlidCreditSum; if (creditQuota < (req.Credit ?? 0)) { throw new ServiceException($"当前母公司【{parent.ClientName}】可用授信额度为【{creditQuota}】,子公司授信额度之和不能大于母公司可用额度"); } } } } }