Email Report engine
来源:互联网 发布:php字符串默认编码 编辑:程序博客网 时间:2024/05/22 10:28
code
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Diagnostics;using System.Linq;using System.Linq.Expressions;using System.ServiceProcess;using System.Text;using EmailAlerts.Service.Properties;using System.Net.Mail;using DAL.findahome;using System.Data.Linq;using System.IO;using System.Transactions;using TargetState = DAL.findahome.InOut_Target.States;using KeyState = DAL.findahome.InOut_Key.States;using System.Threading;using System.Globalization;using System.Net.Mime;namespace EmailAlerts.Service{ partial class Engine : ServiceBase { BedroomList emptyBedroomList = new BedroomList(); Agent emptyAgent = new Agent() { idOffice = -1 }; SmtpClient smtpClient = new SmtpClient(); AgentContactFrequency defaultPeriod = new AgentContactFrequency() { LastSent = DateTime.Today.AddDays(-8), Frequency = 7 }; BedroomList bedroomList = new BedroomList(); PropertyHit propertyHit = new PropertyHit() { Emails = 0, Hits = 0 }; EmailComparer emailComparer = new EmailComparer(); public Engine() { InitializeComponent(); } protected override void OnStart(string[] args) { Process.GetCurrentProcess().PriorityClass = Settings.Default.Priority; this.Pulse.Enabled = true;#if DEBUG this.Pulse.Interval = 20000;#else this.Pulse.Interval = Settings.Default.Pulse.TotalMilliseconds;#endif } protected override void OnStop() { this.Pulse.Enabled = false; } private void Pulse_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { this.Pulse.Enabled = false; Thread.CurrentThread.CurrentCulture = new CultureInfo("en-IE"); // Control Sent in the Morning DateTime dt = DateTime.Now; if (dt.Hour > 6 && dt.Hour < 9) { if (Settings.Default.ApplicantAlertsOn) { ProcessApplicantAlerts(); } if (Settings.Default.AgentAlertsOn) { ProcessAgentAlerts(); } } Trace.Flush(); this.Pulse.Enabled = true; } private void ProcessAgentAlerts() { try { var now = DateTime.Now; var dlo = new DataLoadOptions(); dlo.LoadWith<Agency>(c => c.User); dlo.LoadWith<AgencyOffice>(c => c.Agency); dlo.LoadWith<AgencyOffice>(c => c.Agents); dlo.LoadWith<Agent>(c => c.AgentContactFrequency); dlo.LoadWith<Agent>(c => c.User); dlo.LoadWith<Property>(c => c.AlertContents); dlo.LoadWith<Property>(c => c.Frequency); dlo.LoadWith<Property>(c => c.PropMarket); dlo.LoadWith<Property>(c => c.PropertyType); dlo.LoadWith<Property>(c => c.PropertyHits); dlo.LoadWith<Property>(c => c.District); dlo.LoadWith<Property>(c => c.CountyCity); dlo.LoadWith<Property>(c => c.Country); using (var dc = new findahomeDataContext() { CommandTimeout = 600, LoadOptions = dlo }) {#if DEBUG dc.Log = new StreamWriter(@"\linq2sql.log") { AutoFlush = true };#endif var officeCollection = (from office in dc.AgencyOffices from agent in office.Agents let report = (agent.AgentContactFrequency ?? defaultPeriod) where report.Frequency != Settings.Default.Unsubscribe && now >= (report.LastSent ?? now.AddYears(-report.Frequency)).AddDays(report.Frequency) && agent.User.Properties.Any(e => e.idCountry == 1/*only properties from Ireland*/ && e.idCRule == Settings.Default.Active && e.idPropMarket != Settings.Default.CollegeMarket || e.idCRule == Settings.Default.Agreed) && agent.User.idCountry == 1 //only agent who have address Ireland //********************** Test for martin********** //&& agent.User.idUser == 32158 // martin's office account && agent.AgencyOffice.Agency.idAffiliation == 3 // all the account that belong to IPAV //&& agent.User.idUser == 65276 // kidd's personal test account //************************************************ select office).Take(300) .ToArray(); var exportTargetCollection = dc.InOut_Targets.Where(c => c.State == TargetState.OutOn).ToArray(); var template = dc.InOut_Target_Contents.Where(c => c.Website_Id == Settings.Default.fourpmWebsiteId).ToList(); // template.ForEach(delegate(InOut_Target_Content c) { c.Text = Uri.UnescapeDataString(c.Text); }); var onstyle = template.First(c => c.Name.Equals(Settings.Default.propertyreport_onstyle)).Text; foreach (var office in officeCollection) { try { var publisherCollection = office.Agents.Where(c => c.User.Properties.Any(e => e.idCRule == Settings.Default.Active || e.idCRule == Settings.Default.Agreed && e.idPropMarket != Settings.Default.CollegeMarket)).ToArray(); var marketCollection = new StringBuilder(); var marketCounter = 0; var propertyCollection = new StringBuilder(); var currentMarket = string.Empty; var currentOwner = string.Empty; var odd = false; var propCounter = 0; foreach (var p in publisherCollection.SelectMany(d => d.User.Properties.Where(c => c.idCRule == Settings.Default.Active || c.idCRule == Settings.Default.Agreed && c.idPropMarket != Settings.Default.CollegeMarket)).OrderBy(c => c.PropMarket.MarketName).ThenBy(c => c.idCreatedBy).ThenByDescending(c => c.ModifyDate)) { if (currentMarket != p.PropMarket.MarketName) { currentMarket = p.PropMarket.MarketName; propertyCollection.AppendFormat(template.First(c => c.Name.Equals(Settings.Default.propertyreport_marketline)).Text, p.idPropMarket, currentMarket); marketCollection.AppendFormat(template.First(c => c.Name.Equals(Settings.Default.propertyreport_marketindex)).Text, p.idPropMarket, currentMarket); marketCounter++; odd = false; if (currentOwner != p.User.Name) { currentOwner = p.User.Name; } propertyCollection.AppendFormat(template.First(c => c.Name.Equals(Settings.Default.propertyreport_publisherline)).Text, currentOwner); } if (currentOwner != p.User.Name) { currentOwner = p.User.Name; propertyCollection.AppendFormat(template.First(c => c.Name.Equals(Settings.Default.propertyreport_publisherline)).Text, currentOwner); } var expire = p.ModifyDate.Add(p.PropMarket.StatusGroup == PropMarket.StatusGroupVariant.Sales ? Settings.Default.SaleExpiration : Settings.Default.LetExpiration); expire = expire < p.ExpiryDate ? p.ExpiryDate : expire; var expiredays = (expire - now).Days; var pclass = expiredays <= 3 ? " color: #e00!important;" : string.Empty; var temp = 0; var size = currentMarket.ToLower().Contains("commercial") || currentMarket.ToLower().Contains("land") ? string.Format("<span>{0}</span> {1}", p.PropSize > 0 ? (Int32)p.PropSize : (Int32)p.PropSizeAcres, p.PropSize > 0 ? "SqM" : "Acr") : string.Format("<span>{0}</span> bed{1}", temp = (p.BedroomLists.FirstOrDefault() ?? bedroomList).TotalRooms, temp == 1 ? string.Empty : "s"); var price = string.Format("{0:c0} {1}", p.PriceVal, (p.PropMarket.StatusGroup == PropMarket.StatusGroupVariant.Sales ? string.Empty : p.Frequency.FrequencyName)); var pics = p.PictureAdded > 0 ? p.PropertyPictures.Count(c => (c.Thumbnail ?? 0) == 0) : 0; var hit = (p.PropertyHits ?? propertyHit); var alert = p.AlertContents.Count; int? num = null; propertyCollection.AppendFormat(template.First(c => c.Name.Equals(Settings.Default.propertyreport_propertyline)).Text, pclass + ((odd = !odd) ? " background-color: #F8F4F0;" : string.Empty), p.idList, //{0} //string.Format("{0}, {1}, {2}, {3}", p.DisplayAddress, p.District.DistrictName, p.CountyCity.CountyCityName, p.Country.CountryName).Trim(' ', '.', ','), p.DisplayAddress, size, p.PropertyType.PTypeName, price, num, pics == 0 ? string.Empty : pics.ToString() + "pics", //pics, //pics == 1 ? string.Empty : "s", // ********** response the john request, when hits & Email Equal 0, hidden it ************* //hit.Hits, num, hit.Hits == 0 ? string.Empty : hit.Hits.ToString() + " hits", //hit.Hits == 1 ? string.Empty : "s", num, // hit.Emails, hit.Emails == 0 ? string.Empty : hit.Emails.ToString() + " Emails", // hit.Emails == 1 ? string.Empty : "s", // ***************************************************************************************** //alert, //alert == 1 ? string.Empty : "s", num, alert == 0 ? string.Empty : alert.ToString() + "alerts", p.ModifyDate, expiredays < 30 && expiredays > 0 ? string.Format(" {0} day{1}", expiredays, (Math.Abs(expiredays) > 1 ? "s" : string.Empty)) : string.Empty, string.Format("{0}.{1}", p.User.idUser, p.User.Key), //p.idPropMarket == 3 || p.idPropMarket == 8 || p.idPropMarket == 10 || p.idPropMarket == 11 || p.idPropMarket == 13 ? "Sale Agreed" : "Rent Agreed", p.idCRule == Settings.Default.Active ? p.idPropMarket == 3 || p.idPropMarket == 8 || p.idPropMarket == 10 || p.idPropMarket == 11 || p.idPropMarket == 13 ? String.Format(Settings.Default.PropertyRuleControl, string.Format("{0}.{1}", p.User.idUser, p.User.Key), p.idList, "agreed", Settings.Default.GreenColor, "Sale Agreed") : String.Format(Settings.Default.PropertyRuleControl, string.Format("{0}.{1}", p.User.idUser, p.User.Key), p.idList, "agreed", Settings.Default.GreenColor, "Rent Agreed") : p.idPropMarket == 3 || p.idPropMarket == 8 || p.idPropMarket == 10 || p.idPropMarket == 11 || p.idPropMarket == 13 ? String.Format(Settings.Default.PropertyRuleControl, string.Format("{0}.{1}", p.User.idUser, p.User.Key), p.idList, "close", Settings.Default.BlueColor, "Take Offline") : String.Format(Settings.Default.PropertyRuleControl, string.Format("{0}.{1}", p.User.idUser, p.User.Key), p.idList, "close", Settings.Default.BlueColor, "Take Offline"), string.Format("{0}, {1}, {2}", p.District.DistrictName, p.CountyCity.CountyCityName, p.Country.CountryName) //{18} ); propCounter++; } foreach (var p in (from p in publisherCollection let report = (p.AgentContactFrequency ?? defaultPeriod) where p.User.ValidEmail && report.Frequency != Settings.Default.Unsubscribe && now >= (report.LastSent ?? now.AddYears(-report.Frequency)).AddDays(report.Frequency) select p) .Distinct(emailComparer)) { var officeName = office.OfficeName.Trim(' ', '.', ','); var reportOwner = string.Format("{0}, {1} {2}", p.User.Name, officeName.Equals(office.Agency.User.Name, StringComparison.InvariantCultureIgnoreCase) ? string.Empty : officeName + ",", office.Agency.User.Name).Trim(' ', '.', ','); var body = new StringBuilder(); var exportCollection = new StringBuilder(); var key = string.Format("{0}.{1}", p.User.idUser, p.User.Key); foreach (var target in exportTargetCollection.OrderBy(c => c.Name)) { var tkey = p.User.InOut_Keys.FirstOrDefault(c => c.Target_Id == target.Id) ?? new InOut_Key() { Approved = !Settings.Default.DefaultClosedTargets.Contains(target.Id.ToString()), State = KeyState.Open }; var on = tkey.Approved && tkey.State == KeyState.Open ? onstyle : string.Empty; var off = string.IsNullOrEmpty(on) ? onstyle : string.Empty; exportCollection.AppendFormat(template.First(c => c.Name.Equals(Settings.Default.propertyreport_exportline)).Text, target.Name, key, target.Id, on, off); } //############################Template select function for Onview.ie############################################# if (p.AgencyOffice.Agency.idAffiliation.Equals(3)) { body.AppendFormat(template.First(c => c.Name.Equals(Settings.Default.propertyreport_template_onview)).Text, string.Empty, now, reportOwner, key, propertyCollection, marketCollection, marketCounter > 1 ? string.Empty : " display: none;"); } else { //body.AppendFormat(template.First(c => c.Name.Equals(Settings.Default.propertyreport_template_onview)).Text, string.Empty, now, reportOwner, key, exportCollection, propertyCollection, marketCollection, marketCounter > 1 ? string.Empty : " display: none;"); body.AppendFormat(template.First(c => c.Name.Equals(Settings.Default.propertyreport_template)).Text, string.Empty, now, reportOwner, key, exportCollection, propertyCollection, marketCollection, marketCounter > 1 ? string.Empty : " display: none;"); } //if(p.AgentContactFrequency.Template.Equals(0)) //{ // body.AppendFormat(template.First(c => c.Name.Equals(Settings.Default.propertyreport_template)).Text, string.Empty, now, reportOwner, key, exportCollection, propertyCollection, marketCollection, marketCounter > 1 ? string.Empty : " display: none;"); //} //else if (p.AgentContactFrequency.Template.Equals(1)) //{ // body.AppendFormat(template.First(c => c.Name.Equals(Settings.Default.propertyreport_template_onview)).Text, string.Empty, now, reportOwner, key, propertyCollection, marketCollection, marketCounter > 1 ? string.Empty : " display: none;"); //} //else //{ // body.AppendFormat(template.First(c => c.Name.Equals(Settings.Default.propertyreport_template)).Text, string.Empty, now, reportOwner, key, exportCollection, propertyCollection, marketCollection, marketCounter > 1 ? string.Empty : " display: none;"); //} //#################################################################################################################### var report = new MailMessage(Settings.Default.ReportEmail,#if DEBUG "kidd@4pm.ie,michael@4pm.ie,john@4pm.ie",#else//"kidd@4pm.ie", p.User.UserEmail,#endif string.Format(template.First(c => c.Name.Equals(Settings.Default.propertyreport_subject)).Text, propCounter), body.ToString()) { IsBodyHtml = true }; report.Bcc.Add(Settings.Default.ReportEmail); report.ReplyTo = new MailAddress(template.First(c => c.Name.Equals(Settings.Default.propertyreport_replyto)).Text); smtpClient.Send(report);#if !DEBUG if (p.AgentContactFrequency == null) { dc.AgentContactFrequencies.InsertOnSubmit(new AgentContactFrequency() { AgentId = p.idAgent, Frequency = 7, LastSent = now }); } else { p.AgentContactFrequency.LastSent = now; } dc.SubmitChanges();#endif } } catch (Exception ex) { Trace.TraceWarning("OfficeId={0}, err: {1}", office.idOffice, ex); } }#if DEBUG dc.Log.Close();#endif } } catch (Exception ex) { Trace.TraceError(ex.ToString()); } } private void ProcessApplicantAlerts() { try { var dlo = new DataLoadOptions(); dlo.LoadWith<Property>(c => c.PropertyPictures); dlo.AssociateWith<Property>(c => c.PropertyPictures.Where(d => (d.Thumbnail ?? 0) == 1)); dlo.LoadWith<Property>(c => c.Country); dlo.LoadWith<Property>(c => c.CountyCity); dlo.LoadWith<Property>(c => c.LivingType); dlo.LoadWith<Property>(c => c.PropertyType); dlo.LoadWith<Property>(c => c.PropMarket); dlo.LoadWith<Property>(c => c.User); dlo.LoadWith<User>(c => c.Agents); dlo.LoadWith<Property>(c => c.District); dlo.LoadWith<AlertRequest>(c => c.Applicant); dlo.LoadWith<AlertRequest>(c => c.User); dlo.LoadWith<AlertRequest>(c => c.Country); dlo.LoadWith<AlertRequest>(c => c.CountyCity); dlo.LoadWith<AlertRequest>(c => c.District); dlo.LoadWith<AlertRequest>(c => c.DistrictGroup); dlo.LoadWith<AlertRequest>(c => c.LetCategory); dlo.LoadWith<AlertRequest>(c => c.PropertyType); dlo.LoadWith<AlertRequest>(c => c.PropMarket); dlo.LoadWith<AlertRequest>(c => c.Site); dlo.LoadWith<AlertRequest>(c => c.InOut_Target); dlo.LoadWith<Applicant>(c => c.User); dlo.LoadWith<AgencyOfficeWebSite>(c => c.ClientWebSite); using (var dc = new findahomeDataContext() { LoadOptions = dlo, CommandTimeout = 600, }) {#if DEBUG dc.Log = new StreamWriter(@"\linq2sql.log") { AutoFlush = true };#endif var log = new AlertEngineLog(); var now = DateTime.Now; try { log.CalledBy = this.ServiceName; log.Date = DateTime.Now; log.Error = string.Empty; var currentAlertRequests = dc.AlertRequests.Where(c => c.Active && now >= (c.LastSend ?? c.CreatedDate).AddDays(c.Frequency ?? 0) && (c.Applicant.AllowEmail ?? c.Applicant.AllowSMS ?? c.Applicant.AllowMMS ?? c.idApplicant == 0) && c.Applicant.User != null//this check constraint must be set on the db level! ) .ToArray(); if (currentAlertRequests.Count() > 0) { var minDate = currentAlertRequests.Min(c => c.LastSend ?? c.CreatedDate); var properties = dc.Properties.Where(c => c.idCRule == 1 && c.CreatedDate >= minDate).ToArray(); var portalIds = currentAlertRequests.Select(c => c.idSite).Where(c => c.HasValue).Distinct().ToArray(); var officeIds = currentAlertRequests.Select(c => c.idOffice).Where(c => c.HasValue).Distinct().ToArray(); var agentIds = dc.Agents.Where(c => officeIds.Contains(c.idOffice)).Select(c => new { c.idOffice, c.idUser }).ToArray(); var officesTemplates = (from template in dc.gw_newsletter_templates join a in dc.Agents on template.UserId equals a.idAgent where officeIds.Contains(a.idOffice) && (template.Active ?? false) && template.idTemplateType == 1 select new { template, a.idOffice }) .ToArray(); var portalsTemplates = dc.gw_newsletter_templates.Where(c => (c.Active ?? false) && c.idTemplateType == 1 && portalIds.Contains(c.idSite)).ToArray(); var defaultTemplate = dc.gw_newsletter_templates.FirstOrDefault(c => (c.Locked ?? false) && c.idTemplateType == 1); var clientWebsites = dc.AgencyOfficeWebSites.Where(c => officeIds.Contains(c.idAgencyOffice)).Select(c => new { c.ClientWebSite, c.idAgencyOffice }).ToArray(); var portalWebsites = dc.Sites.ToArray(); foreach (var alertRequest in currentAlertRequests) { if (alertRequest.idApplicant != 0 && !alertRequest.Applicant.User.ValidEmail) { alertRequest.Active = false; alertRequest.LastSend = now; log.Error += string.Format("\nUser.Id {0} have invalid email '{1}'", alertRequest.Applicant.User.idUser, alertRequest.Applicant.User.UserEmail); dc.SubmitChanges(); continue;//bypass bad emails } else if (alertRequest.idApplicant == 0 && !alertRequest.User.ValidEmail) { alertRequest.Active = false; alertRequest.LastSend = now; log.Error += string.Format("\nUser.Id {0} have invalid email '{1}'", alertRequest.User.idUser, alertRequest.User.UserEmail); dc.SubmitChanges(); continue;//bypass bad emails } if (alertRequest.InOut_Target_Id != 0)//new EmailAlerts.Client { var sentCollection = alertRequest.User.AlertRequests.SelectMany(a => a.Alerts.SelectMany(c => c.AlertContents.Select(d => d.idList))).Distinct().ToArray(); var ownerCollection = alertRequest.InOut_Target.Office_Id == 0 ? alertRequest.Website.Agency.AgencyOffices.SelectMany(c => c.Agents.Select(d => d.idUser)).ToList() : alertRequest.InOut_Target.Agency_Id == 0 ? alertRequest.Website.AgencyOffice.Agents.Select(d => d.idUser).ToList() : new List<int>() ; var propertiesToSend = (from c in properties let l = Compare(alertRequest, c) let t = c.AdTypeList.Length > alertRequest.InOut_Target.SiteIndex - 1 ? (int)c.AdTypeList[alertRequest.InOut_Target.SiteIndex - 1] != (int)Ad_TypeX.Variant.DontShow : false where ownerCollection.Contains(c.idCreatedBy) || t && !sentCollection.Contains(c.idList) && alertRequest.idPropertyMarket == c.idPropMarket && alertRequest.idPropertyType == c.idPType && alertRequest.idCountry == c.idCountry && (alertRequest.idCounty ?? c.idCountyCity) == c.idCountyCity && c.CreatedDate >= (alertRequest.LastSend ?? alertRequest.CreatedDate) && l >= Settings.Default.MinimumLikeness orderby string.Format("{0}.{1}", l, c.idList) descending select c) .Take(Settings.Default.PropertyLimit) .ToArray(); if (propertiesToSend.Count() > 0) { var header = alertRequest.InOut_Target.InOut_Target_Contents.FirstOrDefault(c => c.Name == Settings.Default.emailalert_header); var propertyline = alertRequest.InOut_Target.InOut_Target_Contents.FirstOrDefault(c => c.Name == Settings.Default.emailalert_propertyline); var footer = alertRequest.InOut_Target.InOut_Target_Contents.FirstOrDefault(c => c.Name == Settings.Default.emailalert_footer); var alert = new Alert() { Type = Alert.TypeVariant.Email, Request_Id = alertRequest.idRequest, SendDate = now, }; dc.Alerts.InsertOnSubmit(alert); var key = alertRequest.Applicant.User.Key; var body = new StringBuilder(@"<html xmlns=""http://www.w3.org/1999/xhtml""><head><title>email alert</title></head><body>"); body.AppendFormat(header.Text, now); foreach (var property in propertiesToSend) { //{0} - id property //{1} - main image src //{2} - address //{3} - property status //{4} - price //{5} - proprty type //{6} - part of description body.AppendFormat(propertyline.Text, property.idList, property.PropertyPictures.Any() ? string.Format("http://www.4pm.ie/ShowThumbnail.aspx?id={0}&img={1}", property.idList, Uri.EscapeDataString(property.PropertyPictures.First().PicPath)) : string.Empty, string.Format("{0}, {1}, {2}", property.DisplayAddress, property.District.DistrictName, property.CountyCity.CountyCityName), property.PropStatus.StatusName, property.PriceVal > 0 ? string.Format("{0:c0} {1}", property.PriceVal, property.PropMarket.StatusGroup == PropMarket.StatusGroupVariant.Rental /*show frequency for rental only*/ ? property.Frequency.FrequencyName : string.Empty) : "On request", string.Format("{0} {1}", property.PropertyType.PTypeName, property.LivingType.LTypeName.Equals("not applicable", StringComparison.InvariantCultureIgnoreCase) ? string.Empty : string.Format("({0})", property.LivingType.LTypeName)), property.Description.PadRight(300).Substring(0, 300).Trim() + "..." ) ; var alertContent = new AlertContent(); alertContent.Alert = alert; alertContent.idList = property.idList; dc.AlertContents.InsertOnSubmit(alertContent); } body.AppendFormat(footer.Text, string.Format("http://api.4pm.ie/alert.svc/{0}.{1}/unsubscribe", alertRequest.idRequest, key) ); body.Append(@"</body></html>"); var message = new MailMessage( string.Format("info@{0}", alertRequest.Website.Domain), alertRequest.Applicant.User.UserEmail, Settings.Default.EmailSubject, body.ToString()) { IsBodyHtml = true, }; message.Bcc.Add(Settings.Default.ReportEmail); smtpClient.Send(message); } log.NbAlertsSent++; } else if (alertRequest.Website_Id != 0)//new EmailAlerts.Client { var sentCollection = alertRequest.Applicant.AlertRequests.SelectMany(a => a.Alerts.SelectMany(c => c.AlertContents.Select(d => d.idList))).Distinct().ToArray(); var ownerCollection = alertRequest.Website.Office_Id == 0 ? alertRequest.Website.Agency.AgencyOffices.SelectMany(c => c.Agents.Select(d => d.idUser)).ToList() : alertRequest.Website.AgencyOffice.Agents.Select(d => d.idUser).ToList() ; var propertiesToSend = (from c in properties let l = Compare(alertRequest, c) where ownerCollection.Contains(c.idCreatedBy) && !sentCollection.Contains(c.idList) && alertRequest.idPropertyMarket == c.idPropMarket && alertRequest.idPropertyType == c.idPType && alertRequest.idCountry == c.idCountry && (alertRequest.idCounty ?? c.idCountyCity) == c.idCountyCity && c.CreatedDate >= (alertRequest.LastSend ?? alertRequest.CreatedDate) && l >= Settings.Default.MinimumLikeness orderby string.Format("{0}.{1}", l, c.idList) descending select c) .Take(Settings.Default.PropertyLimit) .ToArray(); if ((alertRequest.Applicant.AllowEmail ?? false) && propertiesToSend.Count() > 0) { var header = alertRequest.Website.InOut_Target_Contents.FirstOrDefault(c => c.Name == Settings.Default.emailalert_header); var propertyline = alertRequest.Website.InOut_Target_Contents.FirstOrDefault(c => c.Name == Settings.Default.emailalert_propertyline); var footer = alertRequest.Website.InOut_Target_Contents.FirstOrDefault(c => c.Name == Settings.Default.emailalert_footer); var alert = new Alert() { Type = Alert.TypeVariant.Email, Request_Id = alertRequest.idRequest, SendDate = now, }; dc.Alerts.InsertOnSubmit(alert); var key = alertRequest.Applicant.User.Key; var body = new StringBuilder(@"<html xmlns=""http://www.w3.org/1999/xhtml""><head><title>email alert</title></head><body>"); body.AppendFormat(header.Text, now); foreach (var property in propertiesToSend) { //{0} - id property //{1} - main image src //{2} - address //{3} - property status //{4} - price //{5} - proprty type //{6} - part of description body.AppendFormat(propertyline.Text, property.idList, property.PropertyPictures.Any() ? string.Format("http://www.4pm.ie/ShowThumbnail.aspx?id={0}&img={1}", property.idList, Uri.EscapeDataString(property.PropertyPictures.First().PicPath)) : string.Empty, string.Format("{0}, {1}, {2}", property.DisplayAddress, property.District.DistrictName, property.CountyCity.CountyCityName), property.PropStatus.StatusName, property.PriceVal > 0 ? string.Format("{0:c0} {1}", property.PriceVal, property.PropMarket.StatusGroup == PropMarket.StatusGroupVariant.Rental /*show frequency for rental only*/ ? property.Frequency.FrequencyName : string.Empty) : "On request", string.Format("{0} {1}", property.PropertyType.PTypeName, property.LivingType.LTypeName.Equals("not applicable", StringComparison.InvariantCultureIgnoreCase) ? string.Empty : string.Format("({0})", property.LivingType.LTypeName)), property.Description.PadRight(300).Substring(0, 300).Trim() + "..." ) ; var alertContent = new AlertContent(); alertContent.Alert = alert; alertContent.idList = property.idList; dc.AlertContents.InsertOnSubmit(alertContent); } body.AppendFormat(footer.Text, string.Format("http://api.4pm.ie/alert.svc/{0}.{1}/unsubscribe", alertRequest.idRequest, key) ); body.Append(@"</body></html>"); var message = new MailMessage( string.Format("info@{0}", alertRequest.Website.Domain), alertRequest.Applicant.User.UserEmail, Settings.Default.EmailSubject, body.ToString()) { IsBodyHtml = true, }; message.Bcc.Add(Settings.Default.ReportEmail); smtpClient.Send(message); } log.NbAlertsSent++; } else//old EmailAlerts.Client TODO: remove {#if !DEBUG var sentList = alertRequest.Applicant.AlertRequests.SelectMany(a => a.Alerts.SelectMany(c => c.AlertContents.Select(d => d.idList))).Distinct().ToArray(); var relatedAlertRequestList = alertRequest.Applicant.AlertRequests.Where(a => a.Active && ((alertRequest.idSite.HasValue && a.idSite == alertRequest.idSite) || (alertRequest.idOffice.HasValue && a.idOffice == alertRequest.idOffice))).Select(a => a.idRequest).ToArray(); var ownerList = agentIds.Where(c => alertRequest.idOffice.HasValue && c.idOffice == alertRequest.idOffice).Select(c => c.idUser).Distinct().ToArray(); var propertiesToSend = (from c in properties let l = Compare(alertRequest, c) where ((alertRequest.idOffice.HasValue && ownerList.Contains(c.idCreatedBy)) || (alertRequest.idSite.HasValue)) && !sentList.Contains(c.idList) && alertRequest.idPropertyMarket == c.idPropMarket && alertRequest.idPropertyType == c.idPType && alertRequest.idCountry == c.idCountry && (alertRequest.idCounty ?? c.idCountyCity) == c.idCountyCity && c.CreatedDate >= (alertRequest.LastSend ?? alertRequest.CreatedDate) && l >= Settings.Default.MinimumLikeness && (alertRequest.idSite.HasValue || (alertRequest.idOffice ?? 0) == (c.User.Agents ?? emptyAgent).idOffice) orderby string.Format("{0}.{1}", l, c.idList) descending select c) .Take(Settings.Default.PropertyLimit) .ToArray(); if ((alertRequest.Applicant.AllowEmail ?? false) && propertiesToSend.Count() > 0) { var template = defaultTemplate; if (alertRequest.idSite.HasValue) { var tempTemplate = portalsTemplates.FirstOrDefault(c => c.idSite == alertRequest.idSite); if (tempTemplate != null) template = tempTemplate; } else if (alertRequest.idOffice.HasValue) { var tempTemplate = officesTemplates.FirstOrDefault(c => c.idOffice == alertRequest.idOffice); if (tempTemplate != null) template = tempTemplate.template; } if (template != null) { var alert = new Alert() { Type = Alert.TypeVariant.Email, Request_Id = alertRequest.idRequest, SendDate = now, }; dc.Alerts.InsertOnSubmit(alert); var key = alertRequest.Applicant.User.Key; var body = new StringBuilder(); var websiteURL = string.Empty; var showPropertyPageURL = string.Empty; var showUserPageURL = string.Empty; if ((alertRequest.idOffice ?? 0) > 0) { var website = clientWebsites.FirstOrDefault(c => c.idAgencyOffice == alertRequest.idOffice); if (website != null) { websiteURL = website.ClientWebSite.mainURL; showPropertyPageURL = website.ClientWebSite.showPropertyURL; showUserPageURL = websiteURL + "/AlertRequest.aspx"; } else { alertRequest.LastSend = now; log.Error += string.Format("\nwe have no ClientWebSite for this office {0}", alertRequest.idOffice); continue;//bypass because bad office configuration } } else if (alertRequest.idSite.HasValue) { websiteURL = "http://www." + alertRequest.Site.SiteName; showPropertyPageURL = websiteURL + "/ShowProp.aspx?id="; showUserPageURL = websiteURL + "/AlertRequest.aspx"; } body.Append("<div style=\"color:#000; text-align:left; \">"); body.Append(template.Content); var StyleBoldText = "font-family: Trebuchet MS, Verdana, Arial, Helvetica, sans-serif; font-size: 9pt; color: #414141; line-height: 18px; font-weight:bold;"; #region " Alert Request " body.Append("<br/><span style=\"font-family: Trebuchet MS, Verdana, Arial, Helvetica, sans-serif;font-size: 16px;font-weight: bold;color: #414141;\">You requested properties matching these criteria :</span>"); body.Append("<i>(Request created on : " + alertRequest.CreatedDate.ToShortDateString() + ")</i><br/>"); body.Append(@"<div style=""text-align:left; margin-bottom:10px;padding:0px;""><img src=""http://www.4pm.ie/emailAlertTemplates/bar.gif"" border=""0"" /></div>"); body.Append("<table border=\"0\" style=\" \" cellpadding=\"5\">"); body.Append("<tr><td>Country : </td><td style=\"" + StyleBoldText + "\"> " + alertRequest.Country.CountryName + "</td></tr>"); body.Append("<tr><td>County/City : </td><td style=\"" + StyleBoldText + "\"> " + alertRequest.CountyCity.CountyCityName + "</td></tr>"); if (alertRequest.idDistrict.HasValue) body.Append("<tr><td>District : </td><td style=\"" + StyleBoldText + "\"> " + alertRequest.District.DistrictName + "</td></tr>"); if (alertRequest.idDistrictGroup.HasValue) body.Append("<tr><td>District group : </td><td style=\"" + StyleBoldText + "\"> " + alertRequest.DistrictGroup.GroupName + "</td></tr>"); if (!string.IsNullOrEmpty(alertRequest.PostCode)) body.Append("<tr><td>Post code : </td><td style=\"" + StyleBoldText + "\"> " + alertRequest.PostCode + "</td></tr>"); body.Append("<tr><td>Market : </td><td style=\"" + StyleBoldText + "\"> " + alertRequest.PropMarket.MarketName); if (alertRequest.idLetCategory.HasValue) body.Append(" - " + alertRequest.LetCategory.CategoryName); body.Append("</td></tr>"); body.Append("<tr><td>Type of property : </td><td style=\"" + StyleBoldText + "\"> " + alertRequest.PropertyType.PTypeName); if (alertRequest.idLivingType.HasValue) body.Append(" - " + alertRequest.LivingType.LTypeName); body.Append("</td></tr>"); if ((alertRequest.NumberOfBeds ?? 0) != 0) body.Append("<tr><td>Number of beds : </td><td style=\"" + StyleBoldText + "\"> " + alertRequest.NumberOfBeds + "</td></tr>"); if (alertRequest.MinPrice != 0) body.Append("<tr><td>Minimum price : </td><td style=\"" + StyleBoldText + "\"> " + alertRequest.MinPrice.ToString("c") + "</td></tr>"); if (alertRequest.MaxPrice != 0) body.Append("<tr><td>Maximum price : </td><td style=\"" + StyleBoldText + "\"> " + alertRequest.MaxPrice.ToString("c") + "</td></tr>"); body.Append("</table>"); #endregion body.Append("<br/><br/><span style=\"font-family: Trebuchet MS, Verdana, Arial, Helvetica, sans-serif;font-size: 16px;font-weight: bold;color: #414141;\">Properties matching your request:</span><br/>"); body.Append("<div style=\"text-align:left; margin-bottom:10px;padding:0px;\"><img src=\"http://www.4pm.ie/emailAlertTemplates/bar.gif\" border=\"0\" /></div>"); body.Append("<table border=\"0\" style=\"\" cellspacing=\"4\" >"); var isAlternateRow = false; var isFirstInRow = true; #region " Property section " foreach (var property in propertiesToSend) { if (isFirstInRow) { body.Append("<tr style=\"\">"); } var detailsLink = showPropertyPageURL + property.idList; body.Append("<td width=\"309\" height=\"145\" valign=\"top\"><table width=\"98%\" border=\"0\" align=\"center\" cellpadding=\"0\" cellspacing=\"0\" style=\"background-color: #ffffff;border: #bda68e 1px solid;padding: 2px;\">"); body.Append("<tr><td width=\"45\" valign=\"top\"><div style=\"width: 124px;height: 124px; background-color: #FFFFFF;\">"); if (property.PictureAdded == 1) body.Append("<img src=\"" + "http://www.4pm.ie/ShowThumbnail.aspx?id=" + property.idList + "&img=" + Uri.EscapeDataString(property.PropertyPictures.First().PicPath) + "\" style=\"margin: 2px;\" />"); else body.Append("<div style=\"width:120px; height:120px; margin:2px; border: solid 1px #f4ebe0; color:#d8d1ca; text-align:center;line-height: 18px;vertical-align:middle\" ><br/><br/>No picture<br/>Available</div>"); body.Append("</div></td><td width=\"62%\" valign=\"top\" style=\"padding:2px;\">"); body.Append("<div style=\"overflow: hidden;height: 40px;background-color: #F8F4F0;vertical-align:middle; padding:4px;\"><span style=\"font-family: Trebuchet MS, Verdana, Arial, Helvetica, sans-serif;font-size: 12px;color: #ac651d;font-weight:bold;\">" + (String.Format("{0}, {1}, {2}", property.DisplayAddress, property.District.DistrictName, property.CountyCity.CountyCityName)) + "</span></div>"); body.Append("<span style=\"font-family: Trebuchet MS, Verdana, Arial, Helvetica, sans-serif; font-size: 9pt; color: #414141; line-height: 18px;\"><strong>" + property.PropertyType.PTypeName); if ((property.BedroomLists.FirstOrDefault() ?? emptyBedroomList).TotalBedspaces != 0) body.Append(" - <span style=\"font-family: Trebuchet MS, Verdana, Arial, Helvetica, sans-serif;font-size: 11px; color: #4d8989;\">" + (property.BedroomLists.FirstOrDefault() ?? emptyBedroomList).TotalBedspaces + "</span> </strong>bed(s)<strong>"); body.Append("<br /></strong></span> "); body.Append("<span style=\"font-family: Trebuchet MS, Verdana, Arial, Helvetica, sans-serif;font-size: 11px; color: #4d8989;\">" + (property.PriceVal > 0 ? property.PriceVal.ToString("c") : "Price on request") + "</span><br />"); body.Append("</td></tr>"); body.Append("<tr><td colspan=\"2\" style=\"background-color: #F8F4F0;height:12px;vertical-align:bottom; text-align:right;\"><a href=\"" + detailsLink + "\" target=\"_blank\" style=\"font-family: Trebuchet MS, Verdana, Arial, Helvetica, sans-serif;font-size: 10px;color: #414141;font-weight:bold; text-decoration:none;\">View more details >>></a></td></tr></table>"); body.Append("</td>"); if (!isFirstInRow) { body.Append("</tr>"); } isAlternateRow = !isAlternateRow; isFirstInRow = !isFirstInRow; var alertContent = new AlertContent(); alertContent.Alert = alert; alertContent.idList = property.idList; dc.AlertContents.InsertOnSubmit(alertContent); } #endregion if (!isFirstInRow) body.Append("</tr>");//in case the last row was incomplete, close it body.Append("</table>"); body.AppendFormat(@"<br/><a href=""{0}"" target=""_blank"">Click here</a> to access your alerts management page and change your research criteria or alerts frequency settings.<br/> You can also <a href=""{1}"" target=""_blank"">unsubscribe from this alert</a>,<br/> or <a href=""{2}"" target=""_blank"">cancel all email alerts at once</a>.<br/> <br/>", showUserPageURL, string.Format("http://api.4pm.ie/alert.svc/{0}.{1}/unsubscribe", alertRequest.idRequest, key), string.Format("http://api.4pm.ie/alert.svc/{0}.{1}/unsubscribe", string.Join(",", relatedAlertRequestList.Select(c => c.ToString()).ToArray()), key) ); body.Append(template.footer); body.Append("</div>"); var senderEmail = template.sender; try { new MailAddress(senderEmail); } catch (FormatException ex) { log.Error += "\n" + ex.ToString(); senderEmail = defaultTemplate.sender; } smtpClient.Send( new MailMessage( senderEmail, alertRequest.Applicant.User.UserEmail, Settings.Default.EmailSubject, body.ToString()) { IsBodyHtml = true }); } log.NbAlertsSent++; } if ((alertRequest.Applicant.AllowSMS ?? false) && propertiesToSend.Count() > 0) { //TODO } if ((alertRequest.Applicant.AllowMMS ?? false) && propertiesToSend.Count() > 0) { //TODO }#endif } alertRequest.LastSend = now; dc.SubmitChanges(); } } } catch (Exception ex) { log.Error += "\n" + ex.ToString(); } finally { if (!string.IsNullOrEmpty(log.Error)) { Trace.TraceWarning(log.Error); } log.ExecutionTime = (decimal)DateTime.Now.Subtract(log.Date).TotalSeconds; dc.AlertEngineLogs.InsertOnSubmit(log); dc.SubmitChanges(); }#if DEBUG dc.Log.Close();#endif } } catch (Exception ex) { Trace.TraceError(ex.ToString()); } } private double Compare(AlertRequest alertRequest, Property property) { var result = 0.0; var likeness = 0.0; if ((!(alertRequest.MaxPrice >= property.PriceVal || alertRequest.MaxPrice == 0 || property.PriceVal == 0 || LikenessPercentage((double)alertRequest.MaxPrice, (double)property.PriceVal) > Settings.Default.MaxPriceK)) || (!(alertRequest.MinPrice <= property.PriceVal || alertRequest.MinPrice == 0 || property.PriceVal == 0 || LikenessPercentage((double)alertRequest.MinPrice, (double)property.PriceVal) > Settings.Default.MinPriceK))) { result = 1;//return 0; } else { if ((alertRequest.idDistrict ?? 0) != 0 && property.idDistrict != 0) { result += Settings.Default.DistrictK; likeness += Settings.Default.DistrictK; if (alertRequest.idDistrict != property.idDistrict) likeness -= Settings.Default.DistrictK; } if ((alertRequest.idDistrictGroup ?? 0) != 0) { result += Settings.Default.DistrictGroupK; likeness += Settings.Default.DistrictGroupK; if (property.District.DistrictGroupLists.FirstOrDefault(c => c.idDistrictGroup == alertRequest.idDistrictGroup) == null) likeness -= Settings.Default.DistrictGroupK; } if ((alertRequest.NumberOfBeds ?? 0) != 0) { result += Settings.Default.NumberOfBedsK; likeness += Settings.Default.NumberOfBedsK; if (Math.Abs((property.BedroomLists.FirstOrDefault() ?? emptyBedroomList).TotalBedspaces - alertRequest.NumberOfBeds ?? 0) > 1) likeness -= Settings.Default.NumberOfBedsK; } if ((alertRequest.idLivingType ?? 0) != 0) { result += Settings.Default.LivingTypeK; likeness += Settings.Default.LivingTypeK; if (alertRequest.idLivingType != property.idLType) likeness -= Settings.Default.LivingTypeK; } if (!string.IsNullOrEmpty(alertRequest.PostCode)) { result += Settings.Default.PostCodeK; likeness += Settings.Default.PostCodeK; if (!(property.Postcode ?? string.Empty).Trim().StartsWith(alertRequest.PostCode.Trim(), StringComparison.InvariantCultureIgnoreCase)) likeness -= Settings.Default.PostCodeK; } if ((alertRequest.idLetCategory ?? 0) != 0) { result += Settings.Default.LetCategoryK; likeness += Settings.Default.LetCategoryK; if ((property.LetCategoryLists.Count == 0 && property.idPropMarket == 2 && alertRequest.idLetCategory != 4) || (property.LetCategoryLists.FirstOrDefault(c => c.idLetCategory == alertRequest.idLetCategory) == null) ) likeness -= Settings.Default.LetCategoryK; } if (result == 0) { likeness = result = 1; } if (property.PriceVal == 0) { likeness -= Settings.Default.PriceOnRequestPenalty; } } return likeness / result; } private double LikenessPercentage(double val1, double val2) { var likeness = 1 - (Math.Abs(val1 - val2) / val1); return (likeness > 0 ? likeness : 0); } }}
- Email Report engine
- Report Engine
- Report Engine
- email report template
- Swing版本的report engine
- Send Report from Same Email Address
- springboot + birt Design Engine API,Report Engine API
- 在Application Engine 中调用 Crystal Report时,如何为 Crystal Report 传递参数?
- The similarity between integrating Design Engine API and integrating Report Engine API
- report
- Report
- report
- Report
- report
- Report ><
- Report
- Report
- 缺少“;”(在“namespace”的前面)
- Android之SQlite存储
- android native+web app架构
- 正则表达式(2)
- Delphi 调用C/C++的Dll
- Email Report engine
- 通过父类访问子类
- sqlite3语句
- 正则表达式语法
- 指定打印页数
- 国外软件外包项目网站(适用软件兼职)
- ASP.NET获取.aspx.cs的类名&获取当前url的domain
- 按百分比设置Flex DataGrid的列宽
- windows 下 安装bugzilla