internal static void ProcessReceivedPayment(BasicEvent newEvent) { // Set membership expiry to one year from today's expiry // First, find this particular membership Membership renewedMembership = null; bool foundExisting = false; try { renewedMembership = Membership.FromBasic(Memberships.GetMembership(newEvent.VictimPersonId, newEvent.OrganizationId)); foundExisting = true; } catch (ArgumentException) { } // an exception here means there was no active membership if (foundExisting) { Person person = renewedMembership.Person; DateTime expires = renewedMembership.Expires; ChurnData.LogRetention(person.Identity, renewedMembership.OrganizationId, expires); Events.CreateEvent(EventSource.CustomServiceInterface, EventType.ExtendedMembership, person.Identity, renewedMembership.OrganizationId, person.GeographyId, person.Identity, 0, string.Empty); expires = expires.AddYears(1); // If the membership is in organization 1, then propagate the expiry to every other org this person is a member of // Cheat and assume Swedish. In the future, take this from a template. string mailBody = "Tack för att du har valt att förnya ditt medlemskap och fortsätta vara en del av piratrörelsen i " + "Sverige! Ditt medlemskap går nu ut " + expires.ToString("yyyy-MM-dd") + ", och gäller följande föreningar:\r\n\r\n"; Memberships memberships = person.GetMemberships(); foreach (Membership membership in memberships) { if (membership.Organization.Inherits(1) || membership.OrganizationId == 1) { membership.Expires = expires; mailBody += membership.Organization.Name + "\r\n"; } } mailBody += "\r\nOm du har några frågor, så kontakta gärna Medlemsservice på [email protected]. Återigen, " + "välkommen att vara med i vårt fortsatta arbete!\r\n"; new PirateWeb.Utility.Mail.MailTransmitter("Piratpartiet Medlemsservice", "*****@*****.**", "Piratpartiet: Ditt medlemskap är förnyat", mailBody, person).Send(); } else { // This person's membership has expired, so he/she needs a new one. // TODO } }
SeriesCollection GetChurnRetentionData() { DateTime dateIterator = new DateTime(2007, 4, 15); string timeFocus = Request.QueryString["DaysHistory"]; if (timeFocus != null) { dateIterator = DateTime.Now.Date.AddDays(-Int32.Parse(timeFocus)); } string cacheDataKey = "ChartData-All-PpSe-ChurnData"; ChurnData data = (ChurnData)Cache.Get(cacheDataKey); if (data == null) { data = ChurnData.ForOrganization(Organization.PPSE); Cache.Insert(cacheDataKey, data, null, DateTime.Today.AddDays(1).ToUniversalTime(), System.Web.Caching.Cache.NoSlidingExpiration); } int[] retentionIntervals = { 30, 21, 14, 7, 2 }; Series[] seriesRetention = new Series[retentionIntervals.Length + 1]; for (int index = 0; index < retentionIntervals.Length + 1; index++) { seriesRetention[index] = new Series(); if (index == 0) { seriesRetention[index].Name = (retentionIntervals[0] + 1).ToString() + "+d"; } else if (index < retentionIntervals.Length) { seriesRetention[index].Name = retentionIntervals[index].ToString() + "-" + retentionIntervals[index - 1].ToString() + "d"; } else { seriesRetention[index].Name = "Last day"; } } Series seriesChurn = new Series(); seriesChurn.Name = "Churn"; DateTime today = DateTime.Now.Date; int eventIndex = 0; while (data [eventIndex].ExpiryDate < dateIterator) { eventIndex++; } while (dateIterator < today) { int todaysChurn = 0; int[] todaysRetention = new int[seriesRetention.Length]; // array elements initialize to 0 DateTime nextDate = dateIterator.AddDays(1); while (eventIndex < data.Count && data[eventIndex].ExpiryDate < nextDate) { ChurnDataPoint dataPoint = data[eventIndex]; if (dataPoint.DataType == ChurnDataType.Churn) { todaysChurn++; } else { int dayCount = (dataPoint.ExpiryDate - dataPoint.DecisionDateTime).Days; int seriesIndex = 0; while (seriesIndex < retentionIntervals.Length && dayCount < retentionIntervals[seriesIndex]) { seriesIndex++; } todaysRetention[seriesIndex]++; } eventIndex++; } Element newElement = new Element(); for (int seriesIndex = 0; seriesIndex < seriesRetention.Length; seriesIndex++) { newElement = new Element(); newElement.XDateTime = dateIterator; newElement.YValue = todaysRetention [seriesIndex]; seriesRetention [seriesIndex].Elements.Add(newElement); } newElement = new Element(); newElement.XDateTime = dateIterator; newElement.YValue = todaysChurn; seriesChurn.Elements.Add(newElement); dateIterator = nextDate; } SeriesCollection collection = new SeriesCollection(); for (int seriesIndex = 0; seriesIndex < seriesRetention.Length - 1; seriesIndex++) { seriesRetention [seriesIndex].DefaultElement.Color = InterpolateColor(Color.Green, Color.Yellow, (double)(seriesIndex * 100) / (double)(seriesRetention.Length - 2)); collection.Add(seriesRetention[seriesIndex]); } seriesRetention[seriesRetention.Length - 1].DefaultElement.Color = Color.Wheat; collection.Add(seriesRetention[seriesRetention.Length - 1]); seriesChurn.DefaultElement.Color = Color.FromArgb(128, 16, 32); collection.Add(seriesChurn); return(collection); }
SeriesCollection GetSeriesCollection() { SeriesCollection result = new SeriesCollection(); ChurnData churnData = ChurnData.ForOrganization(Organization.PPSE); Memberships memberships = Memberships.ForOrganization(Organization.PPSE, true); // Build a hash table with memberships, based on person id Dictionary <int, Membership> membershipHash = new Dictionary <int, Membership>(); foreach (Membership membership in memberships) { membershipHash[membership.PersonId] = membership; } string[] elementNames = { "Churn", "Retention" }; Color[] colors = { Color.Red, Color.Green }; int currentYear = DateTime.Today.Year; int seriesCount = currentYear - 2006; // Create one series per year starting at 2006 int[,] data = new int[seriesCount, 2]; DateTime now = DateTime.Now; // cache this value foreach (ChurnDataPoint churnDataPoint in churnData) { if (membershipHash.ContainsKey(churnDataPoint.PersonId)) { Membership membership = membershipHash[churnDataPoint.PersonId]; // If not part of the renewal cycle, ignore - statistically uninteresting if ((churnDataPoint.ExpiryDate - churnDataPoint.DecisionDateTime).Days > 35) { if (churnDataPoint.DecisionDateTime < new DateTime(2006, 12, 1) || churnDataPoint.DecisionDateTime > new DateTime(2007, 1, 15)) { continue; } } TimeSpan span = churnDataPoint.ExpiryDate - membership.MemberSince; int membershipDurationYears = (int)((span.Days + 40) / 365.25); // Add 40d for margin at renewal process if (membershipDurationYears < 0) { membershipDurationYears = 0; // some bogus data in db } int dataIndex = 0; if (churnDataPoint.DataType == Activizr.Basic.Enums.ChurnDataType.Retention) { dataIndex = 1; } if (membershipDurationYears == 0) { membershipDurationYears = 1; // pretend first-year events happen at first cycle } data[membershipDurationYears - 1, dataIndex]++; } else { Response.Write("<!-- " + churnDataPoint.PersonId + " -->"); } } for (int renewalIndex = seriesCount - 1; renewalIndex >= 0; renewalIndex--) { Series series = new Series(); series.Name = "Renewal #" + (renewalIndex + 1).ToString(); for (int elementLoop = 0; elementLoop < 2; elementLoop++) { Element element = new Element(elementNames[elementLoop], data[renewalIndex, elementLoop]); element.Color = colors[elementLoop]; series.Elements.Add(element); } result.Add(series); } return(result); }