private static void RebuildMembershipCacheForOrg(int handledOrgId) { Organizations orgs = Organization.FromIdentity(handledOrgId).GetTree(); Memberships ms = Memberships.ForOrganizations(orgs, false); OrgMembershipCacheEntry msc = null; foreach (Activizr.Logic.Pirates.Membership m in ms) { if (!membershipCache.ContainsKey(m.OrganizationId)) { msc = new OrgMembershipCacheEntry(); msc.memberships = new Dictionary <int, Activizr.Logic.Pirates.Membership>(); membershipCache[m.OrganizationId] = msc; } else { msc = membershipCache[m.OrganizationId]; } msc.membershipCacheTime = DateTime.Now; msc.memberships[m.PersonId] = m; msc.orgId = m.OrganizationId; } }
static public void Run() { MeetingElections polls = MeetingElections.GetAll(); foreach (MeetingElection poll in polls) { Console.Write("Looking at poll #" + poll.Identity.ToString() + "..."); if (DateTime.Now > poll.VotingCloses) { Console.Write(" after closedatetime " + poll.VotingCloses.ToString("yyyy-MM-dd HH:mm") + "..."); // Poll should be CLOSED, definitely CLOSED. if (poll.VotingOpen) { Console.WriteLine(" CLOSING."); poll.VotingOpen = false; // Closes poll poll.Creator.SendNotice("Poll Closed: " + poll.Name, string.Empty, poll.OrganizationId); Person.FromIdentity(1).SendNotice("Poll Closed: " + poll.Name, string.Empty, poll.OrganizationId); ReportPollResults(poll, false); } else { Console.WriteLine(" no action."); } } else if (DateTime.Now > poll.VotingOpens) { try { // Poll should be OPEN. Console.Write("after opendatetime " + poll.VotingOpens.ToString("yyyy-MM-dd HH:mm") + "..."); if (!poll.VotingOpen) { Console.WriteLine("OPENING for " + poll.Organization.Name + ":"); // Populate voters, then open for voting Organizations orgTree = poll.Organization.GetTree(); Memberships memberships = Memberships.ForOrganizations(orgTree); Dictionary <int, bool> dupeCheck = new Dictionary <int, bool>(); int count = 0; foreach (Membership membership in memberships) { Console.Write("\r - voters: {0:D6}/{1:D6} (person #{2:D6})...", ++count, memberships.Count, membership.PersonId); if (!membership.Active) { continue; // paranoid programming } if (!membership.Organization.IsOrInherits(poll.Organization)) { continue; // more paranoid programming } if (!dupeCheck.ContainsKey(membership.PersonId)) { if (membership.Person.GeographyId == 0) { // It's a trap! Console.Write(" GEOGRAPHY ZERO, ignoring\r\n"); } else { Geography geo = membership.Person.Geography; if (geo.Inherits(poll.GeographyId) || geo.Identity == poll.GeographyId) { poll.AddVoter(membership.Person); dupeCheck[membership.PersonId] = true; } } } } Console.WriteLine(" done."); Console.Write(" - opening poll..."); poll.VotingOpen = true; Console.WriteLine(" done."); Console.Write("Sending notices... "); string body = "Electoral roll for poll \"" + poll.Name + "\" primed. " + dupeCheck.Count.ToString() + " people can vote. The vote is now OPEN."; string subject = "Poll Open: " + poll.Name; poll.Creator.SendNotice(subject, body, poll.OrganizationId); Person.FromIdentity(1).SendNotice(subject, body, poll.OrganizationId); Console.WriteLine(" done."); } else { Console.WriteLine(" already open, no action."); // Report intermediate results to owner ReportPollResults(poll, true); } } catch (Exception exception) { Console.WriteLine(exception.ToString()); throw exception; } } } }
SeriesCollection GetAgeGenderData(OrganizationMetadata metadata) { int orgId = metadata.OrganizationId; bool recurseTree = metadata.Recursive; Series seriesMale = new Series(); Series seriesFemale = new Series(); seriesMale.Name = "Male"; seriesFemale.Name = "Female"; Memberships memberships = null; if (recurseTree) { memberships = Memberships.ForOrganizations(Organization.FromIdentity(orgId).GetTree()); } else { memberships = Memberships.ForOrganization(Organization.FromIdentity(orgId)); } BasicPerson[] allPeople = PirateDb.GetDatabase().GetAllPeople(); Dictionary <int, int> geoLookup = new Dictionary <int, int>(); Dictionary <int, PersonGender> genderLookup = new Dictionary <int, PersonGender>(); Dictionary <int, int> birthYearLookup = new Dictionary <int, int>(); Dictionary <int, bool> personLookup = new Dictionary <int, bool>(); foreach (BasicPerson person in allPeople) { geoLookup[person.Identity] = person.GeographyId; genderLookup[person.Identity] = person.IsMale ? PersonGender.Male : PersonGender.Female; birthYearLookup[person.Identity] = person.Birthdate.Year; } int[] male = new int[200]; int[] female = new int[200]; foreach (Membership membership in memberships) { int birthYear = 0; PersonGender gender = PersonGender.Unknown; if (personLookup.ContainsKey(membership.PersonId)) { continue; // If a person was already counted, do not count again } if (genderLookup.ContainsKey(membership.PersonId) && (membership.OrganizationId == orgId || (recurseTree && membership.Organization.Inherits(orgId)))) { birthYear = birthYearLookup[membership.PersonId]; gender = genderLookup[membership.PersonId]; int index = birthYear - 1900; if (index < 30 || index >= 100) { index = 90; // Put invalid years on 1990, where it won't show up in the noise } if (gender == PersonGender.Male) { male[index]++; } else { female[index]++; } personLookup[membership.PersonId] = true; } } Element newElement = new Element(); for (int yearIndex = 30; yearIndex < 100; yearIndex++) { newElement = new Element(); newElement.Name = (1900 + yearIndex).ToString(); newElement.YValue = male[yearIndex]; seriesMale.Elements.Add(newElement); newElement = new Element(); newElement.Name = (1900 + yearIndex).ToString(); newElement.YValue = female[yearIndex]; seriesFemale.Elements.Add(newElement); } seriesMale.DefaultElement.Color = Color.Blue; seriesFemale.DefaultElement.Color = Color.Red; SeriesCollection collection = new SeriesCollection(); collection.Add(seriesFemale); collection.Add(seriesMale); return(collection); }
public static GeographyStatistics GeneratePresent(int[] memberCountForOrganizations) { Dictionary <int, int> voterCounts = SwarmDb.GetDatabaseForReading().GetGeographyVoterCounts(); var result = new GeographyStatistics(); // Step 1 - tally the leaf nodes foreach (int geographyId in voterCounts.Keys) { var dataPoint = new GeographyDataPoint { GeographyName = Geography.FromIdentity(geographyId).Name, GeographyId = geographyId, VoterCount = voterCounts[geographyId] }; result[geographyId] = dataPoint; } // Step 2 - add the member counts to the individual requested geo nodes foreach (int orgId in memberCountForOrganizations) { People members = People.FromMemberships( Memberships.ForOrganizations(Organization.FromIdentity(orgId).GetTree())); foreach (Person person in members) { Geography geography = person.Geography; // If we don't have this key, it's because it's too far down. Move up the tree until we're at least // at municipal level. while (geography.Identity != 1 && !result.ContainsKey(geography.Identity)) { geography = geography.Parent; } // Add the data, unless we hit the roof in the last op. if (geography.Identity != 1) { int birthYearBracket = (person.Birthdate.Year - 1900) / 5; if (birthYearBracket >= 0 && birthYearBracket < 30) { result[geography.Identity].OrganizationData[orgId - 1].BirthYearBracketMemberCounts[ birthYearBracket]++; } if (person.IsFemale) { result[geography.Identity].OrganizationData[orgId - 1].FemaleMemberCount++; } else if (person.IsMale) { result[geography.Identity].OrganizationData[orgId - 1].MaleMemberCount++; } } } } // TODO: Activist count as a new step // Step 3 - add up the totals for every intermediate node (expensive!) Geographies allGeographies = Geography.Root.GetTree(); foreach (Geography geography in allGeographies) { Geographies localTree = geography.GetTree(); int voterCount = 0; var tempOrgData = new GeographyOrganizationDataPoint[2]; // HACK tempOrgData[0] = new GeographyOrganizationDataPoint(); tempOrgData[1] = new GeographyOrganizationDataPoint(); foreach (Geography localNode in localTree) { // Increment our temp values for every geo node below the one we're currently processing. if (!result.ContainsKey(localNode.Identity)) { continue; } voterCount += result[localNode.Identity].VoterCount; for (int orgIndex = 0; orgIndex < 2; orgIndex++) { for (int ageBracketIndex = 0; ageBracketIndex < 30; ageBracketIndex++) { tempOrgData[orgIndex].BirthYearBracketMemberCounts[ageBracketIndex] += result[localNode.Identity].OrganizationData[orgIndex].BirthYearBracketMemberCounts[ ageBracketIndex]; } tempOrgData[orgIndex].ActivistCount += result[localNode.Identity].OrganizationData[orgIndex].ActivistCount; tempOrgData[orgIndex].FemaleMemberCount += result[localNode.Identity].OrganizationData[orgIndex].FemaleMemberCount; tempOrgData[orgIndex].MaleMemberCount += result[localNode.Identity].OrganizationData[orgIndex].MaleMemberCount; } } if (!result.ContainsKey(geography.Identity)) { result[geography.Identity] = new GeographyDataPoint { GeographyId = geography.Identity, GeographyName = geography.Name }; } // Save our temp values to the processed node. result[geography.Identity].VoterCount = voterCount; for (int orgIndex = 0; orgIndex < 2; orgIndex++) { for (int ageBracketIndex = 0; ageBracketIndex < 30; ageBracketIndex++) { result[geography.Identity].OrganizationData[orgIndex].BirthYearBracketMemberCounts[ ageBracketIndex] = tempOrgData[orgIndex].BirthYearBracketMemberCounts[ageBracketIndex]; } result[geography.Identity].OrganizationData[orgIndex].ActivistCount = tempOrgData[orgIndex].ActivistCount; result[geography.Identity].OrganizationData[orgIndex].FemaleMemberCount = tempOrgData[orgIndex].FemaleMemberCount; result[geography.Identity].OrganizationData[orgIndex].MaleMemberCount = tempOrgData[orgIndex].MaleMemberCount; } } // Step 4 - collect return(result); }
protected void Page_Load(object sender, EventArgs e) { string fileName = DateTime.Now.ToString("yyyyMMdd_HHmm") + ".txt"; DateTime specificDate = DateTime.MinValue; DateTime yearLimit = DateTime.Today.AddYears(-1); if (Request["Date"] != null) { DateTime.TryParse(Request["Date"].ToString(), out specificDate); if (specificDate != DateTime.MinValue) { fileName = "[" + specificDate.ToString("yyyyMMdd_HHmm") + "]" + fileName; specificDate = specificDate.AddDays(1); yearLimit = specificDate.AddYears(-1); specificDate = specificDate.AddSeconds(-1); } } if (Request.Browser.Browser == "IE") { fileName = Server.UrlPathEncode(fileName); if (fileName != null) { fileName = fileName.Replace(@"+", @"%20"); } } int org = Organization.UPSEid; Organization organization = Organization.FromIdentity(org); fileName = organization.NameShort + fileName; Response.ContentType = "text/plain"; Response.ContentEncoding = Encoding.GetEncoding(1252); //Response.ContentType = "application/octet-stream"; Response.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";"); if (_authority.HasRoleAtOrganization(organization, new RoleType[] { RoleType.OrganizationChairman, RoleType.OrganizationSecretary }, Authorization.Flag.AnyGeographyExactOrganization) || _authority.HasRoleType(RoleType.SystemAdmin)) { People ThePeople = People.GetAll().RemoveUnlisted(); Memberships MembershipsList = null; if (Request["Date"] != null) { MembershipsList = Memberships.FromArray(PirateDb.GetDatabase().GetMemberships()); // gets ALL memberships } else { MembershipsList = Memberships.ForOrganizations(Organization.FromIdentity(org).GetTree()); } Dictionary <int, string> GeoDistriktForGeo = new Dictionary <int, string>(); Dictionary <int, string> OrgDistriktForOrg = new Dictionary <int, string>(); Dictionary <int, Memberships> ActiveMemberships = new Dictionary <int, Memberships>(); foreach (Membership ms in MembershipsList) { if (ms.OrganizationId == org || ms.Organization.Inherits(org)) { if (specificDate != DateTime.MinValue) { if ((ms.Active || ms.DateTerminated > specificDate) && // Rick replaced "DateTerminated.HasValue" with "Active=1" ms.Expires > specificDate && ms.MemberSince <= specificDate) { if (!ActiveMemberships.ContainsKey(ms.PersonId)) { ActiveMemberships.Add(ms.PersonId, new Memberships()); } ActiveMemberships[ms.PersonId].Add(ms); } } else if (ms.Active) { if (!ActiveMemberships.ContainsKey(ms.PersonId)) { ActiveMemberships.Add(ms.PersonId, new Memberships()); } ActiveMemberships[ms.PersonId].Add(ms); } } } List <int> idlist = new List <int>(); Dictionary <int, List <BasicPWEvent> > personLogs = new Dictionary <int, List <BasicPWEvent> >(); foreach (int pId in ActiveMemberships.Keys) { idlist.Add(pId); if (idlist.Count > 500) { FetchBatchOfLogs(ref specificDate, ref yearLimit, idlist, personLogs); idlist = new List <int>(); } } if (idlist.Count > 0) { FetchBatchOfLogs(ref specificDate, ref yearLimit, idlist, personLogs); } StringBuilder sb = new StringBuilder(); sb.Append("Identity"); sb.Append("\tName"); sb.Append("\tEmail"); sb.Append("\tStreet"); sb.Append("\tPostalCode"); sb.Append("\tCity"); sb.Append("\tCountry.Name"); sb.Append("\tPhone"); sb.Append("\tBirthdate"); sb.Append("\tGender"); sb.Append("\tGeography.Name"); sb.Append("\tGeography.District"); sb.Append("\tOrganization.Name"); sb.Append("\tOrganization.District"); sb.Append("\tMembership.start"); sb.Append("\tMembership.until"); sb.Append("\tRenewed"); sb.Append("\tType"); sb.Append("\tby"); sb.Append("\tfrom"); sb.Append("\r\n"); foreach (Person p in ThePeople) { if (ActiveMemberships.ContainsKey(p.PersonId)) { Memberships pMemberships = ActiveMemberships[p.PersonId]; foreach (Membership m in pMemberships) { if (!GeoDistriktForGeo.ContainsKey(p.GeographyId)) { Geography currentGeoDistr = null; GeoDistriktForGeo[p.GeographyId] = "N/A"; if (p.GeographyId != 0) { try { Geography previous = p.Geography; if (p.Geography.ParentGeographyId != 0) { currentGeoDistr = p.Geography.Parent; } while (currentGeoDistr != null && currentGeoDistr.Identity != 0 && currentGeoDistr.Identity != Geography.SwedenId && currentGeoDistr.Identity != Geography.RootIdentity) { previous = currentGeoDistr; if (currentGeoDistr.ParentGeographyId == 0) { currentGeoDistr = null; } else { currentGeoDistr = currentGeoDistr.Parent; } } if (previous != null) { GeoDistriktForGeo[p.GeographyId] = previous.Name; } } catch (Exception ex) { GeoDistriktForGeo[p.GeographyId] = "n/a"; } } } if (!OrgDistriktForOrg.ContainsKey(m.OrganizationId)) { Organization currentOrgDistr = null; OrgDistriktForOrg[m.OrganizationId] = "N/A"; Organization previous = m.Organization; currentOrgDistr = m.Organization.Parent;; while (currentOrgDistr != null && currentOrgDistr.Identity != 0 && currentOrgDistr.Identity != org && currentOrgDistr.Identity != Organization.RootIdentity) { previous = currentOrgDistr; if (currentOrgDistr.ParentOrganizationId == 0) { currentOrgDistr = null; } else { currentOrgDistr = currentOrgDistr.Parent; } } if (previous != null) { OrgDistriktForOrg[m.OrganizationId] = previous.NameShort; } } sb.Append(p.Identity); sb.Append("\t" + p.Name.Replace("\t", "")); sb.Append("\t" + p.Email.Replace("\t", "")); sb.Append("\t" + p.Street.Replace("\t", "")); sb.Append("\t" + p.PostalCode.Replace("\t", "")); sb.Append("\t" + p.CityName.Replace("\t", "")); sb.Append("\t" + p.Country.Name.Replace("\t", "")); sb.Append("\t" + p.Phone.Replace("\t", "")); sb.Append("\t" + p.Birthdate); sb.Append("\t" + p.Gender); sb.Append("\t" + p.Geography.Name); sb.Append("\t" + GeoDistriktForGeo[p.GeographyId]); sb.Append("\t" + m.Organization.Name); sb.Append("\t" + OrgDistriktForOrg[m.OrganizationId]); sb.Append("\t" + m.MemberSince); if (!m.Active) { sb.Append("\t" + m.DateTerminated); } else { sb.Append("\t" + m.Expires); } if (personLogs.ContainsKey(p.Identity)) { bool found = false; foreach (BasicPWEvent log in personLogs[p.Identity]) { if (log.OrganizationId == m.OrganizationId) { sb.Append("\t" + log.DateTime); sb.Append("\t" + log.EventType); sb.Append("\t" + log.ActingPersonId); sb.Append("\t" + log.ParameterText); found = true; break; } } if (!found) { sb.Append("\t\t\t\t"); } } else { sb.Append("\t\t\t\t"); } sb.Append("\r\n"); } } } Response.Write(sb.ToString()); } }
SeriesCollection GetAgeGenderData() { string orgIdString = Request.QueryString["OrgId"]; string recurseTreeString = Request.QueryString["RecurseTree"]; int orgId = Organization.PPSEid; bool recurseTree = false; if (orgIdString != null) { orgId = Int32.Parse(orgIdString); } if (recurseTreeString == "1") { recurseTree = true; } Chart.ChartArea.YAxis.Label.Text = "Medlems\xE5ldrar och k\xF6n - " + Organization.FromIdentity(orgId).Name; Series seriesMale = new Series(); Series seriesFemale = new Series(); seriesMale.Name = "M\xE4n"; seriesFemale.Name = "Kvinnor"; Memberships memberships = null; if (recurseTree) { memberships = Memberships.ForOrganizations(Organization.FromIdentity(orgId).GetTree()); } else { memberships = Memberships.ForOrganization(Organization.FromIdentity(orgId)); } BasicPerson[] allPeople = PirateDb.GetDatabase().GetAllPeople(); Dictionary <int, int> geoLookup = new Dictionary <int, int>(); Dictionary <int, PersonGender> genderLookup = new Dictionary <int, PersonGender>(); Dictionary <int, int> birthYearLookup = new Dictionary <int, int>(); Dictionary <int, int> personLookup = new Dictionary <int, int>(); foreach (BasicPerson person in allPeople) { geoLookup[person.Identity] = person.GeographyId; genderLookup[person.Identity] = person.IsMale ? PersonGender.Male : PersonGender.Female; birthYearLookup[person.Identity] = person.Birthdate.Year; } int[] male = new int[200]; int[] female = new int[200]; foreach (Membership membership in memberships) { int birthYear = 0; PersonGender gender = PersonGender.Unknown; if (genderLookup.ContainsKey(membership.PersonId) && !personLookup.ContainsKey(membership.PersonId) && (membership.OrganizationId == orgId || (recurseTree && membership.Organization.Inherits(orgId)))) { personLookup[membership.PersonId] = 1; birthYear = birthYearLookup[membership.PersonId]; gender = genderLookup[membership.PersonId]; if (birthYear > 1900 && birthYear < (1900 + 200)) { if (gender == PersonGender.Male) { male[birthYear - 1900]++; } else { female[birthYear - 1900]++; } } } } Element newElement = new Element(); for (int yearIndex = 30; yearIndex <= 100; yearIndex++) { newElement = new Element(); newElement.Name = (1900 + yearIndex).ToString(); newElement.YValue = male[yearIndex]; seriesMale.Elements.Add(newElement); newElement = new Element(); newElement.Name = (1900 + yearIndex).ToString(); newElement.YValue = female[yearIndex]; seriesFemale.Elements.Add(newElement); } seriesMale.DefaultElement.Color = Color.Blue; seriesFemale.DefaultElement.Color = Color.Red; SeriesCollection collection = new SeriesCollection(); collection.Add(seriesFemale); collection.Add(seriesMale); return(collection); }
public static void RemindChangeOrg() { HeartBeater.Instance.Beat(); // Get expiring DateTime starttime = DateTime.Now; Organizations orgs = Organization.FromIdentity(Organization.UPSEid).GetTree(); Dictionary <int, Person> personLookup = new Dictionary <int, Person>(); Dictionary <int, Memberships> personMembershipsLookup = new Dictionary <int, Memberships>(); Dictionary <int, Organization> orgLookup = new Dictionary <int, Organization>(); Dictionary <int, Organization> mostLocalOrganizationCache = new Dictionary <int, Organization>(); List <ChangeOrgReport> report = new List <ChangeOrgReport>(); foreach (Organization org in orgs) { orgLookup[org.OrganizationId] = org; } Memberships allMemberships = Memberships.ForOrganizations(orgs); foreach (Membership ms in allMemberships) { //Handle defunct Memberships.ForOrganizations if (orgLookup.ContainsKey(ms.OrganizationId)) { if (!personLookup.ContainsKey(ms.PersonId)) { personLookup[ms.PersonId] = null; personMembershipsLookup[ms.PersonId] = new Memberships(); } personMembershipsLookup[ms.PersonId].Add(ms); } } allMemberships = null; People peeps = People.FromIdentities((new List <int>(personLookup.Keys)).ToArray()); foreach (Person p in peeps) { personLookup[p.PersonId] = p; } if (Debugger.IsAttached) { Console.WriteLine("Found " + personLookup.Count + " people"); } int processedCounter = 0; int sentCounter = 0; int failCounter = 0; DateTime lastDisplay = DateTime.Now; foreach (Person person in personLookup.Values) { ++processedCounter; if ((processedCounter % 50) == 0) { HeartBeater.Instance.Beat(); if (Debugger.IsAttached) { Console.WriteLine("Processed " + processedCounter + " t=" + DateTime.Now.Subtract(lastDisplay).TotalSeconds); } lastDisplay = DateTime.Now; } int geoid = person.GeographyId; //check for error, geography broken. if (person.GeographyId == 0) { geoid = person.Geography.GeographyId; //Will force resolve Geography if (geoid != 0) { person.Geography = person.Geography; } ; //repair person. } if (geoid == 0) { continue; //give up on that... } Organization expectedLowOrg = null; if (mostLocalOrganizationCache.ContainsKey(geoid)) { expectedLowOrg = mostLocalOrganizationCache[geoid]; } else { expectedLowOrg = Organizations.GetMostLocalOrganization(geoid, Organization.UPSEid); mostLocalOrganizationCache[geoid] = expectedLowOrg; } bool found = false; Dictionary <int, Membership> personMS = new Dictionary <int, Membership>(); foreach (Membership ms in personMembershipsLookup[person.PersonId]) { if (orgLookup.ContainsKey(ms.OrganizationId)) { //Its an UP org personMS[ms.OrganizationId] = ms; } if (ms.OrganizationId == expectedLowOrg.Identity) { found = true; break; } } if (found == false) { //OK we didnt find the recommended org. Find out why. // loop thru the persons up orgs to find an inactive List <Organization> foundInactiveOrg = new List <Organization>(); List <Organization> foundActiveOrg = new List <Organization>(); Membership membership = null; try { Organization org = null; foreach (Membership ms in personMS.Values) { org = orgLookup[ms.OrganizationId]; if (org.AcceptsMembers == false) { foundInactiveOrg.Add(org); } else if (org.AutoAssignNewMembers == true) { foundActiveOrg.Add(org); } } if (foundInactiveOrg.Count > 0) { //inactive membership = personMS[foundInactiveOrg[0].Identity]; } else if (foundActiveOrg.Count > 0) { //change membership = personMS[foundActiveOrg[0].Identity]; } else { //already a member but not of an autoassign org if (Debugger.IsAttached) { Console.WriteLine("Debug:nochange " + person.Name + ";" + person.Geography.Name + ";" + (org != null ? org.Name : "UnknownOrg") + ";" + expectedLowOrg.Name); } continue; } DateTime lastReminder = PWLog.CheckLatest(PWLogItem.Person, membership.PersonId, PWLogAction.MembershipRenewReminder); if (DateTime.Now.Subtract(lastReminder).TotalDays > 25) { if (Debugger.IsAttached) { Console.Write("Debug:" + person.Name + ";" + person.Geography.Name + ";" + membership.Organization.Name + ";" + expectedLowOrg.Name); foreach (var o in foundActiveOrg) { Console.Write(";" + o.Name); } Console.WriteLine(""); } SendChangeOrgMail(person, membership, expectedLowOrg); report.Add(new ChangeOrgReport { FromOrg = membership.Organization, ToOrg = expectedLowOrg }); ++sentCounter; PWLog.Write(PWLogItem.Person, membership.PersonId, PWLogAction.MembershipRenewReminder, "Mail was sent to " + membership.Person.Mail + " for recommendation of organisation change in " + membership.Organization.Name + ".", membership.Organization.Identity.ToString() + "/" + expectedLowOrg.Identity.ToString()); } } catch (Exception x) { ++failCounter; string logText = "FAILED sending mail to " + membership.Person.Mail + " for recommendation of organisation change in " + membership.Organization.Name + "."; PWLog.Write(PWLogItem.Person, membership.PersonId, PWLogAction.MembershipRenewReminder, logText, string.Empty); ExceptionMail.Send(new Exception(logText, x)); } } } Dictionary <Organization, Dictionary <Organization, int> > fromdict = new Dictionary <Organization, Dictionary <Organization, int> >(); StringBuilder fromOrgReport = new StringBuilder(); report.ForEach(delegate(ChangeOrgReport r) { if (!fromdict.ContainsKey(r.FromOrg)) { fromdict[r.FromOrg] = new Dictionary <Organization, int>(); } if (!fromdict[r.FromOrg].ContainsKey(r.ToOrg)) { fromdict[r.FromOrg][r.ToOrg] = 0; } fromdict[r.FromOrg][r.ToOrg]++; }); foreach (var fd in fromdict.Keys) { StringBuilder tmp = new StringBuilder(); int cnt = 0; foreach (var td in fromdict[fd].Keys) { tmp.Append(", " + td.Name); cnt += fromdict[fd][td]; } fromOrgReport.Append("\r\nFrån " + fd.Name + " (" + cnt + " st) till " + tmp.ToString().Substring(2)); } Dictionary <Organization, Dictionary <Organization, int> > todict = new Dictionary <Organization, Dictionary <Organization, int> >(); StringBuilder toOrgReport = new StringBuilder(); report.ForEach(delegate(ChangeOrgReport r) { if (!todict.ContainsKey(r.ToOrg)) { todict[r.ToOrg] = new Dictionary <Organization, int>(); } if (!todict[r.ToOrg].ContainsKey(r.FromOrg)) { todict[r.ToOrg][r.FromOrg] = 0; } todict[r.ToOrg][r.FromOrg]++; }); foreach (var td in todict.Keys) { StringBuilder tmp = new StringBuilder(); int cnt = 0; foreach (var fd in todict[td].Keys) { tmp.Append(", " + fd.Name); cnt += todict[td][fd]; } toOrgReport.Append("\r\nTill " + td.Name + " (" + cnt + " st) från " + tmp.ToString().Substring(2)); } string reportMessage = string.Format( "Result from running recommendation to change org mails:\r\n" + "Time: {0,10:#0.0} minutes. \r\n" + "Checked: {1,10:g}\r\n" + "Sent: {2,10:g}\r\n" + "Failed: {3,10:g}\r\n", DateTime.Now.Subtract(starttime).TotalMinutes, processedCounter, sentCounter, failCounter) + fromOrgReport + "\r\n" + toOrgReport; BasicPersonRole[] UPSecretary = SwarmDb.GetDatabaseForReading().GetPeopleWithRoleType(RoleType.OrganizationSecretary, new int[] { Organization.UPSEid }, new int[] { }); if (UPSecretary.Length > 0) { Person.FromIdentity(UPSecretary[0].PersonId).SendOfficerNotice("ChangeOrg Mails Job report", reportMessage, Organization.UPSEid); } Person.FromIdentity(7838).SendOfficerNotice("ChangeOrgMails run", reportMessage, Organization.UPSEid);//Debug }