private static void HandleHuoqiWithdraw(int userId, int projectId, decimal amount) { var context = new Agp2pDataContext(); // 找出所有需要赎回的债权,判断中间人的余额是否足够支付,并提醒中间人 var needTransferClaims = context.li_claims.Where(c => c.profitingProjectId == projectId && c.status == (int)Agp2pEnums.ClaimStatusEnum.NeedTransfer && !c.Children.Any()).ToList(); needTransferClaims.GroupBy(c => c.dt_users_agent).ToDictionary(g => g.Key, g => g.Sum(c => c.principal)).ForEach( pair => { var msgContent = $"有用户进行了活期转出,目前总转出金额为 {pair.Value},您的余额为 {pair.Key.li_wallets.idle_money},请于一日内保证账号内的余额足以赎回活期债权"; try { var errorMsg = string.Empty; if (!SMSHelper.SendTemplateSms(pair.Key.mobile, msgContent, out errorMsg)) { context.AppendAdminLogAndSave("Huoqi", $"发送活期转出提醒失败:{errorMsg},中间人:{pair.Key.GetFriendlyUserName()},短信内容:{msgContent}"); } } catch (Exception ex) { context.AppendAdminLogAndSave("Huoqi", $"发送活期转出提醒失败:{ex.GetSimpleCrashInfo()},中间人:{pair.Key.GetFriendlyUserName()},短信内容:{msgContent}"); } }); }
private static void HandleGainLoanerRepaymentSuccess(DateTime gainAt, int repaymentTaskId, int loanerUserId, decimal amount) { var context = new Agp2pDataContext(); var loaner = context.dt_users.Single(u => u.id == loanerUserId); var task = context.li_repayment_tasks.Single(r => r.id == repaymentTaskId); var repayTaskCount = task.li_projects.li_repayment_tasks.Count(ta => ta.status != (int)Agp2pEnums.RepaymentStatusEnum.Invalid); var smsContent = $"你已于 {gainAt.ToString("yyyy-MM-dd HH:mm")} 成功还款 {amount} 到项目{task.li_projects.title} 的第 {task.term}/{repayTaskCount} 期,包括本金:{task.repay_principal},利息:{task.repay_interest}"; try { var errorMsg = string.Empty; if (!SMSHelper.SendTemplateSms(loaner.mobile, smsContent, out errorMsg)) { context.AppendAdminLogAndSave("LoanerRepaySuccessHint", $"发送还款成功信息失败:{errorMsg}(借款人:{loaner.GetFriendlyUserName()},项目名称:{task.li_projects.title})"); } } catch (Exception ex) { context.AppendAdminLogAndSave("LoanerRepaySuccessHint", $"发送还款成功信息失败:{ex.GetSimpleCrashInfo()}(借款人:{loaner.GetFriendlyUserName()},项目名称:{task.li_projects.title})"); } }
private static void HandleProjectFinancingFailMsg(int projectId) { var context = new Agp2pDataContext(); var project = context.li_projects.Single(p => p.id == projectId); // 查出所有已经退款的投资者 TODO 排除自己退款的投资者 var investors = project.li_project_transactions.Where( ptr => ptr.type == (int)Agp2pEnums.ProjectTransactionTypeEnum.Invest && ptr.status == (int)Agp2pEnums.ProjectTransactionStatusEnum.Rollback) .GroupBy(ptr => ptr.dt_users).Select(g => g.Key); var sendTime = DateTime.Now; //找出模板 var smsModel = context.dt_sms_template.SingleOrDefault(te => te.call_index == "project_financing_fail"); if (smsModel == null) { throw new InvalidOperationException("找不到流标提醒模板: project_financing_fail"); } var msgContent = smsModel.content .Replace("{project}", project.title) .Replace("{date}", sendTime.ToString("yyyy-MM-dd HH:mm")); // 通知投资者项目流标 investors.ForEach(investor => { try { //发送站内消息 var userMsg = new dt_user_message { type = 1, post_user_name = "", accept_user_name = investor.user_name, title = smsModel.title, content = msgContent, post_time = sendTime, receiver = investor.id }; context.dt_user_message.InsertOnSubmit(userMsg); context.SubmitChanges(); var errorMsg = string.Empty; if (!SMSHelper.SendTemplateSms(investor.mobile, msgContent, out errorMsg)) { context.AppendAdminLogAndSave("ProjectFinancingFailSms", string.Format("发送项目流标提醒失败:{0}(客户ID:{1},项目名称:{2})", errorMsg, investor.user_name, project.title)); } } catch (Exception ex) { context.AppendAdminLogAndSave("ProjectFinancingFailSms", string.Format("发送项目流标提醒失败:{0}(客户ID:{1},项目名称:{2})", ex.GetSimpleCrashInfo(), investor.user_name, project.title)); } }); }
/// <summary> /// 放款 /// </summary> /// <param name="projectId"></param> private static void HandleProjectInvestCompletedMsg(int projectId) { //找出所有投资记录,计算收益(收益以还款记录为准,投资记录收益作为账单参考) var context = new Agp2pDataContext(); var project = context.li_projects.SingleOrDefault(p => p.id == projectId); Debug.Assert(project != null, "project != null"); //查询所有投资记录 var investTrans = project.li_project_transactions.Where( t => t.type == (int)Agp2pEnums.ProjectTransactionTypeEnum.Invest && t.status == (int)Agp2pEnums.ProjectTransactionStatusEnum.Success).ToList(); var finalProfitRate = project.GetFinalProfitRate(DateTime.Now); investTrans.ForEach(pt => { pt.interest = pt.principal * finalProfitRate; }); context.SubmitChanges(); //满标则发满标通知,否则发截标通知 var dtSmsTemplate = project.financing_amount == project.investment_amount ? context.dt_sms_template.FirstOrDefault(t => t.call_index == "project_financing_success") : context.dt_sms_template.FirstOrDefault(t => t.call_index == "project_financing_success_cut"); if (dtSmsTemplate == null) { return; } //发送通知给每个投资者 investTrans.Select(ptr => ptr.dt_users).Distinct().ForEach(user => { var msgContent = dtSmsTemplate.content.Replace("{date}", DateTime.Now.ToString("yyyy年MM月dd日")) .Replace("{project}", project.title); try { string errorMsg; if (!SMSHelper.SendTemplateSms(user.mobile, msgContent, out errorMsg)) { context.AppendAdminLogAndSave("WithdrawSms", "发送放款/截标通知失败:" + errorMsg + "(客户ID:" + user.user_name + ")"); } } catch (Exception ex) { context.AppendAdminLogAndSave("WithdrawSms", "发送放款/截标通知失败:" + ex.GetSimpleCrashInfo() + "(客户ID:" + user.user_name + ")"); } }); }
private static void SendChargeSuccessNotification(li_bank_transactions tr, bool sendUserMsg, bool sendSms) { var context = new Agp2pDataContext(); //短信通知 var charger = tr.dt_users; //找出模板 var dtSmsTemplate = context.dt_sms_template.FirstOrDefault(t => t.call_index == "user_recharge_info"); if (dtSmsTemplate == null) { return; } var siteConfig = ConfigLoader.loadSiteConfig(false); //替换模板内容 var msgContent = dtSmsTemplate.content.Replace("{amount}", tr.value.ToString()) .Replace("{webtel}", siteConfig.webtel); if (sendSms) { try { string errorMsg; if (!SMSHelper.SendTemplateSms(charger.mobile, msgContent, out errorMsg)) { context.AppendAdminLogAndSave("ReChargeSms", "发送充值提醒失败:" + errorMsg + "(客户ID:" + charger.user_name + ",订单号:" + tr.no_order + ")"); } } catch (Exception ex) { context.AppendAdminLogAndSave("ReChargeSms", "发送充值提醒失败:" + ex.GetSimpleCrashInfo() + "(客户ID:" + charger.user_name + ",订单号:" + tr.no_order + ")"); } } if (sendUserMsg) { var message = new dt_user_message { type = 1, accept_user_name = charger.user_name, content = msgContent, receiver = charger.id, title = dtSmsTemplate.title, post_time = tr.transact_time.GetValueOrDefault(tr.create_time) }; context.dt_user_message.InsertOnSubmit(message); context.SubmitChanges(); } }
private static void sendWithdrawApplyNotification(li_bank_transactions tr, bool sendSms, bool sendUserMsg) { var context = new Agp2pDataContext(); //短信通知 var withdrawer = tr.li_bank_accounts.dt_users; //找出模板 var dtSmsTemplate = context.dt_sms_template.FirstOrDefault(t => t.call_index == "user_withdraw_info"); if (dtSmsTemplate == null) { return; } //替换模板内容 var msgContent = dtSmsTemplate.content.Replace("{amount}", tr.value.ToString()) //.Replace("{user_name}", withdrawer.user_name) .Replace("{date}", tr.create_time.ToString("yyyy-MM-dd HH:mm")); if (sendSms) { try { string errorMsg; if (!SMSHelper.SendTemplateSms(withdrawer.mobile, msgContent, out errorMsg)) { context.AppendAdminLogAndSave("WithdrawSms", "发送提现通知失败:" + errorMsg + "(客户ID:" + withdrawer.user_name + ",订单号:" + tr.no_order + ")"); } } catch (Exception ex) { context.AppendAdminLogAndSave("WithdrawSms", "发送提现通知失败:" + ex.GetSimpleCrashInfo() + "(客户ID:" + withdrawer.user_name + ",订单号:" + tr.no_order + ")"); } } if (sendUserMsg) { var message = new dt_user_message { type = 1, accept_user_name = withdrawer.user_name, content = msgContent, receiver = withdrawer.id, title = dtSmsTemplate.title, post_time = tr.transact_time.GetValueOrDefault(tr.create_time) }; context.dt_user_message.InsertOnSubmit(message); context.SubmitChanges(); } }
private static void HandleDelayInvest(int projectTransactionId, DateTime investTime) { var context = new Agp2pDataContext(); var agent = context.dt_users.FirstOrDefault(u => u.dt_user_groups.title == AutoRepay.AgentGroup); try { if (agent == null) { throw new InvalidOperationException("没有找到中间人组,不能发送提醒短信"); } if (string.IsNullOrWhiteSpace(agent.mobile)) { throw new InvalidOperationException("中间人没有设置手机,不能发送提醒短信"); } var ptr = context.li_project_transactions.Single(ptr0 => ptr0.id == projectTransactionId); var huoqiBuyableClaimsAmount = TransactionFacade.QueryHuoqiBuyableClaimsAmount(context, ptr.li_projects, agent.id); var delayInvested = ptr.li_projects.li_project_transactions.Where( tr => tr.type == (int)Agp2pEnums.ProjectTransactionTypeEnum.Invest && tr.status == (int)Agp2pEnums.ProjectTransactionStatusEnum.Pending) .Aggregate(0m, (sum, tr) => sum + tr.principal); var msgContent = $"用户总共投资了活期项目 {ptr.li_projects.title} {delayInvested.ToString("c")},但活期债权本金总额({huoqiBuyableClaimsAmount.ToString("c")})不足,请尽快处理"; var errorMsg = string.Empty; if (!SMSHelper.SendTemplateSms(agent.mobile, msgContent, out errorMsg)) { context.AppendAdminLogAndSave("Agent", "发送提醒中间人买入债权短信失败:" + errorMsg); } else { context.AppendAdminLogAndSave("Agent", "发送提醒中间人买入债权短信成功:" + msgContent); } } catch (Exception ex) { context.AppendAdminLogAndSave("Agent", "发送提醒中间人买入债权短信失败:" + ex.GetSimpleCrashInfo()); } }
public static void DoRepay(TimerMsg.Type timerType, bool onTime) { if (timerType != TimerMsg.Type.AutoRepayTimer) { return; } if (ConfigLoader.loadSiteConfig().enableAutoRepay == 0) { return; } var context = new Agp2pDataContext(); var shouldRepayTask = context.li_repayment_tasks.Where( t => t.status == (int)Agp2pEnums.RepaymentStatusEnum.Unpaid && t.should_repay_time.Date <= DateTime.Today).ToList(); if (!shouldRepayTask.Any()) { return; } // 优先进行特殊项目的回款 shouldRepayTask.OrderByDescending(t => t.li_projects.dt_article_category.sort_id).ForEach(ta => { //TODO 特殊项目回款处理 //if (ta.li_projects.IsNewbieProject()) //{ // context.ExecuteRepaymentTask(ta.id); //} //else //调用托管本息到账接口,在本息到账异步响应中执行还款计划 RequestApiHandle.SendReturnPrinInte(ta.project, (ta.repay_interest + ta.repay_principal).ToString("f"), ta.id, false, ta.li_projects.IsHuoqiProject()); }); context.AppendAdminLogAndSave("AutoRepay", "今日待还款项目自动还款:" + shouldRepayTask.Count); // 活期项目不发兑付公告 SendRepayNotice(shouldRepayTask.Where(t => !t.li_projects.IsHuoqiProject()).ToList(), context); }
/// <summary> /// 新手标第一期自动返10元(停用) /// </summary> /// <param name="timerName"></param> /// <param name="onTime"></param> private static void HandleTimerMsg(TimerMsg.Type timerName, bool onTime) { if (timerName != TimerMsg.Type.AutoRepayTimer) { return; } var context = new Agp2pDataContext(); var shouldRepayTask = context.li_repayment_tasks.Where( t => t.only_repay_to != null && (t.status == (int)Agp2pEnums.RepaymentStatusEnum.Unpaid || t.status == (int)Agp2pEnums.RepaymentStatusEnum.OverTime) && t.should_repay_time.Date <= DateTime.Today).ToList(); if (!shouldRepayTask.Any()) { return; } shouldRepayTask.ForEach(ta => context.ExecuteRepaymentTask(ta.id)); context.AppendAdminLogAndSave("AutoRepay", "新手体验标自动还款:" + string.Join(", ", shouldRepayTask.Select(t => t.dt_users.user_name).ToArray())); }
/// <summary> /// 发布当天的兑付公告 /// </summary> /// <param name="tasks"></param> /// <param name="context"></param> public static void SendRepayNotice(List <li_repayment_tasks> tasks, Agp2pDataContext context) { //找到兑付公告模板 var temp = context.dt_mail_template.SingleOrDefault(te => te.call_index == "project_repay"); if (temp != null) { //构造兑付项目表格 var tableTemplate = "<table class='table table-bordered'><tbody><tr><th>序号</th><th>项目类别</th><th>项目名称</th><th>返回金额(元)</th><th>返回本金(元)</th><th>返回收益(元)</th></tr>{tr}</tbody></table>"; var trTemplate = "<tr><td>{no}</td><td>{project_type}</td><td>{project_name}</td><td>{amount}</td><td>{principal}</td><td>{interest}</td></tr>"; var trAll = Enumerable.Range(0, tasks.Count).Select(i => { var t = tasks[i]; return(trTemplate.Replace("{no}", (i + 1).ToString()) .Replace("{project_type}", t.li_projects.dt_article_category.title) .Replace("{project_name}", t.li_projects.title) .Replace("{amount}", (t.repay_principal + t.repay_interest).ToString("N")) .Replace("{principal}", t.repay_principal.ToString("N")) .Replace("{interest}", t.repay_interest.ToString("N"))); }); var tableContent = tableTemplate.Replace("{tr}", string.Join("", trAll)); var siteConfig = ConfigLoader.loadSiteConfig(); var addTime = DateTime.Now; var content = temp.content.Replace("{today}", addTime.ToString("yyyy-MM-dd")) .Replace("{count}", tasks.Count.ToString()) .Replace("{table}", tableContent) .Replace("{webtel}", siteConfig == null ? "" : siteConfig.webtel); //创建公告 try { var title = addTime.ToString("yyyy年M月d日") + "项目兑付公告"; var notice = new dt_article { add_time = addTime, category_id = 43, channel_id = 5, title = title, seo_title = title, seo_keywords = "安广融合p2p,项目兑付公告", content = content }; var noticeAttr = new dt_article_attribute_value { dt_article = notice, author = "安广融合", source = "安广融合理财平台" }; context.dt_article.InsertOnSubmit(notice); context.dt_article_attribute_value.InsertOnSubmit(noticeAttr); context.SubmitChanges(); } catch (Exception ex) { context.AppendAdminLogAndSave("AutoRepay", "发送兑付公告失败:" + ex.Message); } } }
private static void HandleTimerMessage(TimerMsg.Type timerType, bool onTime) { if (timerType != TimerMsg.Type.AutoRepayTimer) { return; } // 安广融合借款人还款提醒:您的借款项目【{project}】第 {termNumber} 期{remainDays}天后将到期,本期应还本金 {principal} 加利息 {interest} 共计 {total}。 var context = new Agp2pDataContext(); var willRepayTasks = context.li_repayment_tasks.Where( t => (t.should_repay_time.Date == DateTime.Today.AddDays(3) || t.should_repay_time.Date == DateTime.Today.AddDays(1)) && t.status == (int)Agp2pEnums.RepaymentStatusEnum.Unpaid).ToList(); if (!willRepayTasks.Any()) { return; } var smsTemplate = context.dt_sms_template.SingleOrDefault(te => te.call_index == "loaner_repay_hint")?.content; if (smsTemplate == null) { context.AppendAdminLogAndSave("LoanerRepayHint", "找不到还款提醒模板: loaner_repay_hint"); smsTemplate = "您的借款项目【{project}】第 {termNumber} 期{remainDays}天后将到期,本期应还本金 {principal} 加利息 {interest} 共计 {total}。"; } willRepayTasks.ForEach(task => { var loaner = task.li_projects.li_risks.li_loaners.dt_users; if (string.IsNullOrEmpty(loaner.mobile)) { return; } // 判断一天内有没有发送过短信 var alreadySend = 1 <= context.QueryEventTimesDuring(loaner.id, Agp2pEnums.EventRecordTypeEnum.LoanerRepaymentRemind, TimeSpan.FromDays(1), task.id.ToString()); if (alreadySend) { return; } var smsContent = smsTemplate .Replace("{remainDays}", (task.should_repay_time.Date - DateTime.Today).TotalDays.ToString("n0")) .Replace("{project}", task.li_projects.title) .Replace("{termNumber}", task.term.ToString()) .Replace("{principal}", task.repay_principal.ToString("c")) .Replace("{interest}", task.repay_interest.ToString("c")) .Replace("{total}", (task.repay_principal + task.repay_interest).ToString("c")); try { var errorMsg = string.Empty; if (!SMSHelper.SendTemplateSms(loaner.mobile, smsContent, out errorMsg)) { context.AppendAdminLogAndSave("LoanerRepayHint", $"发送还款提醒失败:{errorMsg}(借款人ID:{loaner.user_name},项目名称:{task.li_projects.title})"); } else { context.MarkEventOccurNotSave(loaner.id, Agp2pEnums.EventRecordTypeEnum.LoanerRepaymentRemind, DateTime.Now, task.id.ToString()); context.SubmitChanges(); } } catch (Exception ex) { context.AppendAdminLogAndSave("LoanerRepayHint", $"发送还款提醒失败:{ex.GetSimpleCrashInfo()}(借款人ID:{loaner.user_name},项目名称:{task.li_projects.title})"); } }); }
private static void HandleProjectRepaidMsg(int repaymentTaskId) { if (ConfigLoader.loadSiteConfig().sendShortMsgAfterRepay != 1) { return; } var context = new Agp2pDataContext(); var repayTask = context.li_repayment_tasks.Single(r => r.id == repaymentTaskId); var transactions = context.li_project_transactions.Where(t => t.project == repayTask.project && t.type == (int)Agp2pEnums.ProjectTransactionTypeEnum.RepayToInvestor && t.create_time == repayTask.repay_at).ToLookup(ptr => ptr.dt_users); transactions.ForEach(group => { var repayToUser = group.Key; var repayPrincipal = group.Sum(tr => tr.principal); var repayInterest = group.Sum(tr => tr.interest.GetValueOrDefault()); var now = DateTime.Now; // 检测用户是否接收放款的通知 var sendNotificationSettings = context.li_notification_settings.Where(n => n.user_id == repayToUser.id) .Select(n => n.type).Cast <Agp2pEnums.DisabledNotificationTypeEnum>(); try { //找出模板 var smsModel = 0 < repayPrincipal ? context.dt_sms_template.SingleOrDefault(te => te.call_index == "user_repay_all_info") : context.dt_sms_template.SingleOrDefault(te => te.call_index == "user_repay_info"); if (smsModel == null) { throw new InvalidOperationException("找不到放款提醒模板: user_repay_all_info 或 user_repay_info"); } //发送短信 var msgContent = smsModel.content //.Replace("{user_name}", t.dt_users.user_name) .Replace("{project_name}", repayTask.li_projects.title) .Replace("{amount}", (repayPrincipal + repayInterest).ToString()); if (!sendNotificationSettings.Contains(Agp2pEnums.DisabledNotificationTypeEnum.ProjectRepaidForUserMsg)) { //发送站内消息 var userMsg = new dt_user_message { type = 1, post_user_name = "", accept_user_name = repayToUser.user_name, title = smsModel.title, content = msgContent, post_time = now, receiver = repayToUser.id }; context.dt_user_message.InsertOnSubmit(userMsg); context.SubmitChanges(); } if (!sendNotificationSettings.Contains(Agp2pEnums.DisabledNotificationTypeEnum.ProjectRepaidForSms)) { var errorMsg = string.Empty; if (!SMSHelper.SendTemplateSms(repayToUser.mobile, msgContent, out errorMsg)) { context.AppendAdminLogAndSave("RepaymentSms", $"发送放款提醒失败:{errorMsg}(客户ID:{repayToUser.user_name},项目名称:{repayTask.li_projects.title})"); } } } catch (Exception e) { context.AppendAdminLogAndSave("RepaymentSms", $"发送放款提醒失败:{e.GetSimpleCrashInfo()}(客户ID:{repayToUser.user_name},项目名称:{repayTask.li_projects.title})"); } }); }
/// <summary> /// 重新激活项目 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void btnActivate_OnClick(object sender, EventArgs e) { if (string.IsNullOrEmpty(txt_financing_add_day.Text.Trim())) { JscriptMsg("请输入募集顺延天数!", "back", "Error"); return; } var project = LqContext.li_projects.SingleOrDefault(p => p.id == ProjectId); if (project != null) { try { //ChkAdminLevel("loan_financing", DTEnums.ActionEnum.Delete.ToString()); project.status = (int)Agp2pEnums.ProjectStatusEnum.Financing; project.financing_day = (short)(int.Parse(txt_financing_add_day.Text) + DateTime.Now.Subtract((DateTime)project.publish_time).Days); LqContext.SubmitChanges(); JscriptMsg("借款激活操作成功!", Utils.CombUrlTxt("loan_financing.aspx", "channel_id={0}&status={1}", this.ChannelId.ToString(), ((int)Agp2pEnums.ProjectStatusEnum.Financing).ToString())); //发送顺延通知短信 var dtSmsTemplate = LqContext.dt_sms_template.FirstOrDefault(t => t.call_index == "project_financing_add_day"); if (dtSmsTemplate != null) { project.li_project_transactions.Where( t => t.type == (int)Agp2pEnums.ProjectTransactionTypeEnum.Invest && t.status == (int)Agp2pEnums.ProjectTransactionStatusEnum.Success) .ToList() .ForEach(i => { var msgContent = dtSmsTemplate.content.Replace("{date}", DateTime.Now.ToString("yyyy年MM月dd日")) .Replace("{day}", txt_financing_add_day.Text) .Replace("{project}", i.li_projects.title); try { string errorMsg; if (!SMSHelper.SendTemplateSms(i.dt_users.mobile, msgContent, out errorMsg)) { LqContext.AppendAdminLogAndSave("WithdrawSms", "发送借款募集顺延通知失败:" + errorMsg + "(客户ID:" + i.dt_users.user_name + ")"); } } catch (Exception ex) { LqContext.AppendAdminLogAndSave("WithdrawSms", "发送借款募集顺延通知失败:" + ex.GetSimpleCrashInfo() + "(客户ID:" + i.dt_users.user_name + ")"); } }); } } catch (Exception ex) { JscriptMsg("借款激活操作失败:" + ex.Message, "back", "Error"); } } else { JscriptMsg("项目不存在或已被删除!", "back", "Error"); } }