/// <summary> /// Sets the tolling information for a tolling letter CMO message. /// </summary> /// <param name="message">The CMO message to update.</param> /// <returns>true if the tolling information was set or cleared successfully; otherwise, false.</returns> /// <remarks>The tolling information can only be successfully set if the message is a tolling letter and cleared if the message is not a tolling letter. The information will automatically be cleared for messages that are not tolling letters regardless of the message's tolling values.</remarks> private bool SetCmoMessageTolling(CmoMessage message) { if (message == null) { return(false); } string candidateID = message.CandidateID; int messageID = message.ID; TollingLetter letter = message.TollingLetter; if (message.IsInadequateResponseLetter) { // force interpretation of inadequate response letters as tolling letters if (letter == null) { letter = message.TollingLetter = GetTollingLetter(CPConvert.ToCfisCode(AuditReportType.IdrInadequateResponse), message.IsIdrAdditionalInadequateLetter || message.IsDarAdditionalInadequateLetter ? "ADDINA" : "INARES", "INAD"); } if (!message.TollingEventNumber.HasValue) { message.TollingEventNumber = int.MinValue; } } bool hasTolling = message.TollingEventNumber.HasValue && letter != null; bool isTolling = message.IsTollingLetter; using (Data.CmoEntities context = new Data.CmoEntities()) { var tl = context.CmoTollingLetters.FirstOrDefault(l => l.CandidateId == message.CandidateID && l.MessageId == message.ID); if (tl != null) { if (isTolling) { tl.EventNumber = message.TollingEventNumber ?? int.MinValue; } else { context.DeleteObject(tl); } } else if (isTolling) { context.AddToCmoTollingLetters(Data.CmoTollingLetter.CreateCmoTollingLetter(candidateID, messageID, message.TollingEventNumber ?? int.MinValue, letter.ID)); } try { int updates = context.SaveChanges(); return(isTolling ? updates > 0 : !hasTolling); } catch (OptimisticConcurrencyException) { return(false); } } }
/// <summary> /// Retrieves a collection of post election events that affect tolling for the Draft Audit Report or Final Audit Report. /// </summary> /// <param name="candidateID">The ID of the candidate whose events are to be retrieved.</param> /// <param name="electionCycle">The election cycle in which to search.</param> /// <param name="far">true to retrieve events for the Final Audit Report; otherwise, false to retreive events for the Draft Audit Report.</param> /// <returns>A collection of tolling events that affect Draft Audit Report tolling.</returns> public List <TollingEvent> GetTollingEvents(string candidateID, string electionCycle, bool far) { DateTime?minStartDate = GetTollingStartDate(electionCycle); using (PostElectionTds ds = new PostElectionTds()) { using (TollingEventsTableAdapter ta = new TollingEventsTableAdapter()) { ta.Fill(ds.TollingEvents, candidateID, electionCycle, far); } List <TollingEvent> events = new List <TollingEvent>(ds.TollingEvents.Count); foreach (PostElectionTds.TollingEventsRow row in ds.TollingEvents) { if (row.IsStartDateNull()) { continue; } TollingLetter letter = GetTollingLetter(row.SourceCode.Trim(), row.EventCode.Trim(), row.TypeCode.Trim()) ?? new TollingLetter(byte.MinValue) { SourceCode = new TollingCode(TollingCodeType.SourceCode, byte.MinValue) { Code = row.SourceCode.Trim() }, EventCode = new TollingCode(TollingCodeType.EventCode, byte.MinValue) { Code = row.EventCode.Trim() }, TypeCode = new TollingCode(TollingCodeType.TypeCode, byte.MinValue) { Code = row.TypeCode.Trim() }, Description = row.Description, Title = row.Description }; // first fetch end reason to determine end date inclusion in tolling days TollingEndReason reason = CPConvert.ToTollingEndReason(row.EndReasonCode.Trim()); events.Add(new TollingEvent(row.StartDate, row.IsEndDateNull() ? DateTime.Now : row.EndDate) { Description = letter.Description, Title = letter.Title, TollingEventNumber = row.EventNumber, TollingLetter = letter, TollingStartDate = minStartDate.HasValue && row.StartDate < minStartDate ? minStartDate.Value : row.StartDate, TollingEndDate = row.IsEndDateNull() ? null : (DateTime?)row.EndDate, TollingDueDate = row.IsDueDateNull() ? null : (DateTime?)row.DueDate, TollingEndReason = reason, ReferenceEventNumber = row.RefEventNumber }); } return(events); } }
/// <summary> /// Directly posts a tolling letter to C-Access as a CMO message. /// </summary> /// <param name="electionCycle">The election cycle context of the letter to post.</param> /// <param name="candidateID">The ID of the candidate receipient of the letter to post.</param> /// <param name="eventNumber">The tolling event number.</param> /// <param name="source">The tolling event source code.</param> /// <param name="eventCode">The tolling event code.</param> /// <param name="type">The type of letter to post.</param> /// <param name="isSecondRequest">Whether or not the letter is a second request.</param> /// <param name="isRepost">Whether or not the letter is a repost.</param> /// <param name="creator">The network username of the user posting the letter.</param> /// <param name="title">The letter subject.</param> /// <param name="body">The letter body.</param> /// <param name="receiptEmail">The e-mail address for the recipient of open receipt e-mails.</param> /// <param name="path">The full UNC file path to the tolling letter attachment.</param> /// <param name="notify">Indicates whether to generate an e-mail notification to the campaign's C-Access accounts upon post.</param> /// <returns>The ID of the message if succesfully posted; otherwise, a negative value representing an error code.</returns> /// <exception cref="ArgumentNullException">Any parameters are null, except <paramref name="receiptEmail"/>.</exception> /// <remarks>If <paramref name="receiptEmail"/> is null, whitespace, or empty, the default e-mail address for the user specified by <paramref name="creator"/> will be retrieved from the network and used instead.</remarks> public int PostTollingLetter(string electionCycle, string candidateID, int eventNumber, string source, string eventCode, string type, bool isSecondRequest, bool isRepost, string creator, string title, string body, string receiptEmail, string path, bool notify) { TollingLetter letter = CPProviders.DataProvider.GetTollingLetter(source, eventCode, type); if (letter == null) { return(Convert.ToInt32(CmoServiceError.UnsupportedTollingLetter)); } return(PostLetter(electionCycle, candidateID, creator, title, body, receiptEmail, letter.GetCmoCategoryID(), notify, addAttachment : GetAddAttachmentEventHandler(candidateID, path), addPostElection : GetAddPostElectionEventHandler(isSecondRequest, isRepost), addTolling : delegate(CmoMessage message) { if (message == null || letter == null) { return false; } message.TollingLetter = letter; message.TollingEventNumber = eventNumber; return message.Update(); })); }
/// <summary> /// Retrieves a collection of post election events that affect tolling for the Draft Audit Report or Final Audit Report. /// </summary> /// <param name="candidateID">The ID of the candidate whose events are to be retrieved.</param> /// <param name="electionCycle">The election cycle in which to search.</param> /// <param name="far">true to retrieve events for the Final Audit Report; otherwise, false to retreive events for the Draft Audit Report.</param> /// <returns>A collection of tolling events that affect Draft Audit Report tolling.</returns> public List <ITollingEvent> GetTollingEvents(string candidateID, string electionCycle, bool far) { using (DataClient client = new DataClient()) { var events = client.GetTollingEvents(candidateID, electionCycle, far); List <ITollingEvent> tollingEvents = new List <ITollingEvent>(events != null ? events.Count : 0); // get inadequate events separately List <InadequateEventBase> inadequates = new List <InadequateEventBase>(); if (far) { foreach (var t in client.GetDarInadequateEvents(candidateID, electionCycle, InadequateEventRetrieval.AllEvents)) { inadequates.Add(t); tollingEvents.Add(t); } } else { foreach (var t in client.GetIdrInadequateEvents(candidateID, electionCycle, InadequateEventRetrieval.AllEvents)) { inadequates.Add(t); tollingEvents.Add(t); } } // collection of extensions for each inadequate vent type Dictionary <int, List <ITollingEvent> > allExtensions = new Dictionary <int, List <ITollingEvent> >(); // add remaining standard tolling events (latenesses, extensions) foreach (var t in events) { TollingLetter letter = t.TollingLetter; if (letter != null && letter.HasInadequateScope) { // add inadequate event to collection for matching reference inadequate event List <ITollingEvent> inadequateSourceEvents; if (!allExtensions.ContainsKey(t.ReferenceEventNumber)) { allExtensions.Add(t.ReferenceEventNumber, new List <ITollingEvent>()); } if (allExtensions.TryGetValue(t.ReferenceEventNumber, out inadequateSourceEvents)) { inadequateSourceEvents.Add(t); } } tollingEvents.Add(t); } // process extensions for inadequates foreach (var i in inadequates) { List <ITollingEvent> inadequateSourceEvents; if (allExtensions.TryGetValue(i.TollingEventNumber, out inadequateSourceEvents)) { i.LoadTollingEvents(inadequateSourceEvents); } } return(tollingEvents); } }
/// <summary> /// Sets tolling information for a tolling letter CMO message. /// </summary> /// <param name="candidateID">The ID of the candidate context.</param> /// <param name="messageID">The ID of the message to update.</param> /// <param name="eventNumber">The tolling letter event number.</param> /// <param name="letter">The tolling letter to set or clear.</param> /// <returns>true if the tolling letter codes were set successfully; otherwise, false.</returns> /// <remarks>The tolling letter codes can only be set if the message already exists and is of the tolling letter category.</remarks> public bool SetCmoMessageTolling(string candidateID, int messageID, int eventNumber, TollingLetter letter) { CmoMessage message = GetCmoMessage(candidateID, messageID); message.TollingLetter = letter; message.TollingEventNumber = eventNumber; return(SetCmoMessageTolling(message)); }
/// <summary> /// Retrieves a collection of Post Election Draft Audit Response Inadequate Response events for a specific candidate and election cycle. /// </summary> /// <param name="candidateID">The ID of the candidate whose DAR Inadequate Response events are to be retrieved.</param> /// <param name="electionCycle">The election cycle in which to search.</param> /// <param name="retrievalType">The type of inadequate event criteria to use for retrieval.</param> /// <returns>A collection of Post Election Draft Audit Response Inadequate Response events matching the specified criteria.</returns> public List <DarInadequateEvent> GetDarInadequateEvents(string candidateID, string electionCycle, InadequateEventRetrieval retrievalType) { // interpret retrieval type bool?additionals; switch (retrievalType) { case InadequateEventRetrieval.InitialEvent: additionals = false; break; case InadequateEventRetrieval.AdditionalEvents: additionals = true; break; default: additionals = null; break; } // determine minimum start date DateTime?minStartDate = GetTollingStartDate(electionCycle); // retrieve and parse data using (PostElectionTds ds = new PostElectionTds()) { using (InadequateEventsTableAdapter ta = new InadequateEventsTableAdapter()) { ta.Fill(ds.InadequateEvents, candidateID, electionCycle, true, additionals); } List <DarInadequateEvent> events = new List <DarInadequateEvent>(); foreach (PostElectionTds.InadequateEventsRow row in ds.InadequateEvents) { TollingLetter letter = GetTollingLetter(row.SourceCode.Trim(), row.EventCode.Trim(), row.TypeCode.Trim()) ?? new TollingLetter(byte.MinValue) { SourceCode = new TollingCode(TollingCodeType.SourceCode, byte.MinValue) { Code = row.SourceCode.Trim() }, EventCode = new TollingCode(TollingCodeType.EventCode, byte.MinValue) { Code = row.EventCode.Trim() }, TypeCode = new TollingCode(TollingCodeType.TypeCode, byte.MinValue) { Code = row.TypeCode.Trim() }, Description = row.Description, Title = row.Description }; // first fetch end reason to determine end date inclusion in tolling days TollingEndReason reason = CPConvert.ToTollingEndReason(row.EndReasonCode.Trim()); DarInadequateEvent inadequate = new DarInadequateEvent(row.SentDate, row.IsAdditionalFlagNull() ? false : row.AdditionalFlag) { ReceiptDate = row.IsReceiptDateNull() ? null : (DateTime?)row.ReceiptDate, SecondSentDate = row.IsSecondSentDateNull() ? null : (DateTime?)row.SecondSentDate, SecondReceiptDate = row.IsSecondReceiptDateNull() ? null : (DateTime?)row.SecondReceiptDate, ResponseSubmittedDate = row.IsResponseSubmittedDateNull() ? null : (DateTime?)row.ResponseSubmittedDate, // tolling event properties Description = letter.Description, Title = letter.Title, TollingEventNumber = row.EventNumber, TollingLetter = letter, TollingStartDate = minStartDate.HasValue && row.StartDate < minStartDate ? minStartDate.Value : row.StartDate, TollingEndDate = row.IsEndDateNull() ? null : (DateTime?)row.EndDate, TollingEndReason = reason }; inadequate.ResponseDeadline = new DarInadequateDeadline(row.DueDate, inadequate) { ResponseReceivedDate = row.IsResponseReceivedDateNull() ? null : (DateTime?)row.ResponseReceivedDate, SecondDueDate = row.IsSecondDueDateNull() ? null : (DateTime?)row.SecondDueDate }; events.Add(inadequate); } return(events); } }
/// <summary> /// Retrieves the Post Election Draft Audit Report Inadequate Response event for a specific candidate and election cycle. /// </summary> /// <param name="candidateID">The ID of the candidate whose DAR Inadequate Response event is to be retrieved.</param> /// <param name="electionCycle">The election cycle in which to search.</param> /// <param name="published">Whether or not to retrieve published data.</param> /// <returns>The Post Election Draft Audit Report Inadequate Response event for the candidate and election cycle specified if found; otherwise, null.</returns> public DarInadequateEvent GetDarInadequateEvent(string candidateID, string electionCycle, bool published) { DarInadequateEvent inadequate = null; using (PostElectionTds ds = new PostElectionTds()) { if (published) { DateTime?minStartDate = GetTollingStartDate(electionCycle); using (InadequateEventsTableAdapter ta = new InadequateEventsTableAdapter()) { ta.Fill(ds.InadequateEvents, candidateID, electionCycle, true, false); } foreach (PostElectionTds.InadequateEventsRow row in ds.InadequateEvents) { TollingLetter letter = GetTollingLetter(row.SourceCode.Trim(), row.EventCode.Trim(), row.TypeCode.Trim()) ?? new TollingLetter(byte.MinValue) { SourceCode = new TollingCode(TollingCodeType.SourceCode, byte.MinValue) { Code = row.SourceCode.Trim() }, EventCode = new TollingCode(TollingCodeType.EventCode, byte.MinValue) { Code = row.EventCode.Trim() }, TypeCode = new TollingCode(TollingCodeType.TypeCode, byte.MinValue) { Code = row.TypeCode.Trim() }, Description = row.Description, Title = row.Description }; // first fetch end reason to determine end date inclusion in tolling days TollingEndReason reason = CPConvert.ToTollingEndReason(row.EndReasonCode.Trim()); inadequate = new DarInadequateEvent(row.SentDate) { ReceiptDate = row.IsReceiptDateNull() ? null : (DateTime?)row.ReceiptDate, SecondSentDate = row.IsSecondSentDateNull() ? null : (DateTime?)row.SecondSentDate, SecondReceiptDate = row.IsSecondReceiptDateNull() ? null : (DateTime?)row.SecondReceiptDate, ResponseSubmittedDate = row.IsResponseSubmittedDateNull() ? null : (DateTime?)row.ResponseSubmittedDate, // tolling event properties Description = letter.Description, Title = letter.Title, TollingEventNumber = row.EventNumber, TollingLetter = letter, TollingStartDate = minStartDate.HasValue && row.StartDate < minStartDate ? minStartDate.Value : row.StartDate, TollingEndDate = row.IsEndDateNull() ? null : (DateTime?)row.EndDate, TollingEndReason = reason }; inadequate.ResponseDeadline = new DarInadequateDeadline(row.DueDate, inadequate) { ResponseReceivedDate = row.IsResponseReceivedDateNull() ? null : (DateTime?)row.ResponseReceivedDate, SecondDueDate = row.IsSecondDueDateNull() ? null : (DateTime?)row.SecondDueDate }; break; } } else { using (InadequateEventsDirectTableAdapter ta = new InadequateEventsDirectTableAdapter()) { ta.Fill(ds.InadequateEventsDirect, candidateID, electionCycle, true, false); } foreach (PostElectionTds.InadequateEventsDirectRow row in ds.InadequateEventsDirect) { inadequate = new DarInadequateEvent(row.SentDate) { ReceiptDate = row.IsReceiptDateNull() ? null : (DateTime?)row.ReceiptDate, SecondSentDate = row.IsSecondSentDateNull() ? null : (DateTime?)row.SecondSentDate, SecondReceiptDate = row.IsSecondReceiptDateNull() ? null : (DateTime?)row.SecondReceiptDate, ResponseSubmittedDate = row.IsResponseSubmittedDateNull() ? null : (DateTime?)row.ResponseSubmittedDate, }; inadequate.ResponseDeadline = new DarInadequateDeadline(row.DueDate, inadequate) { ResponseReceivedDate = row.IsResponseReceivedDateNull() ? null : (DateTime?)row.ResponseReceivedDate, SecondDueDate = row.IsSecondDueDateNull() ? null : (DateTime?)row.SecondDueDate }; break; } } } return(inadequate); }