/// <summary> /// Set the SourceOfChange property for the entries in a HistoryChangeList. /// </summary> /// <param name="changes"></param> /// <param name="newSourceOfChange"></param> /// <param name="overrideExisting"></param> private static void SetHistoryEntriesSourceOfChange(History.HistoryChangeList changes, string newSourceOfChange, bool overrideExisting) { // Set the SourceOfChange property for any entries that do not have an existing value, or for all entries if the override flag is set. changes.Where(x => x.SourceOfChange == null || overrideExisting) .ToList() .ForEach(a => a.SourceOfChange = newSourceOfChange); }
public static void AddMoveHistory(RockContext rockContext, Location location, Attendance attendeeAttendance, bool isSubroom) { var moveSummary = string.Format("{0}</span> at <span class=\"field-name\">{1}", location.Name, Rock.RockDateTime.Now); if (isSubroom) { moveSummary += string.Format("</span> (a subroom of <span class=\"field-name\">{0})", location.ParentLocation.Name); } var changes = new History.HistoryChangeList(); changes.AddCustom("Entry", History.HistoryChangeType.Record.ToString(), moveSummary.Truncate(250)); changes.First().Caption = "Moved To Location"; changes.First().RelatedEntityTypeId = locationEntityTypeId; changes.First().RelatedEntityId = location.Id; changes.First().RelatedData = GetHostInfo(); HistoryService.SaveChanges( rockContext, typeof(Rock.Model.Person), CategoryCache.Get(4).Guid, attendeeAttendance.PersonAlias.PersonId, changes, true ); }
public static void AddChanges(RockContext rockContext, Type modelType, Guid categoryGuid, int entityId, List <string> changes, string caption, Type relatedModelType, int?relatedEntityId, int?modifiedByPersonAliasId = null) { var historyChanges = new History.HistoryChangeList(); historyChanges.AddRange(changes.Select(a => new History.HistoryChange(a)).ToList()); AddChanges(rockContext, modelType, categoryGuid, entityId, historyChanges, caption, relatedModelType, relatedEntityId, modifiedByPersonAliasId); }
/// <summary> /// Method that will be called on an entity immediately before the item is saved by context /// </summary> /// <param name="dbContext"></param> /// <param name="entry"></param> public override void PreSaveChanges(Rock.Data.DbContext dbContext, DbEntityEntry entry) { var rockContext = ( RockContext )dbContext; HistoryChangeList = new History.HistoryChangeList(); var scheduledTransaction = this.ScheduledTransaction ?? new FinancialScheduledTransactionService(dbContext as RockContext).Get(this.ScheduledTransactionId); switch (entry.State) { case EntityState.Added: { string acct = History.GetValue <FinancialAccount>(this.Account, this.AccountId, rockContext); HistoryChangeList.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, acct).SetNewValue(Amount.FormatAsCurrency(scheduledTransaction?.ForeignCurrencyCodeValueId)); break; } case EntityState.Modified: { string acct = History.GetValue <FinancialAccount>(this.Account, this.AccountId, rockContext); int?accountId = this.Account != null ? this.Account.Id : this.AccountId; int?origAccountId = entry.OriginalValues["AccountId"].ToStringSafe().AsIntegerOrNull(); if (!accountId.Equals(origAccountId)) { History.EvaluateChange(HistoryChangeList, "Account", History.GetValue <FinancialAccount>(null, origAccountId, rockContext), acct); } var originalCurrencyCodeValueId = scheduledTransaction?.ForeignCurrencyCodeValueId; if (scheduledTransaction != null) { var originalScheduledTransactionEntry = rockContext.ChangeTracker .Entries <FinancialScheduledTransaction>() .Where(s => ( int )s.OriginalValues["Id"] == scheduledTransaction.Id) .FirstOrDefault(); if (originalScheduledTransactionEntry != null) { originalCurrencyCodeValueId = ( int? )originalScheduledTransactionEntry.OriginalValues["ForeignCurrencyCodeValueId"]; } } History.EvaluateChange(HistoryChangeList, acct + " Amount", entry.OriginalValues["Amount"].ToStringSafe().AsDecimal().FormatAsCurrency(originalCurrencyCodeValueId), Amount.FormatAsCurrency(scheduledTransaction?.ForeignCurrencyCodeValueId)); History.EvaluateChange(HistoryChangeList, acct + " Fee Coverage Amount", (entry.OriginalValues["FeeCoverageAmount"] as int?).FormatAsCurrency(), FeeCoverageAmount.FormatAsCurrency()); break; } case EntityState.Deleted: { string acct = History.GetValue <FinancialAccount>(this.Account, this.AccountId, rockContext); HistoryChangeList.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, acct).SetOldValue(Amount.FormatAsCurrency(scheduledTransaction?.ForeignCurrencyCodeValueId)); break; } } base.PreSaveChanges(dbContext, entry); }
/// <summary> /// Method that will be called on an entity immediately before the item is saved by context /// </summary> /// <param name="dbContext"></param> /// <param name="entry"></param> public override void PreSaveChanges(Data.DbContext dbContext, DbEntityEntry entry) { var rockContext = (RockContext)dbContext; GroupHistoryChanges = new History.HistoryChangeList(); switch (entry.State) { case EntityState.Added: { string locationType = History.GetDefinedValueValue(null, GroupLocationTypeValueId); locationType = locationType.IsNotNullOrWhiteSpace() ? locationType : "Unknown"; History.EvaluateChange(GroupHistoryChanges, $"{locationType} Location", (int?)null, Location, LocationId, rockContext); History.EvaluateChange(GroupHistoryChanges, $"{locationType} Is Mailing", false, IsMailingLocation); History.EvaluateChange(GroupHistoryChanges, $"{locationType} Is Map Location", false, IsMappedLocation); break; } case EntityState.Modified: { string locationTypeName = DefinedValueCache.GetName(GroupLocationTypeValueId) ?? "Unknown"; int? oldLocationTypeId = entry.OriginalValues["GroupLocationTypeValueId"].ToStringSafe().AsIntegerOrNull(); if ((oldLocationTypeId ?? 0) == (GroupLocationTypeValueId ?? 0)) { History.EvaluateChange(GroupHistoryChanges, $"{locationTypeName} Location", entry.OriginalValues["LocationId"].ToStringSafe().AsIntegerOrNull(), Location, LocationId, rockContext); } else { Location newLocation = null; History.EvaluateChange(GroupHistoryChanges, $"{DefinedValueCache.GetName( oldLocationTypeId ) ?? "Unknown"} Location", entry.OriginalValues["LocationId"].ToStringSafe().AsIntegerOrNull(), newLocation, (int?)null, rockContext); History.EvaluateChange(GroupHistoryChanges, $"{locationTypeName} Location", (int?)null, Location, LocationId, rockContext); } History.EvaluateChange(GroupHistoryChanges, $"{locationTypeName} Is Mailing", entry.OriginalValues["IsMailingLocation"].ToStringSafe().AsBoolean(), IsMailingLocation); History.EvaluateChange(GroupHistoryChanges, $"{locationTypeName} Is Map Location", entry.OriginalValues["IsMappedLocation"].ToStringSafe().AsBoolean(), IsMappedLocation); break; } case EntityState.Deleted: { string locationType = History.GetDefinedValueValue(null, entry.OriginalValues["GroupLocationTypeValueId"].ToStringSafe().AsIntegerOrNull()); locationType = locationType.IsNotNullOrWhiteSpace() ? locationType : "Unknown"; Location loc = null; History.EvaluateChange(GroupHistoryChanges, $"{locationType} Location", entry.OriginalValues["LocationId"].ToStringSafe().AsIntegerOrNull(), loc, (int?)null, rockContext); break; } } base.PreSaveChanges(dbContext, entry); }
/// <summary> /// Called before the save operation is executed. /// </summary> protected override void PreSave() { var rockContext = ( RockContext )this.RockContext; GroupHistoryChanges = new History.HistoryChangeList(); switch (State) { case EntityContextState.Added: { string locationType = History.GetDefinedValueValue(null, Entity.GroupLocationTypeValueId); locationType = locationType.IsNotNullOrWhiteSpace() ? locationType : "Unknown"; History.EvaluateChange(GroupHistoryChanges, $"{locationType} Location", ( int? )null, Entity.Location, Entity.LocationId, rockContext); History.EvaluateChange(GroupHistoryChanges, $"{locationType} Is Mailing", false, Entity.IsMailingLocation); History.EvaluateChange(GroupHistoryChanges, $"{locationType} Is Map Location", false, Entity.IsMappedLocation); break; } case EntityContextState.Modified: { string locationTypeName = DefinedValueCache.GetName(Entity.GroupLocationTypeValueId) ?? "Unknown"; int? oldLocationTypeId = OriginalValues[nameof(GroupLocation.GroupLocationTypeValueId)].ToStringSafe().AsIntegerOrNull(); if ((oldLocationTypeId ?? 0) == (Entity.GroupLocationTypeValueId ?? 0)) { History.EvaluateChange(GroupHistoryChanges, $"{locationTypeName} Location", OriginalValues[nameof(GroupLocation.LocationId)].ToStringSafe().AsIntegerOrNull(), Entity.Location, Entity.LocationId, rockContext); } else { Location newLocation = null; History.EvaluateChange(GroupHistoryChanges, $"{DefinedValueCache.GetName( oldLocationTypeId ) ?? "Unknown"} Location", OriginalValues[nameof(GroupLocation.LocationId)].ToStringSafe().AsIntegerOrNull(), newLocation, ( int? )null, rockContext); History.EvaluateChange(GroupHistoryChanges, $"{locationTypeName} Location", ( int? )null, Entity.Location, Entity.LocationId, rockContext); } History.EvaluateChange(GroupHistoryChanges, $"{locationTypeName} Is Mailing", OriginalValues[nameof(GroupLocation.IsMailingLocation)].ToStringSafe().AsBoolean(), Entity.IsMailingLocation); History.EvaluateChange(GroupHistoryChanges, $"{locationTypeName} Is Map Location", OriginalValues[nameof(GroupLocation.IsMappedLocation)].ToStringSafe().AsBoolean(), Entity.IsMappedLocation); break; } case EntityContextState.Deleted: { string locationType = History.GetDefinedValueValue(null, OriginalValues[nameof(GroupLocation.GroupLocationTypeValueId)].ToStringSafe().AsIntegerOrNull()); locationType = locationType.IsNotNullOrWhiteSpace() ? locationType : "Unknown"; Location loc = null; History.EvaluateChange(GroupHistoryChanges, $"{locationType} Location", OriginalValues[nameof(GroupLocation.LocationId)].ToStringSafe().AsIntegerOrNull(), loc, ( int? )null, rockContext); break; } } base.PreSave(); }
/// <summary> /// Pres the save. /// </summary> /// <param name="dbContext">The database context.</param> /// <param name="entry"></param> public override void PreSaveChanges(Rock.Data.DbContext dbContext, DbEntityEntry entry) { var rockContext = (RockContext)dbContext; BinaryFileService binaryFileService = new BinaryFileService(rockContext); var binaryFile = binaryFileService.Get(BinaryFileId); HistoryChangeList = new History.HistoryChangeList(); switch (entry.State) { case EntityState.Added: { // if there is an binaryfile (image) associated with this, make sure that it is flagged as IsTemporary=False if (binaryFile.IsTemporary) { binaryFile.IsTemporary = false; } HistoryChangeList.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, "Image"); break; } case EntityState.Modified: { // if there is an binaryfile (image) associated with this, make sure that it is flagged as IsTemporary=False if (binaryFile.IsTemporary) { binaryFile.IsTemporary = false; } HistoryChangeList.AddChange(History.HistoryVerb.Modify, History.HistoryChangeType.Record, "Image"); break; } case EntityState.Deleted: { // if deleting, and there is an binaryfile (image) associated with this, make sure that it is flagged as IsTemporary=true // so that it'll get cleaned up if (!binaryFile.IsTemporary) { binaryFile.IsTemporary = true; } HistoryChangeList.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, "Image"); break; } } base.PreSaveChanges(dbContext, entry); }
public bool ParseEndpointResponse(XmlDocument xmlDocument, int BatchId, bool Log = false) { var resultX = XDocument.Load(new XmlNodeReader(xmlDocument)); if (Log) { var financialBatch = new FinancialBatchService(new RockContext()).Get(BatchId); var changes = new History.HistoryChangeList(); var oldValue = string.Empty; var newValue = resultX.ToString(); History.EvaluateChange(changes, "Intacct Response", oldValue, newValue); var rockContext = new RockContext(); rockContext.WrapTransaction(() => { if (changes.Any()) { HistoryService.SaveChanges( rockContext, typeof(FinancialBatch), Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(), BatchId, changes); } }); } var xResponseXml = resultX.Elements("response").FirstOrDefault(); if (xResponseXml != null) { var xOperationXml = xResponseXml.Elements("operation").FirstOrDefault(); if (xOperationXml != null) { var xResultXml = xOperationXml.Elements("result").FirstOrDefault(); if (xResultXml != null) { var xStatusXml = xResultXml.Elements("status").FirstOrDefault(); if (xStatusXml != null && xStatusXml.Value == "success") { return(true); } } } } return(false); }
/// <summary> /// Handles the Delete event of the gRegistrations control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="RowEventArgs"/> instance containing the event data.</param> protected void gRegistrations_Delete(object sender, RowEventArgs e) { using (var rockContext = new RockContext()) { var registrationService = new RegistrationService(rockContext); var registration = registrationService.Get(e.RowKeyId); if (registration != null) { int registrationInstanceId = registration.RegistrationInstanceId; if (!UserCanEdit && !registration.IsAuthorized("Register", CurrentPerson) && !registration.IsAuthorized(Authorization.EDIT, this.CurrentPerson) && !registration.IsAuthorized(Authorization.ADMINISTRATE, this.CurrentPerson)) { mdDeleteWarning.Show("You are not authorized to delete this registration.", ModalAlertType.Information); return; } string errorMessage; if (!registrationService.CanDelete(registration, out errorMessage)) { mdRegistrationsGridWarning.Show(errorMessage, ModalAlertType.Information); return; } var changes = new History.HistoryChangeList(); changes.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, "Registration"); rockContext.WrapTransaction(() => { HistoryService.SaveChanges( rockContext, typeof(Registration), Rock.SystemGuid.Category.HISTORY_EVENT_REGISTRATION.AsGuid(), registration.Id, changes); registrationService.Delete(registration); rockContext.SaveChanges(); }); hfHasPayments.Value = this.RegistrationInstanceHasPayments.ToString(); } } BindRegistrationsGrid(); }
/// <summary> /// Handles the Delete event of the gBatchList control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="RowEventArgs"/> instance containing the event data.</param> protected void gBatchList_Delete(object sender, RowEventArgs e) { var rockContext = new RockContext(); var batchService = new FinancialBatchService(rockContext); var transactionService = new FinancialTransactionService(rockContext); var batch = batchService.Get(e.RowKeyId); if (batch != null) { if (batch.IsAuthorized(Rock.Security.Authorization.DELETE, CurrentPerson)) { string errorMessage; if (!batchService.CanDelete(batch, out errorMessage)) { mdGridWarning.Show(errorMessage, ModalAlertType.Information); return; } rockContext.WrapTransaction(() => { foreach (var txn in transactionService.Queryable() .Where(t => t.BatchId == batch.Id)) { transactionService.Delete(txn); } var changes = new History.HistoryChangeList(); changes.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, "Batch"); HistoryService.SaveChanges( rockContext, typeof(FinancialBatch), Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(), batch.Id, changes); batchService.Delete(batch); rockContext.SaveChanges(); }); } else { mdGridWarning.Show("You are not authorized to delete the selected batch.", ModalAlertType.Warning); } } BindGrid(); }
protected void btnRemoveDateExported_Click(object sender, EventArgs e) { if (_financialBatch != null) { var rockContext = new RockContext(); var financialBatch = new FinancialBatchService(rockContext).Get(_batchId); var changes = new History.HistoryChangeList(); // // Open Batch is we Closed it // if (GetAttributeValue("CloseBatch").AsBoolean()) { History.EvaluateChange(changes, "Status", financialBatch.Status, BatchStatus.Open); financialBatch.Status = BatchStatus.Open; } // // Remove Date Exported // financialBatch.LoadAttributes(); var oldDate = financialBatch.GetAttributeValue("rocks.kfs.ShelbyFinancials.DateExported").AsDateTime().ToString(); var newDate = string.Empty; History.EvaluateChange(changes, "Date Exported", oldDate, newDate); // // Save the changes // rockContext.WrapTransaction(() => { if (changes.Any()) { HistoryService.SaveChanges( rockContext, typeof(FinancialBatch), Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(), financialBatch.Id, changes); } }); financialBatch.SetAttributeValue("rocks.kfs.ShelbyFinancials.DateExported", newDate); financialBatch.SaveAttributeValue("rocks.kfs.ShelbyFinancials.DateExported", rockContext); } Response.Redirect(Request.RawUrl); }
/// <summary> /// Method that will be called on an entity immediately after the item is saved /// </summary> /// <param name="dbContext">The database context.</param> public override void PostSaveChanges(Data.DbContext dbContext) { if (HistoryChangeList.Any()) { HistoryService.SaveChanges(( RockContext )dbContext, typeof(FinancialTransaction), Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(), this.TransactionId, HistoryChangeList, true, this.ModifiedByPersonAliasId); var txn = new FinancialTransactionService(( RockContext )dbContext).GetSelect(this.TransactionId, s => new { s.Id, s.BatchId }); if (txn != null && txn.BatchId != null) { var batchHistory = new History.HistoryChangeList(); batchHistory.AddChange(History.HistoryVerb.Modify, History.HistoryChangeType.Record, $"Transaction ID:{txn.Id}"); HistoryService.SaveChanges(( RockContext )dbContext, typeof(FinancialBatch), Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(), txn.BatchId.Value, batchHistory, string.Empty, typeof(FinancialTransaction), this.TransactionId, true, this.ModifiedByPersonAliasId, dbContext.SourceOfChange); } } base.PostSaveChanges(dbContext); }
/// <summary> /// Method that will be called on an entity immediately before the item is saved by context /// </summary> /// <param name="dbContext"></param> /// <param name="entry"></param> public override void PreSaveChanges(Rock.Data.DbContext dbContext, DbEntityEntry entry) { var rockContext = (RockContext)dbContext; HistoryChangeList = new History.HistoryChangeList(); switch (entry.State) { case EntityState.Added: { History.EvaluateChange(HistoryChangeList, "Account Number", string.Empty, AccountNumberMasked); History.EvaluateChange(HistoryChangeList, "Currency Type", (int?)null, CurrencyTypeValue, CurrencyTypeValueId); History.EvaluateChange(HistoryChangeList, "Credit Card Type", (int?)null, CreditCardTypeValue, CreditCardTypeValueId); History.EvaluateChange(HistoryChangeList, "Name On Card", string.Empty, AccountNumberMasked, true); History.EvaluateChange(HistoryChangeList, "Expiration Month", string.Empty, ExpirationMonthEncrypted, true); History.EvaluateChange(HistoryChangeList, "Expiration Year", string.Empty, ExpirationYearEncrypted, true); History.EvaluateChange(HistoryChangeList, "Billing Location", string.Empty, History.GetValue <Location>(BillingLocation, BillingLocationId, rockContext)); break; } case EntityState.Modified: case EntityState.Deleted: { History.EvaluateChange(HistoryChangeList, "Account Number", entry.OriginalValues["AccountNumberMasked"].ToStringSafe(), AccountNumberMasked); History.EvaluateChange(HistoryChangeList, "Currency Type", entry.OriginalValues["CurrencyTypeValueId"].ToStringSafe().AsIntegerOrNull(), CurrencyTypeValue, CurrencyTypeValueId); History.EvaluateChange(HistoryChangeList, "Credit Card Type", entry.OriginalValues["CreditCardTypeValueId"].ToStringSafe().AsIntegerOrNull(), CreditCardTypeValue, CreditCardTypeValueId); History.EvaluateChange(HistoryChangeList, "Name On Card", entry.OriginalValues["AccountNumberMasked"].ToStringSafe(), AccountNumberMasked, true); History.EvaluateChange(HistoryChangeList, "Expiration Month", entry.OriginalValues["ExpirationMonthEncrypted"].ToStringSafe(), ExpirationMonthEncrypted, true); History.EvaluateChange(HistoryChangeList, "Expiration Year", entry.OriginalValues["ExpirationYearEncrypted"].ToStringSafe(), ExpirationYearEncrypted, true); History.EvaluateChange(HistoryChangeList, "Billing Location", History.GetValue <Location>(null, entry.OriginalValues["BillingLocationId"].ToStringSafe().AsIntegerOrNull(), rockContext), History.GetValue <Location>(BillingLocation, BillingLocationId, rockContext)); break; } } if (entry.State == EntityState.Added || entry.State == EntityState.Modified) { // Ensure that CurrencyTypeValueId is set. The UI tries to prevent it, but just in case, if it isn't, set it to Unknown if (!this.CurrencyTypeValueId.HasValue) { this.CurrencyTypeValueId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_UNKNOWN.AsGuid())?.Id; } } base.PreSaveChanges(dbContext, entry); }
/// <summary> /// Method that will be called on an entity immediately after the item is saved by context /// </summary> /// <param name="dbContext">The database context.</param> public override void PostSaveChanges(Data.DbContext dbContext) { if (HistoryChangeList.Any()) { foreach (var txn in new FinancialTransactionService((RockContext)dbContext) .Queryable().AsNoTracking() .Where(t => t.FinancialPaymentDetailId == this.Id) .Select(t => new { t.Id, t.BatchId }) .ToList()) { HistoryService.SaveChanges((RockContext)dbContext, typeof(FinancialTransaction), Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(), txn.Id, HistoryChangeList, true, this.ModifiedByPersonAliasId, dbContext.SourceOfChange); var batchHistory = new History.HistoryChangeList(); batchHistory.AddChange(History.HistoryVerb.Modify, History.HistoryChangeType.Property, "Transaction"); HistoryService.SaveChanges((RockContext)dbContext, typeof(FinancialBatch), Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(), txn.BatchId.Value, batchHistory, string.Empty, typeof(FinancialTransaction), txn.Id, true, this.ModifiedByPersonAliasId, dbContext.SourceOfChange); } } base.PostSaveChanges(dbContext); }
/// <summary> /// Method that will be called on an entity immediately before the item is saved by context /// </summary> /// <param name="dbContext"></param> /// <param name="entry"></param> public override void PreSaveChanges(Rock.Data.DbContext dbContext, DbEntityEntry entry) { var rockContext = ( RockContext )dbContext; HistoryChangeList = new History.HistoryChangeList(); switch (entry.State) { case EntityState.Added: { string acct = History.GetValue <FinancialAccount>(this.Account, this.AccountId, rockContext); HistoryChangeList.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, acct).SetNewValue(Amount.FormatAsCurrency()); break; } case EntityState.Modified: { string acct = History.GetValue <FinancialAccount>(this.Account, this.AccountId, rockContext); int?accountId = this.Account != null ? this.Account.Id : this.AccountId; int?origAccountId = entry.OriginalValues["AccountId"].ToStringSafe().AsIntegerOrNull(); if (!accountId.Equals(origAccountId)) { History.EvaluateChange(HistoryChangeList, "Account", History.GetValue <FinancialAccount>(null, origAccountId, rockContext), acct); } History.EvaluateChange(HistoryChangeList, acct, entry.OriginalValues["Amount"].ToStringSafe().AsDecimal().FormatAsCurrency(), Amount.FormatAsCurrency()); History.EvaluateChange(HistoryChangeList, acct, entry.OriginalValues["FeeAmount"].ToStringSafe().AsDecimal().FormatAsCurrency(), FeeAmount.FormatAsCurrency()); History.EvaluateChange(HistoryChangeList, acct, entry.OriginalValues["FeeCoverageAmount"].ToStringSafe().AsDecimal().FormatAsCurrency(), FeeCoverageAmount.FormatAsCurrency()); break; } case EntityState.Deleted: { string acct = History.GetValue <FinancialAccount>(this.Account, this.AccountId, rockContext); HistoryChangeList.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, acct).SetOldValue(Amount.FormatAsCurrency()); break; } } base.PreSaveChanges(dbContext, entry); }
/// <summary> /// Method that will be called on an entity immediately before the item is saved by context /// </summary> /// <param name="dbContext"></param> /// <param name="entry"></param> public override void PreSaveChanges( DbContext dbContext, DbEntityEntry entry ) { var rockContext = (RockContext)dbContext; HistoryPersonId = PersonAlias != null ? PersonAlias.PersonId : (int?)null; if ( !HistoryPersonId.HasValue ) { var personAlias = new PersonAliasService( rockContext ).Get( PersonAliasId ); if ( personAlias != null ) { HistoryPersonId = personAlias.PersonId; } } if ( HistoryPersonId.HasValue ) { HistoryChanges = new History.HistoryChangeList(); switch ( entry.State ) { case System.Data.Entity.EntityState.Added: { History.EvaluateChange( HistoryChanges, "Previous Name", string.Empty, LastName ); break; } case System.Data.Entity.EntityState.Modified: { History.EvaluateChange( HistoryChanges, "Previous Name", entry.OriginalValues["LastName"].ToStringSafe(), LastName ); break; } case System.Data.Entity.EntityState.Deleted: { History.EvaluateChange( HistoryChanges, "Previous Name", entry.OriginalValues["LastName"].ToStringSafe(), string.Empty ); return; } } } base.PreSaveChanges( dbContext, entry ); }
/// <summary> /// Called before the save operation is executed. /// </summary> protected override void PreSave() { var rockContext = ( RockContext )this.RockContext; HistoryPersonId = Entity.PersonAlias != null ? Entity.PersonAlias.PersonId : ( int? )null; if (!HistoryPersonId.HasValue) { var personAlias = new PersonAliasService(rockContext).Get(Entity.PersonAliasId); if (personAlias != null) { HistoryPersonId = personAlias.PersonId; } } if (HistoryPersonId.HasValue) { HistoryChanges = new History.HistoryChangeList(); switch (State) { case EntityContextState.Added: { History.EvaluateChange(HistoryChanges, "Previous Name", string.Empty, Entity.LastName); break; } case EntityContextState.Modified: { History.EvaluateChange(HistoryChanges, "Previous Name", OriginalValues[nameof(PersonPreviousName.LastName)].ToStringSafe(), Entity.LastName); break; } case EntityContextState.Deleted: { History.EvaluateChange(HistoryChanges, "Previous Name", Entity.LastName, string.Empty); return; } } } base.PreSave(); }
public static void AddWithParentHistory(RockContext rockContext, Person person) { var summary = string.Format("</span> to be with Parent at <span class=\"field-name\">{0}", Rock.RockDateTime.Now); var changes = new History.HistoryChangeList(); changes.AddCustom("Moved", History.HistoryChangeType.Record.ToString(), summary.Truncate(250)); changes.First().Caption = "Moved be with Parent"; changes.First().RelatedData = GetHostInfo(); HistoryService.SaveChanges( rockContext, typeof(Rock.Model.Person), CategoryCache.Get(4).Guid, person.Id, changes, true ); AttendanceCache.SetWithParent(person.Id); }
/// <summary> /// Handles the Delete event of the gTransactionEntities control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="RowEventArgs"/> instance containing the event data.</param> protected void gTransactionEntities_Delete(object sender, RowEventArgs e) { var rockContext = new RockContext(); var service = new FinancialTransactionDetailService(rockContext); var detail = service.Get(e.RowKeyId); if (detail == null) { return; } else { var changes = new History.HistoryChangeList(); var typeName = detail.EntityType.FriendlyName; var name = GetEntityName(detail.EntityTypeId, detail.EntityId, rockContext); History.EvaluateChange(changes, "Entity Type Id", detail.EntityTypeId, null); History.EvaluateChange(changes, "Entity Id", detail.EntityId, null); detail.EntityTypeId = null; detail.EntityId = null; changes.AddCustom("Removed", "Removed", string.Format("Removed transaction detail association to {0} {1}", typeName, name)); HistoryService.SaveChanges( rockContext, typeof(FinancialTransaction), Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(), detail.TransactionId, changes ); rockContext.SaveChanges(); } BindGrid(); }
/// <summary> /// Pres the save. /// </summary> /// <param name="dbContext">The database context.</param> /// <param name="entry"></param> public override void PreSaveChanges(Rock.Data.DbContext dbContext, System.Data.Entity.Infrastructure.DbEntityEntry entry) { var rockContext = (RockContext)dbContext; HistoryChangeList = new History.HistoryChangeList(); BatchHistoryChangeList = new Dictionary <int, History.HistoryChangeList> (); switch (entry.State) { case System.Data.Entity.EntityState.Added: { HistoryChangeList.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, "Transaction"); string person = History.GetValue <PersonAlias>(AuthorizedPersonAlias, AuthorizedPersonAliasId, rockContext); History.EvaluateChange(HistoryChangeList, "Authorized Person", string.Empty, person); History.EvaluateChange(HistoryChangeList, "Batch", string.Empty, History.GetValue <FinancialBatch>(Batch, BatchId, rockContext)); History.EvaluateChange(HistoryChangeList, "Gateway", string.Empty, History.GetValue <FinancialGateway>(FinancialGateway, FinancialGatewayId, rockContext)); History.EvaluateChange(HistoryChangeList, "Transaction Date/Time", (DateTime?)null, TransactionDateTime); History.EvaluateChange(HistoryChangeList, "Transaction Code", string.Empty, TransactionCode); History.EvaluateChange(HistoryChangeList, "Summary", string.Empty, Summary); History.EvaluateChange(HistoryChangeList, "Type", (int?)null, TransactionTypeValue, TransactionTypeValueId); History.EvaluateChange(HistoryChangeList, "Source", (int?)null, SourceTypeValue, SourceTypeValueId); History.EvaluateChange(HistoryChangeList, "Scheduled Transaction Id", (int?)null, ScheduledTransactionId); History.EvaluateChange(HistoryChangeList, "Processed By", string.Empty, History.GetValue <PersonAlias>(ProcessedByPersonAlias, ProcessedByPersonAliasId, rockContext)); History.EvaluateChange(HistoryChangeList, "Processed Date/Time", (DateTime?)null, ProcessedDateTime); History.EvaluateChange(HistoryChangeList, "Status", string.Empty, Status); History.EvaluateChange(HistoryChangeList, "Status Message", string.Empty, StatusMessage); int?batchId = Batch != null ? Batch.Id : BatchId; if (batchId.HasValue) { var batchChanges = new History.HistoryChangeList(); batchChanges.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, "Transaction").SetNewValue($"{this.TotalAmount.FormatAsCurrency()} for {person}"); BatchHistoryChangeList.Add(batchId.Value, batchChanges); } break; } case System.Data.Entity.EntityState.Modified: { string origPerson = History.GetValue <PersonAlias>(null, entry.OriginalValues["AuthorizedPersonAliasId"].ToStringSafe().AsIntegerOrNull(), rockContext); string person = History.GetValue <PersonAlias>(AuthorizedPersonAlias, AuthorizedPersonAliasId, rockContext); History.EvaluateChange(HistoryChangeList, "Authorized Person", origPerson, person); int?origBatchId = entry.OriginalValues["BatchId"].ToStringSafe().AsIntegerOrNull(); int?batchId = Batch != null ? Batch.Id : BatchId; if (!batchId.Equals(origBatchId)) { string origBatch = History.GetValue <FinancialBatch>(null, origBatchId, rockContext); string batch = History.GetValue <FinancialBatch>(Batch, BatchId, rockContext); History.EvaluateChange(HistoryChangeList, "Batch", origBatch, batch); } int?origGatewayId = entry.OriginalValues["FinancialGatewayId"].ToStringSafe().AsIntegerOrNull(); if (!FinancialGatewayId.Equals(origGatewayId)) { History.EvaluateChange(HistoryChangeList, "Gateway", History.GetValue <FinancialGateway>(null, origGatewayId, rockContext), History.GetValue <FinancialGateway>(FinancialGateway, FinancialGatewayId, rockContext)); } History.EvaluateChange(HistoryChangeList, "Transaction Date/Time", entry.OriginalValues["TransactionDateTime"].ToStringSafe().AsDateTime(), TransactionDateTime); History.EvaluateChange(HistoryChangeList, "Transaction Code", entry.OriginalValues["TransactionCode"].ToStringSafe(), TransactionCode); History.EvaluateChange(HistoryChangeList, "Summary", entry.OriginalValues["Summary"].ToStringSafe(), Summary); History.EvaluateChange(HistoryChangeList, "Type", entry.OriginalValues["TransactionTypeValueId"].ToStringSafe().AsIntegerOrNull(), TransactionTypeValue, TransactionTypeValueId); History.EvaluateChange(HistoryChangeList, "Source", entry.OriginalValues["SourceTypeValueId"].ToStringSafe().AsIntegerOrNull(), SourceTypeValue, SourceTypeValueId); History.EvaluateChange(HistoryChangeList, "Scheduled Transaction Id", entry.OriginalValues["ScheduledTransactionId"].ToStringSafe().AsIntegerOrNull(), ScheduledTransactionId); History.EvaluateChange(HistoryChangeList, "Processed By", entry.OriginalValues["ProcessedByPersonAliasId"].ToStringSafe().AsIntegerOrNull(), ProcessedByPersonAlias, ProcessedByPersonAliasId, rockContext); History.EvaluateChange(HistoryChangeList, "Processed Date/Time", entry.OriginalValues["ProcessedDateTime"].ToStringSafe().AsDateTime(), ProcessedDateTime); History.EvaluateChange(HistoryChangeList, "Status", entry.OriginalValues["Status"].ToStringSafe(), Status); History.EvaluateChange(HistoryChangeList, "Status Message", entry.OriginalValues["StatusMessage"].ToStringSafe(), StatusMessage); if (!batchId.Equals(origBatchId)) { var batchChanges = new History.HistoryChangeList(); if (origBatchId.HasValue) { batchChanges.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, "Transaction").SetOldValue($"{this.TotalAmount.FormatAsCurrency()} for {person}"); } if (batchId.HasValue) { batchChanges.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, "Transaction").SetNewValue($"{this.TotalAmount.FormatAsCurrency()} for {person}"); } BatchHistoryChangeList.Add(batchId.Value, batchChanges); } else { if (batchId.HasValue) { var batchChanges = new History.HistoryChangeList(); batchChanges.AddChange(History.HistoryVerb.Modify, History.HistoryChangeType.Record, $"Transaction Id:{Id}"); BatchHistoryChangeList.Add(batchId.Value, batchChanges); } } break; } case System.Data.Entity.EntityState.Deleted: { HistoryChangeList.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, "Transaction"); int?batchId = Batch != null ? Batch.Id : BatchId; if (batchId.HasValue) { string batch = History.GetValue <FinancialBatch>(Batch, BatchId, rockContext); string person = History.GetValue <PersonAlias>(AuthorizedPersonAlias, AuthorizedPersonAliasId, rockContext); var batchChanges = new History.HistoryChangeList(); batchChanges.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, "Transaction").SetOldValue($"{this.TotalAmount.FormatAsCurrency()} for {person}"); BatchHistoryChangeList.Add(batchId.Value, batchChanges); } // since images have a cascade delete relationship, make sure the PreSaveChanges gets called var childImages = new FinancialTransactionImageService(dbContext as RockContext).Queryable().Where(a => a.TransactionId == this.Id); foreach (var image in childImages) { image.PreSaveChanges(dbContext, entry.State); } break; } } base.PreSaveChanges(dbContext, entry); }
protected void btnExportToShelbyFinancials_Click(object sender, EventArgs e) { Session["JournalType"] = ddlJournalType.SelectedValue; Session["AccountingPeriod"] = tbAccountingPeriod.Text; if (_financialBatch != null) { var rockContext = new RockContext(); var sfJournal = new SFJournal(); var journalCode = ddlJournalType.SelectedValue; var period = tbAccountingPeriod.Text.AsInteger(); var debugLava = GetAttributeValue("EnableDebug"); var items = sfJournal.GetGLExcelLines(rockContext, _financialBatch, journalCode, period, ref debugLava, GetAttributeValue("JournalDescriptionLava")); if (items.Count > 0) { var excel = sfJournal.GLExcelExport(items); Session["ShelbyFinancialsExcelExport"] = excel; Session["ShelbyFinancialsFileId"] = _financialBatch.Id.ToString(); Session["ShelbyFinancialsDebugLava"] = debugLava; // // vars we need to know // var financialBatch = new FinancialBatchService(rockContext).Get(_batchId); var changes = new History.HistoryChangeList(); // // Close Batch if we're supposed to // if (GetAttributeValue("CloseBatch").AsBoolean()) { History.EvaluateChange(changes, "Status", financialBatch.Status, BatchStatus.Closed); financialBatch.Status = BatchStatus.Closed; } // // Set Date Exported // financialBatch.LoadAttributes(); var oldDate = financialBatch.GetAttributeValue("rocks.kfs.ShelbyFinancials.DateExported"); var newDate = RockDateTime.Now; History.EvaluateChange(changes, "Date Exported", oldDate, newDate.ToString()); // // Save the changes // rockContext.WrapTransaction(() => { if (changes.Any()) { HistoryService.SaveChanges( rockContext, typeof(FinancialBatch), Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(), financialBatch.Id, changes); } }); financialBatch.SetAttributeValue("rocks.kfs.ShelbyFinancials.DateExported", newDate); financialBatch.SaveAttributeValue("rocks.kfs.ShelbyFinancials.DateExported", rockContext); } } Response.Redirect(Request.RawUrl); }
/// <summary> /// Method that will be called on an entity immediately before the item is saved by context /// </summary> /// <param name="dbContext"></param> /// <param name="entry"></param> public override void PreSaveChanges(Data.DbContext dbContext, DbEntityEntry entry) { var rockContext = (RockContext)dbContext; HistoryChangeList = new History.HistoryChangeList(); switch (entry.State) { case System.Data.Entity.EntityState.Added: { HistoryChangeList.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, "Group").SetNewValue(Name); History.EvaluateChange(HistoryChangeList, "Name", string.Empty, Name); History.EvaluateChange(HistoryChangeList, "Description", string.Empty, Description); History.EvaluateChange(HistoryChangeList, "Group Type", (int?)null, GroupType, GroupTypeId); History.EvaluateChange(HistoryChangeList, "Campus", (int?)null, Campus, CampusId); History.EvaluateChange(HistoryChangeList, "Security Role", (bool?)null, IsSecurityRole); History.EvaluateChange(HistoryChangeList, "Active", (bool?)null, IsActive); History.EvaluateChange(HistoryChangeList, "Allow Guests", (bool?)null, AllowGuests); History.EvaluateChange(HistoryChangeList, "Public", (bool?)null, IsPublic); History.EvaluateChange(HistoryChangeList, "Group Capacity", (int?)null, GroupCapacity); // if this is a new record, but is saved with IsActive=False, set the InactiveDateTime if it isn't set already if (!this.IsActive) { this.InactiveDateTime = this.InactiveDateTime ?? RockDateTime.Now; } break; } case System.Data.Entity.EntityState.Modified: { var originalIsActive = entry.OriginalValues["IsActive"].ToStringSafe().AsBoolean(); History.EvaluateChange(HistoryChangeList, "Name", entry.OriginalValues["Name"].ToStringSafe(), Name); History.EvaluateChange(HistoryChangeList, "Description", entry.OriginalValues["Description"].ToStringSafe(), Description); History.EvaluateChange(HistoryChangeList, "Group Type", entry.OriginalValues["GroupTypeId"].ToStringSafe().AsIntegerOrNull(), GroupType, GroupTypeId); History.EvaluateChange(HistoryChangeList, "Campus", entry.OriginalValues["CampusId"].ToStringSafe().AsIntegerOrNull(), Campus, CampusId); History.EvaluateChange(HistoryChangeList, "Security Role", entry.OriginalValues["IsSecurityRole"].ToStringSafe().AsBoolean(), IsSecurityRole); History.EvaluateChange(HistoryChangeList, "Active", originalIsActive, IsActive); History.EvaluateChange(HistoryChangeList, "Allow Guests", entry.OriginalValues["AllowGuests"].ToStringSafe().AsBooleanOrNull(), AllowGuests); History.EvaluateChange(HistoryChangeList, "Public", entry.OriginalValues["IsPublic"].ToStringSafe().AsBoolean(), IsPublic); History.EvaluateChange(HistoryChangeList, "Group Capacity", entry.OriginalValues["GroupCapacity"].ToStringSafe().AsIntegerOrNull(), GroupCapacity); History.EvaluateChange(HistoryChangeList, "Archived", entry.OriginalValues["IsArchived"].ToStringSafe().AsBoolean(), this.IsArchived); // IsActive was modified, set the InactiveDateTime if it changed to Inactive, or set it to NULL if it changed to Active if (originalIsActive != this.IsActive) { if (!this.IsActive) { // if the caller didn't already set InactiveDateTime, set it to now this.InactiveDateTime = this.InactiveDateTime ?? RockDateTime.Now; } else { this.InactiveDateTime = null; } } break; } case System.Data.Entity.EntityState.Deleted: { HistoryChangeList.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, null); // manually delete any grouprequirements of this group since it can't be cascade deleted var groupRequirementService = new GroupRequirementService(rockContext); var groupRequirements = groupRequirementService.Queryable().Where(a => a.GroupId.HasValue && a.GroupId == this.Id).ToList(); if (groupRequirements.Any()) { groupRequirementService.DeleteRange(groupRequirements); } // manually set any attendance search group ids to null var attendanceService = new AttendanceService(rockContext); var attendancesToNullSearchResultGroupId = attendanceService.Queryable() .Where(a => a.SearchResultGroupId.HasValue && a.SearchResultGroupId.Value == this.Id); dbContext.BulkUpdate(attendancesToNullSearchResultGroupId, a => new Attendance { SearchResultGroupId = null }); // since we can't put a CascadeDelete on both Attendance.Occurrence.GroupId and Attendance.OccurrenceId, manually delete all Attendance records associated with this GroupId var attendancesToDelete = attendanceService.Queryable() .Where(a => a.Occurrence.GroupId.HasValue && a.Occurrence.GroupId.Value == this.Id); if (attendancesToDelete.Any()) { dbContext.BulkDelete(attendancesToDelete); } break; } } base.PreSaveChanges(dbContext, entry); }
/// <summary> /// Saves a list of history messages. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="modelType">Type of the model.</param> /// <param name="categoryGuid">The category unique identifier.</param> /// <param name="entityId">The entity identifier.</param> /// <param name="changes">The changes.</param> /// <param name="commitSave">if set to <c>true</c> [commit save].</param> /// <param name="modifiedByPersonAliasId">The modified by person alias identifier.</param> /// <param name="sourceOfChange">The source of change.</param> public static void SaveChanges(RockContext rockContext, Type modelType, Guid categoryGuid, int entityId, History.HistoryChangeList changes, bool commitSave = true, int?modifiedByPersonAliasId = null, string sourceOfChange = null) { SaveChanges(rockContext, modelType, categoryGuid, entityId, changes, null, null, null, commitSave, modifiedByPersonAliasId, sourceOfChange); }
/// <summary> /// Saves the changes. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="modelType">Type of the model.</param> /// <param name="categoryGuid">The category unique identifier.</param> /// <param name="entityId">The entity identifier.</param> /// <param name="changes">The changes.</param> /// <param name="caption">The caption.</param> /// <param name="relatedModelType">Type of the related model.</param> /// <param name="relatedEntityId">The related entity identifier.</param> /// <param name="commitSave">if set to <c>true</c> [commit save].</param> /// <param name="modifiedByPersonAliasId">The modified by person alias identifier.</param> /// <param name="sourceOfChange">The source of change to be recorded on the history record. If this is not provided the RockContext source of change will be used instead.</param> public static void SaveChanges(RockContext rockContext, Type modelType, Guid categoryGuid, int entityId, History.HistoryChangeList changes, string caption, Type relatedModelType, int?relatedEntityId, bool commitSave = true, int?modifiedByPersonAliasId = null, string sourceOfChange = null) { if (changes.Any()) { // Set the change source for any entries that do not have one, or for all entries if a source has been supplied as a parameter. SetHistoryEntriesSourceOfChange(changes, sourceOfChange ?? rockContext.SourceOfChange, sourceOfChange != null); AddChanges(rockContext, modelType, categoryGuid, entityId, changes, caption, relatedModelType, relatedEntityId, modifiedByPersonAliasId); if (commitSave) { rockContext.SaveChanges(); } } }
protected void btnExportToIntacct_Click(object sender, EventArgs e) { if (_financialBatch != null) { if (GetAttributeValue(AttributeKey.ExportMode) == "OtherReceipt") { // // Capture ddl values as user preferences // SetBlockUserPreference("ReceiptAccountType", ddlReceiptAccountType.SelectedValue ?? ""); SetBlockUserPreference("PaymentMethod", ddlPaymentMethods.SelectedValue ?? ""); } if (_intacctAuth == null) { _intacctAuth = GetIntactAuth(); } // // Create Intacct Journal XML and Post to Intacct // var endpoint = new IntacctEndpoint(); var debugLava = GetAttributeValue(AttributeKey.EnableDebug); var postXml = new System.Xml.XmlDocument(); if (GetAttributeValue(AttributeKey.ExportMode) == "JournalEntry") { var journal = new IntacctJournal(); postXml = journal.CreateJournalEntryXML(_intacctAuth, _financialBatch.Id, GetAttributeValue(AttributeKey.JournalId), ref debugLava, GetAttributeValue(AttributeKey.JournalMemoLava)); } else // Export Mode is Other Receipt { var otherReceipt = new IntacctOtherReceipt(); string bankAccountId = null; string undepFundAccount = null; if (ddlReceiptAccountType.SelectedValue == "BankAccount") { SetBlockUserPreference("BankAccountId", ddlBankAccounts.SelectedValue ?? ""); bankAccountId = ddlBankAccounts.SelectedValue; } else { undepFundAccount = GetAttributeValue(AttributeKey.UndepositedFundsAccount); } postXml = otherReceipt.CreateOtherReceiptXML(_intacctAuth, _financialBatch.Id, ref debugLava, ( PaymentMethod )ddlPaymentMethods.SelectedValue.AsInteger(), bankAccountId, undepFundAccount, GetAttributeValue(AttributeKey.JournalMemoLava)); } var resultXml = endpoint.PostToIntacct(postXml); var success = endpoint.ParseEndpointResponse(resultXml, _financialBatch.Id, GetAttributeValue(AttributeKey.LogResponse).AsBoolean()); if (success) { var rockContext = new RockContext(); var financialBatch = new FinancialBatchService(rockContext).Get(_batchId); var changes = new History.HistoryChangeList(); Session["IntacctDebugLava"] = debugLava; // // Close Batch if we're supposed to // if (GetAttributeValue(AttributeKey.CloseBatch).AsBoolean()) { History.EvaluateChange(changes, "Status", financialBatch.Status, BatchStatus.Closed); financialBatch.Status = BatchStatus.Closed; } // // Set Date Exported // financialBatch.LoadAttributes(); var oldDate = financialBatch.GetAttributeValue("rocks.kfs.Intacct.DateExported"); var newDate = RockDateTime.Now; History.EvaluateChange(changes, "Date Exported", oldDate, newDate.ToString()); // // Save the changes // rockContext.WrapTransaction(() => { if (changes.Any()) { HistoryService.SaveChanges( rockContext, typeof(FinancialBatch), Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(), financialBatch.Id, changes); } }); financialBatch.SetAttributeValue("rocks.kfs.Intacct.DateExported", newDate); financialBatch.SaveAttributeValue("rocks.kfs.Intacct.DateExported", rockContext); } } Response.Redirect(Request.RawUrl); }
/// <summary> /// This method stores the transaction in the database along with the appropriate details and batch information. /// </summary> private FinancialTransaction SaveTransaction(Guid transactionGuid) { // if this is a future transaction, the payment hasn't been charged yet if (_payment == null && _automatedPaymentArgs.FutureProcessingDateTime.HasValue) { _payment = new Payment { Status = "PreProcessing", StatusMessage = "This transaction is scheduled to be processed in the future", TransactionCode = _financialPersonSavedAccount.Id.ToStringSafe() }; } // Create a new transaction or update the future transaction now that it has been charged var financialTransaction = _futureTransaction ?? new FinancialTransaction(); financialTransaction.TransactionCode = _payment.TransactionCode; financialTransaction.Guid = transactionGuid; financialTransaction.CreatedByPersonAliasId = _currentPersonAliasId; financialTransaction.ScheduledTransactionId = _automatedPaymentArgs.ScheduledTransactionId; financialTransaction.AuthorizedPersonAliasId = _automatedPaymentArgs.AuthorizedPersonAliasId; financialTransaction.ShowAsAnonymous = _automatedPaymentArgs.ShowAsAnonymous; financialTransaction.TransactionDateTime = _automatedPaymentArgs.FutureProcessingDateTime.HasValue ? ( DateTime? )null : RockDateTime.Now; financialTransaction.FinancialGatewayId = _financialGateway.Id; financialTransaction.TransactionTypeValueId = _transactionType.Id; financialTransaction.Summary = string.Format("{0} {1}", financialTransaction.Summary, _referencePaymentInfo.Comment1).Trim(); financialTransaction.SourceTypeValueId = _financialSource.Id; financialTransaction.IsSettled = _payment.IsSettled; financialTransaction.Status = _payment.Status; financialTransaction.StatusMessage = _payment.StatusMessage; financialTransaction.SettledDate = _payment.SettledDate; financialTransaction.ForeignKey = _payment.ForeignKey; financialTransaction.FutureProcessingDateTime = _automatedPaymentArgs.FutureProcessingDateTime; financialTransaction.ForeignCurrencyCodeValueId = GetCurrencyCodeDefinedValueCache(_automatedPaymentArgs.AmountCurrencyCode)?.Id; // Create a new payment detail or update the future transaction's payment detail now that it has been charged var financialPaymentDetail = financialTransaction.FinancialPaymentDetail ?? new FinancialPaymentDetail(); financialPaymentDetail.AccountNumberMasked = _payment.AccountNumberMasked; financialPaymentDetail.NameOnCard = _payment.NameOnCard; financialPaymentDetail.ExpirationMonth = _payment.ExpirationMonth; financialPaymentDetail.ExpirationYear = _payment.ExpirationYear; financialPaymentDetail.CreatedByPersonAliasId = _currentPersonAliasId; financialPaymentDetail.ForeignKey = _payment.ForeignKey; financialPaymentDetail.GatewayPersonIdentifier = _financialPersonSavedAccount?.GatewayPersonIdentifier; financialPaymentDetail.FinancialPersonSavedAccountId = _financialPersonSavedAccount?.Id; if (_payment.CurrencyTypeValue != null) { financialPaymentDetail.CurrencyTypeValueId = _payment.CurrencyTypeValue.Id; } if (_payment.CreditCardTypeValue != null) { financialPaymentDetail.CreditCardTypeValueId = _payment.CreditCardTypeValue.Id; } financialPaymentDetail.SetFromPaymentInfo(_referencePaymentInfo, _automatedGatewayComponent, _rockContext); financialTransaction.FinancialPaymentDetail = financialPaymentDetail; financialTransaction.FinancialPaymentDetailId = financialPaymentDetail.Id == 0 ? ( int? )null : financialPaymentDetail.Id; // Future transactions already have the appropriate FinancialTransactionDetail models if (_futureTransaction == null) { var doesHaveForeignCurrency = financialTransaction.ForeignCurrencyCodeValueId != null; foreach (var detailArgs in _automatedPaymentArgs.AutomatedPaymentDetails) { var transactionDetail = new FinancialTransactionDetail { Amount = detailArgs.Amount, AccountId = detailArgs.AccountId }; if (doesHaveForeignCurrency) { transactionDetail.ForeignCurrencyAmount = detailArgs.Amount; } financialTransaction.TransactionDetails.Add(transactionDetail); } if (doesHaveForeignCurrency) { /* * The amount coming from the gateway is always in the Organization's currency. * As such the Amount value could be different than the original amount passed in if the * specified currency code is different then the Organization's currency code. */ financialTransaction.SetApportionedDetailAmounts(_payment.Amount); } } // New transactions and future transactions need fee info financialTransaction.SetApportionedFeesOnDetails(_payment.FeeAmount); // Get an existing or new batch according to the name prefix and payment type FinancialBatch batch; if (!financialTransaction.BatchId.HasValue) { batch = _financialBatchService.Get( _automatedPaymentArgs.BatchNamePrefix ?? "Online Giving", string.Empty, _referencePaymentInfo.CurrencyTypeValue, _referencePaymentInfo.CreditCardTypeValue, financialTransaction.TransactionDateTime ?? financialTransaction.FutureProcessingDateTime.Value, _financialGateway.GetBatchTimeOffset(), _financialGateway.BatchDayOfWeek); } else { batch = _financialBatchService.Get(financialTransaction.BatchId.Value); } var batchChanges = new History.HistoryChangeList(); var isNewBatch = batch.Id == 0; // If this is a new Batch, SaveChanges so that we can get the Batch.Id and also // add history entries about the batch creation if (isNewBatch) { batchChanges.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, "Batch"); History.EvaluateChange(batchChanges, "Batch Name", string.Empty, batch.Name); History.EvaluateChange(batchChanges, "Status", null, batch.Status); History.EvaluateChange(batchChanges, "Start Date/Time", null, batch.BatchStartDateTime); History.EvaluateChange(batchChanges, "End Date/Time", null, batch.BatchEndDateTime); _rockContext.SaveChanges(); } if (_futureTransaction == null) { // Use the financialTransactionService to add the transaction instead of batch.Transactions // to avoid lazy-loading the transactions already associated with the batch financialTransaction.BatchId = batch.Id; _financialTransactionService.Add(financialTransaction); } _rockContext.SaveChanges(); if (_futureTransaction == null) { // Update the batch control amount _financialBatchService.IncrementControlAmount(batch.Id, financialTransaction.TotalAmount, batchChanges); _rockContext.SaveChanges(); } // Save the changes history for the batch HistoryService.SaveChanges( _rockContext, typeof(FinancialBatch), SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(), batch.Id, batchChanges ); return(financialTransaction); }
/// <summary> /// Sends the specified communication. /// </summary>Medi /// <param name="communication">The communication.</param> /// <param name="mediumEntityTypeId">The medium entity type identifier.</param> /// <param name="mediumAttributes">The medium attributes.</param> public override void Send(Rock.Model.Communication communication, int mediumEntityTypeId, Dictionary <string, string> mediumAttributes) { using (var communicationRockContext = new RockContext()) { // Requery the Communication communication = new CommunicationService(communicationRockContext) .Queryable() .Include(a => a.CreatedByPersonAlias.Person) .Include(a => a.CommunicationTemplate) .FirstOrDefault(c => c.Id == communication.Id); bool hasPendingRecipients; if (communication != null && communication.Status == Model.CommunicationStatus.Approved && (!communication.FutureSendDateTime.HasValue || communication.FutureSendDateTime.Value.CompareTo(RockDateTime.Now) <= 0)) { var qryRecipients = new CommunicationRecipientService(communicationRockContext).Queryable(); hasPendingRecipients = qryRecipients .Where(r => r.CommunicationId == communication.Id && r.Status == Model.CommunicationRecipientStatus.Pending && r.MediumEntityTypeId.HasValue && r.MediumEntityTypeId.Value == mediumEntityTypeId) .Any(); } else { hasPendingRecipients = false; } if (!hasPendingRecipients) { return; } var currentPerson = communication.CreatedByPersonAlias?.Person; var globalAttributes = GlobalAttributesCache.Get(); string publicAppRoot = globalAttributes.GetValue("PublicApplicationRoot").EnsureTrailingForwardslash(); var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(null, currentPerson); var cssInliningEnabled = communication.CommunicationTemplate?.CssInliningEnabled ?? false; string fromAddress = communication.FromEmail; string fromName = communication.FromName; // Resolve any possible merge fields in the from address fromAddress = fromAddress.ResolveMergeFields(mergeFields, currentPerson, communication.EnabledLavaCommands); fromName = fromName.ResolveMergeFields(mergeFields, currentPerson, communication.EnabledLavaCommands); // From - if none is set, use the one in the Organization's GlobalAttributes. if (string.IsNullOrWhiteSpace(fromAddress)) { fromAddress = globalAttributes.GetValue("OrganizationEmail"); } if (string.IsNullOrWhiteSpace(fromName)) { fromName = globalAttributes.GetValue("OrganizationName"); } MailMessage message = new MailMessage(); // Reply To try { string replyTo = communication.ReplyToEmail; if (!string.IsNullOrWhiteSpace(replyTo)) { // Resolve any possible merge fields in the replyTo address message.ReplyToList.Add(new MailAddress(replyTo.ResolveMergeFields(mergeFields, currentPerson))); } } catch { } message.IsBodyHtml = true; message.Priority = MailPriority.Normal; using (var smtpClient = GetSmtpClient()) { var personEntityTypeId = EntityTypeCache.Get("Rock.Model.Person").Id; var communicationEntityTypeId = EntityTypeCache.Get("Rock.Model.Communication").Id; var communicationCategoryGuid = Rock.SystemGuid.Category.HISTORY_PERSON_COMMUNICATIONS.AsGuid(); bool recipientFound = true; while (recipientFound) { // make a new rockContext per recipient var recipientRockContext = new RockContext(); var recipient = Rock.Model.Communication.GetNextPending(communication.Id, mediumEntityTypeId, recipientRockContext); if (recipient != null) { if (ValidRecipient(recipient, communication.IsBulkCommunication)) { try { message.To.Clear(); message.CC.Clear(); message.Bcc.Clear(); message.Headers.Clear(); message.AlternateViews.Clear(); // Set From/To and check safe sender message.From = new MailAddress(fromAddress, fromName); message.To.Add(new MailAddress(recipient.PersonAlias.Person.Email, recipient.PersonAlias.Person.FullName)); CheckSafeSender(message, globalAttributes); // Create merge field dictionary var mergeObjects = recipient.CommunicationMergeValues(mergeFields); // CC string cc = communication.CCEmails; if (!string.IsNullOrWhiteSpace(cc)) { // Resolve any possible merge fields in the cc address cc = cc.ResolveMergeFields(mergeObjects, currentPerson); foreach (string ccRecipient in cc.SplitDelimitedValues()) { message.CC.Add(new MailAddress(ccRecipient)); } } // BCC string bcc = communication.BCCEmails; if (!string.IsNullOrWhiteSpace(bcc)) { bcc = bcc.ResolveMergeFields(mergeObjects, currentPerson); foreach (string bccRecipient in bcc.SplitDelimitedValues()) { // Resolve any possible merge fields in the bcc address message.Bcc.Add(new MailAddress(bccRecipient)); } } // Subject message.Subject = ResolveText(communication.Subject, currentPerson, communication.EnabledLavaCommands, mergeObjects, publicAppRoot); // Plain text if (mediumAttributes.ContainsKey("DefaultPlainText")) { string plainText = ResolveText(mediumAttributes["DefaultPlainText"], currentPerson, communication.EnabledLavaCommands, mergeObjects, publicAppRoot); if (!string.IsNullOrWhiteSpace(plainText)) { AlternateView plainTextView = AlternateView.CreateAlternateViewFromString(plainText, new System.Net.Mime.ContentType(MediaTypeNames.Text.Plain)); message.AlternateViews.Add(plainTextView); } } // Add Html view // Get the unsubscribe content and add a merge field for it string htmlBody = communication.Message; if (communication.IsBulkCommunication && mediumAttributes.ContainsKey("UnsubscribeHTML")) { string unsubscribeHtml = ResolveText(mediumAttributes["UnsubscribeHTML"], currentPerson, communication.EnabledLavaCommands, mergeObjects, publicAppRoot); mergeObjects.AddOrReplace("UnsubscribeOption", unsubscribeHtml); htmlBody = ResolveText(htmlBody, currentPerson, communication.EnabledLavaCommands, mergeObjects, publicAppRoot); // Resolve special syntax needed if option was included in global attribute if (Regex.IsMatch(htmlBody, @"\[\[\s*UnsubscribeOption\s*\]\]")) { htmlBody = Regex.Replace(htmlBody, @"\[\[\s*UnsubscribeOption\s*\]\]", unsubscribeHtml); } // Add the unsubscribe option at end if it wasn't included in content if (!htmlBody.Contains(unsubscribeHtml)) { htmlBody += unsubscribeHtml; } } else { htmlBody = ResolveText(htmlBody, currentPerson, communication.EnabledLavaCommands, mergeObjects, publicAppRoot); htmlBody = Regex.Replace(htmlBody, @"\[\[\s*UnsubscribeOption\s*\]\]", string.Empty); } if (!string.IsNullOrWhiteSpace(htmlBody)) { if (cssInliningEnabled) { // move styles inline to help it be compatible with more email clients htmlBody = htmlBody.ConvertHtmlStylesToInlineAttributes(); } // add the main Html content to the email AlternateView htmlView = AlternateView.CreateAlternateViewFromString(htmlBody, new System.Net.Mime.ContentType(MediaTypeNames.Text.Html)); message.AlternateViews.Add(htmlView); } // Add any additional headers that specific SMTP provider needs var metaData = new Dictionary <string, string>(); metaData.Add("communication_recipient_guid", recipient.Guid.ToString()); AddAdditionalHeaders(message, metaData); // Recreate the attachments message.Attachments.Clear(); foreach (var binaryFile in communication.GetAttachments(CommunicationType.Email).Select(a => a.BinaryFile)) { message.Attachments.Add(new Attachment(binaryFile.ContentStream, binaryFile.FileName)); } smtpClient.Send(message); recipient.Status = CommunicationRecipientStatus.Delivered; string statusNote = StatusNote; if (!string.IsNullOrWhiteSpace(statusNote)) { recipient.StatusNote = statusNote; } recipient.TransportEntityTypeName = this.GetType().FullName; try { var historyChangeList = new History.HistoryChangeList(); historyChangeList.AddChange( History.HistoryVerb.Sent, History.HistoryChangeType.Record, $"Communication") .SetRelatedData(message.From.DisplayName, communicationEntityTypeId, communication.Id) .SetCaption(message.Subject); HistoryService.SaveChanges(recipientRockContext, typeof(Rock.Model.Person), communicationCategoryGuid, recipient.PersonAlias.PersonId, historyChangeList, false, communication.SenderPersonAliasId); } catch (Exception ex) { ExceptionLogService.LogException(ex, null); } } catch (Exception ex) { ExceptionLogService.LogException(ex); recipient.Status = CommunicationRecipientStatus.Failed; recipient.StatusNote = "Exception: " + ex.Messages().AsDelimited(" => "); } } recipientRockContext.SaveChanges(); } else { recipientFound = false; } } } } }
/// <summary> /// Executes the specified workflow. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="action">The action.</param> /// <param name="entity">The entity.</param> /// <param name="errorMessages">The error messages.</param> /// <returns></returns> public override bool Execute(RockContext rockContext, WorkflowAction action, Object entity, out List <string> errorMessages) { errorMessages = new List <string>(); // get person int?personId = null; string personAttributeValue = GetAttributeValue(action, "Person"); Guid? guidPersonAttribute = personAttributeValue.AsGuidOrNull(); if (guidPersonAttribute.HasValue) { var attributePerson = AttributeCache.Get(guidPersonAttribute.Value, rockContext); if (attributePerson != null && attributePerson.FieldType.Class == "Rock.Field.Types.PersonFieldType") { string attributePersonValue = action.GetWorkflowAttributeValue(guidPersonAttribute.Value); if (!string.IsNullOrWhiteSpace(attributePersonValue)) { Guid personAliasGuid = attributePersonValue.AsGuid(); if (!personAliasGuid.IsEmpty()) { personId = new PersonAliasService(rockContext).Queryable() .Where(a => a.Guid.Equals(personAliasGuid)) .Select(a => a.PersonId) .FirstOrDefault(); if (personId == null) { errorMessages.Add(string.Format("Person could not be found for selected value ('{0}')!", guidPersonAttribute.ToString())); return(false); } } } } } if (personId == null) { errorMessages.Add("The attribute used to provide the person was invalid, or not of type 'Person'."); return(false); } // determine the phone type to edit DefinedValueCache phoneType = null; var phoneTypeAttributeValue = action.GetWorkflowAttributeValue(GetAttributeValue(action, "PhoneTypeAttribute").AsGuid()); if (phoneTypeAttributeValue != null) { phoneType = DefinedValueCache.Get(phoneTypeAttributeValue.AsGuid()); } if (phoneType == null) { phoneType = DefinedValueCache.Get(GetAttributeValue(action, "PhoneType").AsGuid()); } if (phoneType == null) { errorMessages.Add("The phone type to be updated was not selected."); return(false); } // get the ignore blank setting var ignoreBlanks = GetActionAttributeValue(action, "IgnoreBlankValues").AsBoolean(true); // get the new phone number value string phoneNumberValue = GetAttributeValue(action, "PhoneNumber"); Guid? phoneNumberValueGuid = phoneNumberValue.AsGuidOrNull(); if (phoneNumberValueGuid.HasValue) { phoneNumberValue = action.GetWorkflowAttributeValue(phoneNumberValueGuid.Value); } else { phoneNumberValue = phoneNumberValue.ResolveMergeFields(GetMergeFields(action)); } phoneNumberValue = PhoneNumber.CleanNumber(phoneNumberValue); // gets value indicating if phone number is unlisted string unlistedValue = GetAttributeValue(action, "Unlisted"); Guid? unlistedValueGuid = unlistedValue.AsGuidOrNull(); if (unlistedValueGuid.HasValue) { unlistedValue = action.GetWorkflowAttributeValue(unlistedValueGuid.Value); } else { unlistedValue = unlistedValue.ResolveMergeFields(GetMergeFields(action)); } bool?unlisted = unlistedValue.AsBooleanOrNull(); // gets value indicating if messaging should be enabled for phone number string smsEnabledValue = GetAttributeValue(action, "MessagingEnabled"); Guid? smsEnabledValueGuid = smsEnabledValue.AsGuidOrNull(); if (smsEnabledValueGuid.HasValue) { smsEnabledValue = action.GetWorkflowAttributeValue(smsEnabledValueGuid.Value); } else { smsEnabledValue = smsEnabledValue.ResolveMergeFields(GetMergeFields(action)); } bool?smsEnabled = smsEnabledValue.AsBooleanOrNull(); bool updated = false; bool newPhoneNumber = false; var phoneNumberService = new PhoneNumberService(rockContext); var phoneNumber = phoneNumberService.Queryable() .Where(n => n.PersonId == personId.Value && n.NumberTypeValueId == phoneType.Id) .FirstOrDefault(); string oldValue = string.Empty; if (phoneNumber == null) { phoneNumber = new PhoneNumber { NumberTypeValueId = phoneType.Id, PersonId = personId.Value }; newPhoneNumber = true; updated = true; } else { oldValue = phoneNumber.NumberFormattedWithCountryCode; } if (!string.IsNullOrWhiteSpace(phoneNumberValue) || !ignoreBlanks) { updated = updated || phoneNumber.Number != phoneNumberValue; phoneNumber.Number = phoneNumberValue; } if (unlisted.HasValue) { updated = updated || phoneNumber.IsUnlisted != unlisted.Value; phoneNumber.IsUnlisted = unlisted.Value; } if (smsEnabled.HasValue) { updated = updated || phoneNumber.IsMessagingEnabled != smsEnabled.Value; phoneNumber.IsMessagingEnabled = smsEnabled.Value; } if (updated) { if (oldValue != phoneNumber.NumberFormattedWithCountryCode) { var changes = new History.HistoryChangeList(); changes.AddChange(History.HistoryVerb.Modify, History.HistoryChangeType.Record, "Phone").SetSourceOfChange($"{action.ActionTypeCache.ActivityType.WorkflowType.Name} workflow"); HistoryService.SaveChanges(rockContext, typeof(Person), Rock.SystemGuid.Category.HISTORY_PERSON_DEMOGRAPHIC_CHANGES.AsGuid(), personId.Value, changes, false); } if (phoneNumber.Number.IsNullOrWhiteSpace()) { if (!newPhoneNumber) { phoneNumberService.Delete(phoneNumber); } } else { if (newPhoneNumber) { phoneNumberService.Add(phoneNumber); } } rockContext.SaveChanges(); if (action.Activity != null && action.Activity.Workflow != null) { var workflowType = action.Activity.Workflow.WorkflowTypeCache; if (workflowType != null && workflowType.LoggingLevel == WorkflowLoggingLevel.Action) { var person = new PersonService(rockContext).Get(personId.Value); action.AddLogEntry(string.Format("Updated {0} phone for {1} to {2}.", phoneType.Value, person.FullName, phoneNumber.NumberFormattedWithCountryCode)); } } } return(true); }
/// <summary> /// Sends the specified communication. /// </summary> /// <param name="communication">The communication.</param> /// <param name="mediumEntityTypeId">The medium entity type identifier.</param> /// <param name="mediumAttributes">The medium attributes.</param> public override void Send(Model.Communication communication, int mediumEntityTypeId, Dictionary <string, string> mediumAttributes) { using (var communicationRockContext = new RockContext()) { // Requery the Communication communication = new CommunicationService(communicationRockContext) .Queryable().Include(a => a.CreatedByPersonAlias.Person).Include(a => a.CommunicationTemplate) .FirstOrDefault(c => c.Id == communication.Id); // If there are no pending recipients than just exit the method if (communication != null && communication.Status == Model.CommunicationStatus.Approved && (!communication.FutureSendDateTime.HasValue || communication.FutureSendDateTime.Value.CompareTo(RockDateTime.Now) <= 0)) { var qryRecipients = new CommunicationRecipientService(communicationRockContext).Queryable(); if (!qryRecipients .Where(r => r.CommunicationId == communication.Id && r.Status == Model.CommunicationRecipientStatus.Pending && r.MediumEntityTypeId.HasValue && r.MediumEntityTypeId.Value == mediumEntityTypeId) .Any()) { return; } } var currentPerson = communication.CreatedByPersonAlias?.Person; var globalAttributes = GlobalAttributesCache.Get(); string publicAppRoot = globalAttributes.GetValue("PublicApplicationRoot").EnsureTrailingForwardslash(); var mergeFields = Lava.LavaHelper.GetCommonMergeFields(null, currentPerson); var cssInliningEnabled = communication.CommunicationTemplate?.CssInliningEnabled ?? false; string fromAddress = string.IsNullOrWhiteSpace(communication.FromEmail) ? globalAttributes.GetValue("OrganizationEmail") : communication.FromEmail; string fromName = string.IsNullOrWhiteSpace(communication.FromName) ? globalAttributes.GetValue("OrganizationName") : communication.FromName; // Resolve any possible merge fields in the from address fromAddress = fromAddress.ResolveMergeFields(mergeFields, currentPerson, communication.EnabledLavaCommands); fromName = fromName.ResolveMergeFields(mergeFields, currentPerson, communication.EnabledLavaCommands); Parameter replyTo = new Parameter(); // Reply To if (communication.ReplyToEmail.IsNotNullOrWhiteSpace()) { // Resolve any possible merge fields in the replyTo address replyTo.Name = "h:Reply-To"; replyTo.Type = ParameterType.GetOrPost; replyTo.Value = communication.ReplyToEmail.ResolveMergeFields(mergeFields, currentPerson); } var personEntityTypeId = EntityTypeCache.Get("Rock.Model.Person").Id; var communicationEntityTypeId = EntityTypeCache.Get("Rock.Model.Communication").Id; var communicationCategoryGuid = Rock.SystemGuid.Category.HISTORY_PERSON_COMMUNICATIONS.AsGuid(); RestRequest restRequest = null; // Loop through recipients and send the email bool recipientFound = true; while (recipientFound) { var recipientRockContext = new RockContext(); var recipient = Model.Communication.GetNextPending(communication.Id, mediumEntityTypeId, recipientRockContext); // This means we are done, break the loop if (recipient == null) { recipientFound = false; break; } // Not valid save the obj with the status messages then go to the next one if (!ValidRecipient(recipient, communication.IsBulkCommunication)) { recipientRockContext.SaveChanges(); continue; } try { // Create merge field dictionary var mergeObjects = recipient.CommunicationMergeValues(mergeFields); // Create the request obj restRequest = new RestRequest(GetAttributeValue("Resource"), Method.POST); restRequest.AddParameter("domian", GetAttributeValue("Domain"), ParameterType.UrlSegment); // ReplyTo if (communication.ReplyToEmail.IsNotNullOrWhiteSpace()) { restRequest.AddParameter(replyTo); } // From restRequest.AddParameter("from", new MailAddress(fromAddress, fromName).ToString()); // To restRequest.AddParameter("to", new MailAddress(recipient.PersonAlias.Person.Email, recipient.PersonAlias.Person.FullName).ToString()); // Safe sender checks CheckSafeSender(restRequest, fromAddress, globalAttributes.GetValue("OrganizationEmail")); // CC if (communication.CCEmails.IsNotNullOrWhiteSpace()) { string[] ccRecipients = communication.CCEmails.ResolveMergeFields(mergeObjects, currentPerson).Replace(";", ",").Split(','); foreach (var ccRecipient in ccRecipients) { restRequest.AddParameter("cc", ccRecipient); } } // BCC if (communication.BCCEmails.IsNotNullOrWhiteSpace()) { string[] bccRecipients = communication.BCCEmails.ResolveMergeFields(mergeObjects, currentPerson).Replace(";", ",").Split(','); foreach (var bccRecipient in bccRecipients) { restRequest.AddParameter("bcc", bccRecipient); } } // Subject string subject = ResolveText(communication.Subject, currentPerson, communication.EnabledLavaCommands, mergeObjects, publicAppRoot); restRequest.AddParameter("subject", subject); // Body Plain Text if (mediumAttributes.ContainsKey("DefaultPlainText")) { string plainText = ResolveText(mediumAttributes["DefaultPlainText"], currentPerson, communication.EnabledLavaCommands, mergeObjects, publicAppRoot); if (!string.IsNullOrWhiteSpace(plainText)) { AlternateView plainTextView = AlternateView.CreateAlternateViewFromString(plainText, new ContentType(MediaTypeNames.Text.Plain)); restRequest.AddParameter("text", plainTextView); } } // Body HTML string htmlBody = communication.Message; // Get the unsubscribe content and add a merge field for it if (communication.IsBulkCommunication && mediumAttributes.ContainsKey("UnsubscribeHTML")) { string unsubscribeHtml = ResolveText(mediumAttributes["UnsubscribeHTML"], currentPerson, communication.EnabledLavaCommands, mergeObjects, publicAppRoot); mergeObjects.AddOrReplace("UnsubscribeOption", unsubscribeHtml); htmlBody = ResolveText(htmlBody, currentPerson, communication.EnabledLavaCommands, mergeObjects, publicAppRoot); // Resolve special syntax needed if option was included in global attribute if (Regex.IsMatch(htmlBody, @"\[\[\s*UnsubscribeOption\s*\]\]")) { htmlBody = Regex.Replace(htmlBody, @"\[\[\s*UnsubscribeOption\s*\]\]", unsubscribeHtml); } // Add the unsubscribe option at end if it wasn't included in content if (!htmlBody.Contains(unsubscribeHtml)) { htmlBody += unsubscribeHtml; } } else { htmlBody = ResolveText(htmlBody, currentPerson, communication.EnabledLavaCommands, mergeObjects, publicAppRoot); htmlBody = Regex.Replace(htmlBody, @"\[\[\s*UnsubscribeOption\s*\]\]", string.Empty); } if (!string.IsNullOrWhiteSpace(htmlBody)) { if (cssInliningEnabled) { // move styles inline to help it be compatible with more email clients htmlBody = htmlBody.ConvertHtmlStylesToInlineAttributes(); } // add the main Html content to the email restRequest.AddParameter("html", htmlBody); } // Headers AddAdditionalHeaders(restRequest, new Dictionary <string, string>() { { "communication_recipient_guid", recipient.Guid.ToString() } }); // Attachments foreach (var attachment in communication.GetAttachments(CommunicationType.Email).Select(a => a.BinaryFile)) { MemoryStream ms = new MemoryStream(); attachment.ContentStream.CopyTo(ms); restRequest.AddFile("attachment", ms.ToArray(), attachment.FileName); } // Send the email // Send it RestClient restClient = new RestClient { BaseUrl = new Uri(GetAttributeValue("BaseURL")), Authenticator = new HttpBasicAuthenticator("api", GetAttributeValue("APIKey")) }; // Call the API and get the response Response = restClient.Execute(restRequest); // Update recipient status and status note recipient.Status = Response.StatusCode == HttpStatusCode.OK ? CommunicationRecipientStatus.Delivered : CommunicationRecipientStatus.Failed; recipient.StatusNote = Response.StatusDescription; recipient.TransportEntityTypeName = this.GetType().FullName; // Log it try { var historyChangeList = new History.HistoryChangeList(); historyChangeList.AddChange( History.HistoryVerb.Sent, History.HistoryChangeType.Record, $"Communication") .SetRelatedData(fromName, communicationEntityTypeId, communication.Id) .SetCaption(subject); HistoryService.SaveChanges(recipientRockContext, typeof(Rock.Model.Person), communicationCategoryGuid, recipient.PersonAlias.PersonId, historyChangeList, false, communication.SenderPersonAliasId); } catch (Exception ex) { ExceptionLogService.LogException(ex, null); } } catch (Exception ex) { ExceptionLogService.LogException(ex); recipient.Status = CommunicationRecipientStatus.Failed; recipient.StatusNote = "Exception: " + ex.Messages().AsDelimited(" => "); } recipientRockContext.SaveChanges(); } } }
/// <summary> /// Method that will be called on an entity immediately before the item is saved by context. Takes /// care of logging any particular change history for user login. /// </summary> /// <param name="dbContext"></param> /// <param name="entry"></param> public override void PreSaveChanges(Rock.Data.DbContext dbContext, DbEntityEntry entry) { var rockContext = ( RockContext )dbContext; HistoryChanges = new History.HistoryChangeList(); switch (entry.State) { case EntityState.Added: { // Get the authentication provider entity type var entityType = EntityTypeCache.Get(this.EntityTypeId ?? 0); var change = HistoryChanges.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, "Authentication Provider").SetNewValue(entityType?.FriendlyName); // Don't log Pin Authentication user names. var isUserNameSensitive = (entityType?.Guid == Rock.SystemGuid.EntityType.AUTHENTICATION_PIN.AsGuid()) ? true : false; if (isUserNameSensitive) { change.SetCaption("User Account"); } History.EvaluateChange(HistoryChanges, "User Login", string.Empty, UserName, isUserNameSensitive); History.EvaluateChange(HistoryChanges, "Is Confirmed", null, IsConfirmed); History.EvaluateChange(HistoryChanges, "Is Password Change Required", null, IsPasswordChangeRequired); History.EvaluateChange(HistoryChanges, "Is Locked Out", null, IsLockedOut); break; } case EntityState.Modified: { var entityType = EntityTypeCache.Get(this.EntityTypeId ?? 0); // Don't log Pin Authentication user names. var isUserNameSensitive = (entityType?.Guid == Rock.SystemGuid.EntityType.AUTHENTICATION_PIN.AsGuid()) ? true : false; History.EvaluateChange(HistoryChanges, "User Login", entry.OriginalValues["UserName"].ToStringSafe(), UserName, isUserNameSensitive); History.EvaluateChange(HistoryChanges, "Is Confirmed", entry.OriginalValues["IsConfirmed"].ToStringSafe().AsBooleanOrNull(), IsConfirmed); History.EvaluateChange(HistoryChanges, "Is Password Change Required", entry.OriginalValues["IsPasswordChangeRequired"].ToStringSafe().AsBooleanOrNull(), IsPasswordChangeRequired); History.EvaluateChange(HistoryChanges, "Is Locked Out", entry.OriginalValues["IsLockedOut"].ToStringSafe().AsBooleanOrNull(), IsLockedOut); History.EvaluateChange(HistoryChanges, "Password", entry.OriginalValues["Password"].ToStringSafe(), Password, true); // Did the provider type change? int?origEntityTypeId = entry.OriginalValues["EntityTypeId"].ToStringSafe().AsIntegerOrNull(); int?entityTypeId = EntityType != null ? EntityType.Id : EntityTypeId; if (!entityTypeId.Equals(origEntityTypeId)) { var origProviderType = EntityTypeCache.Get(origEntityTypeId ?? 0)?.FriendlyName; var providerType = EntityTypeCache.Get(this.EntityTypeId ?? 0)?.FriendlyName; History.EvaluateChange(HistoryChanges, "User Login", origProviderType, providerType); } // Change the caption if this is a sensitive user account if (HistoryChanges.Count > 0 && isUserNameSensitive) { var change = HistoryChanges.FirstOrDefault(); change.SetCaption("User Account"); } break; } case EntityState.Deleted: { // By this point EF has stripped out some of the data we need to save history // Reload the data using a new context. RockContext newRockContext = new RockContext(); var userLogin = new UserLoginService(newRockContext).Get(this.Id); if (userLogin != null && userLogin.PersonId != null) { try { var entityType = EntityTypeCache.Get(userLogin.EntityTypeId ?? 0); var isUserNameSensitive = (entityType?.Guid == Rock.SystemGuid.EntityType.AUTHENTICATION_PIN.AsGuid()) ? true : false; if (!isUserNameSensitive) { HistoryChanges.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, "User Login").SetOldValue(userLogin.UserName); HistoryService.SaveChanges(newRockContext, typeof(Person), Rock.SystemGuid.Category.HISTORY_PERSON_ACTIVITY.AsGuid(), userLogin.PersonId.Value, HistoryChanges, UserName, typeof(UserLogin), this.Id, true, userLogin.ModifiedByPersonAliasId, null); } else { HistoryChanges.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, "Authentication Provider").SetOldValue(entityType?.FriendlyName).SetCaption("User Account"); HistoryService.SaveChanges(newRockContext, typeof(Person), Rock.SystemGuid.Category.HISTORY_PERSON_ACTIVITY.AsGuid(), userLogin.PersonId.Value, HistoryChanges, entityType?.FriendlyName, typeof(UserLogin), this.Id, true, userLogin.ModifiedByPersonAliasId, null); } } catch (Exception ex) { // Just log the problem and move on... ExceptionLogService.LogException(ex); } } HistoryChanges.Clear(); return; } } base.PreSaveChanges(dbContext, entry); }