Пример #1
0
        /// <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>
        /// 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);
        }
Пример #3
0
        /// <summary>
        /// Adds the new home location.
        /// </summary>
        /// <param name="ncoaHistory">The NCOA history.</param>
        /// <param name="locationService">The location service.</param>
        /// <param name="groupLocationService">The group location service.</param>
        /// <param name="homeValueId">The home value identifier.</param>
        /// <param name="changes">The changes.</param>
        /// <param name="isMailingLocation">Is the location a mailing location.</param>
        /// <param name="isMappedLocation">Is the location a mapped location.</param>
        /// <returns></returns>
        private bool AddNewHomeLocation(NcoaHistory ncoaHistory, LocationService locationService, GroupLocationService groupLocationService, int?homeValueId, History.HistoryChangeList changes, bool isMailingLocation, bool isMappedLocation)
        {
            if (homeValueId.HasValue)
            {
                var location = locationService.Get(
                    ncoaHistory.UpdatedStreet1,
                    ncoaHistory.UpdatedStreet2,
                    ncoaHistory.UpdatedCity,
                    ncoaHistory.UpdatedState,
                    ncoaHistory.UpdatedPostalCode,
                    ncoaHistory.UpdatedCountry);

                var groupLocation = new GroupLocation();
                groupLocation.Location                 = location;
                groupLocation.IsMailingLocation        = isMailingLocation;
                groupLocation.IsMappedLocation         = isMappedLocation;
                groupLocation.GroupId                  = ncoaHistory.FamilyId;
                groupLocation.GroupLocationTypeValueId = homeValueId.Value;
                groupLocation.IsMailingLocation        = true;
                groupLocationService.Add(groupLocation);

                changes.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Property, "Location").SetNewValue(groupLocation.Location.ToString()).SourceOfChange = "NCOA Request";

                return(true);
            }

            return(false);
        }
Пример #4
0
        /// <summary>
        /// Marks an address as previous location.
        /// </summary>
        /// <param name="ncoaHistory">The NCOA history.</param>
        /// <param name="groupLocationService">The group location service.</param>
        /// <param name="previousValueId">The previous value identifier.</param>
        /// <param name="changes">The changes.</param>
        /// <returns></returns>
        public GroupLocation MarkAsPreviousLocation(NcoaHistory ncoaHistory, GroupLocationService groupLocationService, int?previousValueId, History.HistoryChangeList changes)
        {
            if (ncoaHistory.LocationId.HasValue && previousValueId.HasValue)
            {
                var groupLocation = groupLocationService.Queryable()
                                    .Where(gl =>
                                           gl.GroupId == ncoaHistory.FamilyId &&
                                           gl.LocationId == ncoaHistory.LocationId &&
                                           gl.Location.Street1 == ncoaHistory.OriginalStreet1)
                                    .FirstOrDefault();
                if (groupLocation != null)
                {
                    if (groupLocation.GroupLocationTypeValueId != previousValueId.Value)
                    {
                        changes.AddChange(History.HistoryVerb.Modify, History.HistoryChangeType.Property, $"Location Type for {groupLocation.Location} ").SetNewValue("Previous").SourceOfChange = "NCOA Request";

                        groupLocation.GroupLocationTypeValueId = previousValueId.Value;
                    }

                    return(groupLocation);
                }
            }

            return(null);
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
        /// <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();
        }
Пример #7
0
        /// <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();
        }
Пример #8
0
        /// <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 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);
        }
Пример #10
0
        public void AddConnectionStatusChangeHistoryBulkTestData()
        {
            var dataContext = new RockContext();

            //this.ThrowIfTestHistoryDataExists( dataContext, _TestDataSourceOfChange );

            // Add Connection Status Change History Entries.
            var personService = new PersonService(dataContext);

            var personQuery = personService.Queryable()
                              .AsNoTracking()
                              .Where(x => !x.IsSystem)
                              .Take(_BulkHistoryMaxPeople).ToList();

            var statusType = DefinedTypeCache.Get(SystemGuid.DefinedType.PERSON_CONNECTION_STATUS);

            var statusValues = statusType.DefinedValues.Select(x => x.Id).ToList();

            int?toStatusId;
            int?fromStatusId;

            var rng = new Random();

            var adminPerson = this.GetAdminPersonOrThrow(personService);

            // For each person, add a random number of status changes over a random period of time prior to today.
            int entriesAdded = 0;

            foreach (var person in personQuery)
            {
                var historyChanges = new History.HistoryChangeList();

                var numberOfChanges = rng.Next(_BulkHistoryMinChangesPerPerson, _BulkHistoryMaxChangesPerPerson + 1);

                // Distribute the changes evenly throughout a random period of days.
                var changePeriodInDays = rng.Next(1, _BulkHistoryMaxPeriodInDays + 1);

                //var firstDate = lastDate.AddDays( changePeriodInDays  * -1 );

                decimal dayIncrement = Decimal.Divide(changePeriodInDays, numberOfChanges);
                decimal dayOffset    = 0;

                DateTime dateOfChange; // = _HistoryTestEndDate;

                // Set the initial value to the current status.
                fromStatusId = person.ConnectionStatusValueId;

                for (int i = 1; i <= numberOfChanges; i++)
                {
                    dateOfChange = _BulkHistoryEndDate.AddDays(( int )dayOffset * -1);

                    dayOffset = dayOffset + dayIncrement;

                    // Set the target status for this change to be the status prior to the most recent status change.
                    // This is to ensure that the status changes form a logical sequence.
                    toStatusId = fromStatusId;

                    do
                    {
                        fromStatusId = statusValues.GetRandomElement();
                    }while (toStatusId == fromStatusId);

                    var historyEntry = historyChanges.AddChange(History.HistoryVerb.Modify, History.HistoryChangeType.Property, "Connection Status")
                                       .SetNewValue(toStatusId.ToStringSafe())
                                       .SetOldValue(fromStatusId.ToStringSafe())
                                       .SetRawValues(fromStatusId.ToStringSafe(), toStatusId.ToStringSafe())
                                       .SetDateOfChange(dateOfChange)
                                       .SetSourceOfChange(_TestDataSourceOfChange);

                    entriesAdded++;

                    Debug.Print($"Added History Entry [Entry#={entriesAdded}, PersonId={person.Id}, Date={dateOfChange}, OldValue={fromStatusId}, NewValue={toStatusId}");
                }

                dataContext = new RockContext();

                HistoryService.SaveChanges(dataContext, typeof(Person), Rock.SystemGuid.Category.HISTORY_PERSON_DEMOGRAPHIC_CHANGES.AsGuid(), person.Id, historyChanges, true, adminPerson.PrimaryAliasId, _TestDataSourceOfChange);
            }

            Debug.Print($"Create Data completed: { entriesAdded } history entries created.");

            Assert.IsTrue(entriesAdded > 0, "No history entries created.");
        }
Пример #11
0
        /// <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);
        }
Пример #12
0
        /// <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();
                }
            }
        }
Пример #13
0
        /// <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);
        }
Пример #14
0
        //
        // Swipe Panel Events
        //

        private void ProcessSwipe(string swipeData)
        {
            try
            {
                using (var rockContext = new RockContext())
                {
                    // create swipe object
                    SwipePaymentInfo swipeInfo = new SwipePaymentInfo(swipeData);
                    swipeInfo.Amount = this.Amounts.Sum(a => a.Value);
                    var txnType = DefinedValueCache.Get(new Guid(Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION));
                    swipeInfo.TransactionTypeValueId = txnType.Id;

                    // if not anonymous then add contact info to the gateway transaction
                    if (this.AnonymousGiverPersonAliasId != this.SelectedGivingUnit.PersonAliasId)
                    {
                        var giver = new PersonAliasService(rockContext).Queryable("Person, Person.PhoneNumbers").Where(p => p.Id == this.SelectedGivingUnit.PersonAliasId).FirstOrDefault();
                        swipeInfo.FirstName = giver.Person.NickName;
                        swipeInfo.LastName  = giver.Person.LastName;

                        if (giver.Person.PhoneNumbers != null)
                        {
                            Guid homePhoneValueGuid = new Guid(Rock.SystemGuid.DefinedValue.PERSON_PHONE_TYPE_HOME);
                            var  homephone          = giver.Person.PhoneNumbers.Where(p => p.NumberTypeValue.Guid == homePhoneValueGuid).FirstOrDefault();
                            if (homephone != null)
                            {
                                swipeInfo.Phone = homephone.NumberFormatted;
                            }
                        }

                        var homeLocation = giver.Person.GetHomeLocation();

                        if (homeLocation != null)
                        {
                            swipeInfo.Street1 = homeLocation.Street1;

                            if (!string.IsNullOrWhiteSpace(homeLocation.Street2))
                            {
                                swipeInfo.Street2 = homeLocation.Street2;
                            }

                            swipeInfo.City       = homeLocation.City;
                            swipeInfo.State      = homeLocation.State;
                            swipeInfo.PostalCode = homeLocation.PostalCode;
                        }
                    }

                    // add comment to the transaction
                    swipeInfo.Comment1 = GetAttributeValue("PaymentComment");

                    // get gateway
                    FinancialGateway financialGateway = null;
                    GatewayComponent gateway          = null;
                    Guid?            gatewayGuid      = GetAttributeValue("CreditCardGateway").AsGuidOrNull();
                    if (gatewayGuid.HasValue)
                    {
                        financialGateway = new FinancialGatewayService(rockContext).Get(gatewayGuid.Value);
                        if (financialGateway != null)
                        {
                            financialGateway.LoadAttributes(rockContext);
                        }
                        gateway = financialGateway.GetGatewayComponent();
                    }

                    if (gateway != null)
                    {
                        string errorMessage = string.Empty;
                        var    transaction  = gateway.Charge(financialGateway, swipeInfo, out errorMessage);

                        if (transaction != null)
                        {
                            _transactionCode = transaction.TransactionCode;

                            var personName = new PersonAliasService(rockContext)
                                             .Queryable().AsNoTracking()
                                             .Where(a => a.Id == this.SelectedGivingUnit.PersonAliasId)
                                             .Select(a => a.Person.NickName + " " + a.Person.LastName)
                                             .FirstOrDefault();

                            transaction.AuthorizedPersonAliasId = this.SelectedGivingUnit.PersonAliasId;
                            transaction.TransactionDateTime     = RockDateTime.Now;
                            transaction.FinancialGatewayId      = financialGateway.Id;

                            transaction.TransactionTypeValueId = txnType.Id;

                            transaction.Summary = swipeInfo.Comment1;

                            if (transaction.FinancialPaymentDetail == null)
                            {
                                transaction.FinancialPaymentDetail = new FinancialPaymentDetail();
                            }
                            transaction.FinancialPaymentDetail.SetFromPaymentInfo(swipeInfo, gateway, rockContext);

                            Guid sourceGuid = Guid.Empty;
                            if (Guid.TryParse(GetAttributeValue("Source"), out sourceGuid))
                            {
                                var source = DefinedValueCache.Get(sourceGuid);
                                if (source != null)
                                {
                                    transaction.SourceTypeValueId = source.Id;
                                }
                            }

                            foreach (var accountAmount in this.Amounts.Where(a => a.Value > 0))
                            {
                                var transactionDetail = new FinancialTransactionDetail();
                                transactionDetail.Amount    = accountAmount.Value;
                                transactionDetail.AccountId = accountAmount.Key;
                                transaction.TransactionDetails.Add(transactionDetail);
                                var account = new FinancialAccountService(rockContext).Get(accountAmount.Key);
                            }

                            var batchService = new FinancialBatchService(rockContext);

                            // Get the batch
                            var batch = batchService.Get(
                                GetAttributeValue("BatchNamePrefix"),
                                swipeInfo.CurrencyTypeValue,
                                swipeInfo.CreditCardTypeValue,
                                transaction.TransactionDateTime.Value,
                                financialGateway.GetBatchTimeOffset());

                            var batchChanges = new History.HistoryChangeList();

                            if (batch.Id == 0)
                            {
                                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);
                            }

                            decimal newControlAmount = batch.ControlAmount + transaction.TotalAmount;
                            History.EvaluateChange(batchChanges, "Control Amount", batch.ControlAmount.FormatAsCurrency(), newControlAmount.FormatAsCurrency());
                            batch.ControlAmount = newControlAmount;

                            transaction.BatchId = batch.Id;
                            batch.Transactions.Add(transaction);

                            rockContext.WrapTransaction(() =>
                            {
                                rockContext.SaveChanges();
                                HistoryService.SaveChanges(
                                    rockContext,
                                    typeof(FinancialBatch),
                                    Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(),
                                    batch.Id,
                                    batchChanges
                                    );
                            });

                            // send receipt in one is configured and not giving anonymously
                            if (!string.IsNullOrWhiteSpace(GetAttributeValue("ReceiptEmail")) && (this.AnonymousGiverPersonAliasId != this.SelectedGivingUnit.PersonAliasId))
                            {
                                _receiptSent = true;

                                SendReceipt();
                            }

                            HidePanels();
                            ShowReceiptPanel();
                        }
                        else
                        {
                            lSwipeErrors.Text = String.Format("<div class='alert alert-danger'>An error occurred while process this transaction. Message: {0}</div>", errorMessage);
                        }
                    }
                    else
                    {
                        lSwipeErrors.Text = "<div class='alert alert-danger'>Invalid gateway provided. Please provide a gateway. Transaction not processed.</div>";
                    }
                }
            }
            catch (Exception ex)
            {
                lSwipeErrors.Text = String.Format("<div class='alert alert-danger'>An error occurred while process this transaction. Message: {0}</div>", ex.Message);
            }
        }
        /// <summary>
        /// Handles the Click event of the lbSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void lbSave_Click(object sender, EventArgs e)
        {
            var            rockContext  = new RockContext();
            var            batchService = new FinancialBatchService(rockContext);
            FinancialBatch batch        = null;

            var changes = new History.HistoryChangeList();

            int batchId = hfBatchId.Value.AsInteger();

            if (batchId == 0)
            {
                batch = new FinancialBatch();
                batchService.Add(batch);
                changes.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, "Batch");
            }
            else
            {
                batch = batchService.Get(batchId);
            }

            if (batch != null)
            {
                if (dvpBatchName.Visible)
                {
                    History.EvaluateChange(changes, "Batch Name", batch.Name, dvpBatchName.SelectedItem.Text);
                    batch.Name = dvpBatchName.SelectedItem.Text;
                }
                else
                {
                    History.EvaluateChange(changes, "Batch Name", batch.Name, tbName.Text);
                    batch.Name = tbName.Text;
                }

                BatchStatus batchStatus = (BatchStatus)ddlStatus.SelectedIndex;

                string errorMessage;
                if (!batch.IsValidBatchStatusChange(batch.Status, batchStatus, this.CurrentPerson, out errorMessage))
                {
                    cvBatch.IsValid      = false;
                    cvBatch.ErrorMessage = errorMessage;
                    return;
                }

                History.EvaluateChange(changes, "Status", batch.Status, batchStatus);
                batch.Status = batchStatus;

                CampusCache oldCampus = null;
                if (batch.CampusId.HasValue)
                {
                    oldCampus = CampusCache.Get(batch.CampusId.Value);
                }

                CampusCache newCampus = null;
                if (campCampus.SelectedCampusId.HasValue)
                {
                    newCampus = CampusCache.Get(campCampus.SelectedCampusId.Value);
                }

                History.EvaluateChange(changes, "Campus", oldCampus != null ? oldCampus.Name : "None", newCampus != null ? newCampus.Name : "None");
                batch.CampusId = campCampus.SelectedCampusId;

                DateTime?startDateTime = dtpStart.SelectedDateTimeIsBlank ? null : dtpStart.SelectedDateTime;
                History.EvaluateChange(changes, "Start Date/Time", batch.BatchStartDateTime, startDateTime);
                batch.BatchStartDateTime = startDateTime;

                DateTime?endDateTime;
                if (dtpEnd.SelectedDateTimeIsBlank && batch.BatchStartDateTime.HasValue)
                {
                    endDateTime = batch.BatchStartDateTime.Value.AddDays(1);
                }
                else
                {
                    endDateTime = dtpEnd.SelectedDateTimeIsBlank ? null : dtpEnd.SelectedDateTime;
                }

                History.EvaluateChange(changes, "End Date/Time", batch.BatchEndDateTime, endDateTime);
                batch.BatchEndDateTime = endDateTime;

                decimal controlAmount = tbControlAmount.Text.AsDecimal();
                History.EvaluateChange(changes, "Control Amount", batch.ControlAmount.FormatAsCurrency(), controlAmount.FormatAsCurrency());
                batch.ControlAmount = controlAmount;

                int?controlItemCount = nbControlItemCount.Text.AsIntegerOrNull();
                History.EvaluateChange(changes, "Control Item Count", batch.ControlItemCount.FormatAsCurrency(), controlItemCount.FormatAsCurrency());
                batch.ControlItemCount = controlItemCount;

                History.EvaluateChange(changes, "Accounting System Code", batch.AccountingSystemCode, tbAccountingCode.Text);
                batch.AccountingSystemCode = tbAccountingCode.Text;

                History.EvaluateChange(changes, "Notes", batch.Note, tbNote.Text);
                batch.Note = tbNote.Text;

                cvBatch.IsValid = batch.IsValid;
                if (!Page.IsValid || !batch.IsValid)
                {
                    cvBatch.ErrorMessage = batch.ValidationResults.Select(a => a.ErrorMessage).ToList().AsDelimited("<br />");
                    return;
                }

                batch.LoadAttributes(rockContext);
                Rock.Attribute.Helper.GetEditValues(phAttributes, batch);

                rockContext.WrapTransaction(() =>
                {
                    if (rockContext.SaveChanges() > 0)
                    {
                        if (changes.Any())
                        {
                            pdAuditDetails.SetEntity(batch, ResolveRockUrl("~"));
                            HistoryService.SaveChanges(
                                rockContext,
                                typeof(FinancialBatch),
                                Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(),
                                batch.Id,
                                changes);
                        }
                    }
                });

                batch.SaveAttributeValues(rockContext);

                if (batchId == 0)
                {
                    // If created a new batch, navigate to same page so that transaction list displays correctly
                    var pageReference = CurrentPageReference;
                    pageReference.Parameters.AddOrReplace("batchId", batch.Id.ToString());
                    NavigateToPage(pageReference);
                }
                else
                {
                    hfBatchId.SetValue(batch.Id);

                    // Requery the batch to support EF navigation properties
                    var savedBatch = GetBatch(batch.Id);
                    ShowReadonlyDetails(savedBatch);

                    // If there is a batch context item, update the context's properties with new values
                    var contextObjects = new Dictionary <string, object>();
                    foreach (var contextEntityType in RockPage.GetContextEntityTypes())
                    {
                        var contextEntity = RockPage.GetCurrentContext(contextEntityType);
                        if (contextEntity is FinancialBatch)
                        {
                            var contextBatch = contextEntity as FinancialBatch;
                            contextBatch.CopyPropertiesFrom(batch);
                        }
                    }

                    // Then refresh transaction list
                    RockPage.UpdateBlocks("~/Blocks/Finance/TransactionList.ascx");
                }
            }
        }
Пример #16
0
        /// <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);
        }
Пример #17
0
        /// <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);
        }
Пример #18
0
        /// <summary>
        /// This method is called in the
        /// <see cref="M:Rock.Data.Model`1.PreSaveChanges(Rock.Data.DbContext,System.Data.Entity.Infrastructure.DbEntityEntry,System.Data.Entity.EntityState)" />
        /// method. Use it to populate <see cref="P:Rock.Data.Model`1.HistoryItems" /> if needed.
        /// These history items are queued to be written into the database post save (so that they
        /// are only written if the save actually occurs).
        /// </summary>
        /// <param name="dbContext">The database context.</param>
        /// <param name="entry">The entry.</param>
        /// <param name="state">The state.</param>
        protected override void BuildHistoryItems(Data.DbContext dbContext, DbEntityEntry entry, EntityState state)
        {
            // Sometimes, especially if the model is being deleted, some properties might not be
            // populated, but we can query to try to get their original value. We need to use a new
            // rock context to get the actual value from the DB
            var rockContext   = new RockContext();
            var service       = new FinancialPersonSavedAccountService(rockContext);
            var originalModel = service.Queryable("PersonAlias, FinancialPaymentDetail")
                                .FirstOrDefault(fpsa => fpsa.Id == Id);

            // Use the original value for the person alias or the new value if that is not set
            var personId = (originalModel?.PersonAlias ?? PersonAlias)?.PersonId;

            if (!personId.HasValue)
            {
                // If this model is new, it won't have any virtual properties hydrated or an original
                // record in the database
                if (PersonAliasId.HasValue)
                {
                    var personAliasService = new PersonAliasService(rockContext);
                    var personAlias        = personAliasService.Get(PersonAliasId.Value);
                    personId = personAlias?.PersonId;
                }

                // We can't log history if we don't know who the saved account belongs to
                if (!personId.HasValue)
                {
                    return;
                }
            }

            History.HistoryVerb verb;

            switch (state)
            {
            case EntityState.Added:
                verb = History.HistoryVerb.Add;
                break;

            case EntityState.Deleted:
                verb = History.HistoryVerb.Delete;
                break;

            default:
                // As of now, there is no requirement to log other events
                return;
            }

            var historyChangeList = new History.HistoryChangeList();

            historyChangeList.AddChange(verb, History.HistoryChangeType.Record, "Financial Person Saved Account");

            HistoryItems = HistoryService.GetChanges(
                typeof(Person),
                Rock.SystemGuid.Category.HISTORY_PERSON.AsGuid(),
                personId.Value,
                historyChangeList,
                GetNameForHistory(originalModel?.FinancialPaymentDetail ?? FinancialPaymentDetail),
                typeof(FinancialPersonSavedAccount),
                Id,
                dbContext.GetCurrentPersonAlias()?.Id,
                dbContext.SourceOfChange);
        }
Пример #19
0
        public void AddConnectionStatusChangeHistoryTestData()
        {
            this.RemoveConnectionStatusChangeHistoryTestData();

            var dataContext = new RockContext();

            this.ThrowIfTestHistoryDataExists(dataContext, _TestDataSourceOfChange);

            var memberConnectionStatusId   = GetStatusValueIdOrThrow("Member");
            var attenderConnectionStatusId = GetStatusValueIdOrThrow("Attendee");
            var visitorConnectionStatusId  = GetStatusValueIdOrThrow("Visitor");
            var prospectConnectionStatusId = GetStatusValueIdOrThrow("Web Prospect");

            var personService = new PersonService(dataContext);

            var personList = personService.Queryable()
                             .AsNoTracking()
                             .Where(x => !x.IsSystem)
                             .Take(_BulkHistoryMaxPeople)
                             .ToList();

            var currentDate = _BulkHistoryEndDate;

            var rng = new Random();

            var adminPerson = this.GetAdminPersonOrThrow(personService);

            // Create new change history entries for each person.
            int entriesAdded = 0;

            History.HistoryChange historyEntry;

            foreach (var person in personList)
            {
                var historyChanges = new History.HistoryChangeList();

                var dateOfChange = currentDate;

                if (person.ConnectionStatusValueId == memberConnectionStatusId)
                {
                    // For each Person who has a Connection Status of Member, add prior change events for Visitor --> Attendee --> Member.

                    // Add a change for Attendee --> Member.
                    dateOfChange = dateOfChange.AddDays(rng.Next(1, 365) * -1);

                    historyEntry = historyChanges.AddChange(History.HistoryVerb.Modify, History.HistoryChangeType.Property, "Connection Status")
                                   .SetOldValue("Attendee")
                                   .SetNewValue("Member")
                                   .SetRawValues(attenderConnectionStatusId.ToString(), memberConnectionStatusId.ToString())
                                   .SetDateOfChange(dateOfChange)
                                   .SetSourceOfChange(_TestDataSourceOfChange);

                    // Add a change for Visitor --> Attendee.
                    // This change record has only the OldValue and NewValue, compatible with records created prior to Rock v1.8
                    dateOfChange = dateOfChange.AddDays(rng.Next(1, 365) * -1);

                    historyEntry = historyChanges.AddChange(History.HistoryVerb.Modify, History.HistoryChangeType.Property, "Connection Status")
                                   .SetOldValue("Visitor")
                                   .SetNewValue("Attendee")
                                   .SetDateOfChange(dateOfChange)
                                   .SetSourceOfChange(_TestDataSourceOfChange);

                    entriesAdded += 2;
                }
                else if (person.ConnectionStatusValueId == visitorConnectionStatusId)
                {
                    // For each Person who has a Connection Status of Visitor, add prior change events for Web Prospect --> Visitor.
                    dateOfChange = dateOfChange.AddDays(rng.Next(1, 365) * -1);

                    historyEntry = historyChanges.AddChange(History.HistoryVerb.Modify, History.HistoryChangeType.Property, "Connection Status")
                                   .SetOldValue("Web Prospect")
                                   .SetNewValue("Visitor")
                                   .SetRawValues(prospectConnectionStatusId.ToString(), visitorConnectionStatusId.ToString())
                                   .SetDateOfChange(dateOfChange)
                                   .SetSourceOfChange(_TestDataSourceOfChange);

                    entriesAdded += 1;
                }

                Debug.Print($"Processed History Entries... [PersonId={person.Id}, Date={dateOfChange}]");

                HistoryService.SaveChanges(dataContext, typeof(Person), Rock.SystemGuid.Category.HISTORY_PERSON_DEMOGRAPHIC_CHANGES.AsGuid(), person.Id, historyChanges, true, adminPerson.PrimaryAliasId, _TestDataSourceOfChange);
            }

            Debug.Print($"Create Data completed: { entriesAdded } history entries created.");

            Assert.IsTrue(entriesAdded > 0, "No history entries created.");
        }
Пример #20
0
        /// <summary>
        /// Process a refund for a transaction.
        /// </summary>
        /// <param name="transaction">The refund transaction.</param>
        /// <param name="amount">The amount.</param>
        /// <param name="reasonValueId">The reason value identifier.</param>
        /// <param name="summary">The summary.</param>
        /// <param name="process">if set to <c>true</c> [process].</param>
        /// <param name="batchNameSuffix">The batch name suffix.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public FinancialTransaction ProcessRefund(FinancialTransaction transaction, decimal?amount, int?reasonValueId, string summary, bool process, string batchNameSuffix, out string errorMessage)
        {
            errorMessage = string.Empty;

            // Validate parameters
            if (transaction == null)
            {
                errorMessage = "A valid transaction is required";
                return(null);
            }

            if (transaction.Batch == null)
            {
                errorMessage = "Transaction must belong to a batch";
                return(null);
            }

            if (!amount.HasValue || amount.Value <= 0.0m)
            {
                amount = transaction.TotalAmount;
            }

            if (!amount.HasValue || amount.Value <= 0.0m)
            {
                errorMessage = string.Format("Amount must be greater than {0}", 0.0m.FormatAsCurrency());
                return(null);
            }


            FinancialTransaction refundTransaction = null;

            // If processing the refund through gateway, get the gateway component and process a "Credit" transaction.
            if (process)
            {
                if (transaction.FinancialGateway == null || transaction.TransactionCode.IsNullOrWhiteSpace())
                {
                    errorMessage = "When processing the refund through the Gateway, the transaction must have a valid Gateway and Transaction Code";
                    return(null);
                }

                var gatewayComponent = transaction.FinancialGateway.GetGatewayComponent();
                if (gatewayComponent == null)
                {
                    errorMessage = "Could not get the Gateway component in order to process the refund";
                    return(null);
                }

                refundTransaction = gatewayComponent.Credit(transaction, amount.Value, summary, out errorMessage);
                if (refundTransaction == null)
                {
                    return(null);
                }
            }
            else
            {
                refundTransaction = new FinancialTransaction();
            }

            refundTransaction.AuthorizedPersonAliasId = transaction.AuthorizedPersonAliasId;
            refundTransaction.TransactionDateTime     = RockDateTime.Now;
            refundTransaction.FinancialGatewayId      = transaction.FinancialGatewayId;
            refundTransaction.TransactionTypeValueId  = transaction.TransactionTypeValueId;
            refundTransaction.SourceTypeValueId       = transaction.SourceTypeValueId;
            if (transaction.FinancialPaymentDetail != null)
            {
                refundTransaction.FinancialPaymentDetail = new FinancialPaymentDetail();
                refundTransaction.FinancialPaymentDetail.AccountNumberMasked      = transaction.FinancialPaymentDetail.AccountNumberMasked;
                refundTransaction.FinancialPaymentDetail.BillingLocationId        = transaction.FinancialPaymentDetail.BillingLocationId;
                refundTransaction.FinancialPaymentDetail.CreditCardTypeValueId    = transaction.FinancialPaymentDetail.CreditCardTypeValueId;
                refundTransaction.FinancialPaymentDetail.CurrencyTypeValueId      = transaction.FinancialPaymentDetail.CurrencyTypeValueId;
                refundTransaction.FinancialPaymentDetail.ExpirationMonthEncrypted = transaction.FinancialPaymentDetail.ExpirationMonthEncrypted;
                refundTransaction.FinancialPaymentDetail.ExpirationYearEncrypted  = transaction.FinancialPaymentDetail.ExpirationYearEncrypted;
                refundTransaction.FinancialPaymentDetail.NameOnCardEncrypted      = transaction.FinancialPaymentDetail.NameOnCardEncrypted;
            }

            decimal remainingBalance = amount.Value;

            foreach (var account in transaction.TransactionDetails.Where(a => a.Amount > 0))
            {
                var transactionDetail = new FinancialTransactionDetail();
                transactionDetail.AccountId    = account.AccountId;
                transactionDetail.EntityId     = account.EntityId;
                transactionDetail.EntityTypeId = account.EntityTypeId;
                refundTransaction.TransactionDetails.Add(transactionDetail);

                if (remainingBalance >= account.Amount)
                {
                    transactionDetail.Amount = 0 - account.Amount;
                    remainingBalance        -= account.Amount;
                }
                else
                {
                    transactionDetail.Amount = 0 - remainingBalance;
                    remainingBalance         = 0.0m;
                }

                if (remainingBalance <= 0.0m)
                {
                    break;
                }
            }

            if (remainingBalance > 0 && refundTransaction.TransactionDetails.Any())
            {
                refundTransaction.TransactionDetails.Last().Amount += remainingBalance;
            }

            var rockContext = this.Context as Rock.Data.RockContext;

            var registrationEntityType = EntityTypeCache.Get(typeof(Rock.Model.Registration));

            if (registrationEntityType != null)
            {
                foreach (var transactionDetail in refundTransaction.TransactionDetails
                         .Where(d =>
                                d.EntityTypeId.HasValue &&
                                d.EntityTypeId.Value == registrationEntityType.Id &&
                                d.EntityId.HasValue))
                {
                    var registrationChanges = new History.HistoryChangeList();
                    registrationChanges.AddChange(History.HistoryVerb.Process, History.HistoryChangeType.Record, $"{transactionDetail.Amount.FormatAsCurrency()} Refund");
                    HistoryService.SaveChanges(
                        rockContext,
                        typeof(Registration),
                        Rock.SystemGuid.Category.HISTORY_EVENT_REGISTRATION.AsGuid(),
                        transactionDetail.EntityId.Value,
                        registrationChanges
                        );
                }
            }

            refundTransaction.RefundDetails = new FinancialTransactionRefund();
            refundTransaction.RefundDetails.RefundReasonValueId   = reasonValueId;
            refundTransaction.RefundDetails.RefundReasonSummary   = summary;
            refundTransaction.RefundDetails.OriginalTransactionId = transaction.Id;

            string batchName = transaction.Batch.Name;

            if (batchNameSuffix.IsNotNullOrWhiteSpace() && !batchName.EndsWith(batchNameSuffix))
            {
                batchName += batchNameSuffix;
            }

            // Get the batch
            var      batchService = new FinancialBatchService(rockContext);
            TimeSpan timespan     = new TimeSpan();

            if (transaction.FinancialGateway != null)
            {
                timespan = transaction.FinancialGateway.GetBatchTimeOffset();
            }
            var batch = batchService.GetByNameAndDate(batchName, refundTransaction.TransactionDateTime.Value, timespan);

            // If this is a new Batch, SaveChanges so that we can get the Batch.Id
            if (batch.Id == 0)
            {
                rockContext.SaveChanges();
            }

            refundTransaction.BatchId = batch.Id;
            Add(refundTransaction);
            rockContext.SaveChanges();

            batchService.IncrementControlAmount(batch.Id, refundTransaction.TotalAmount, null);
            rockContext.SaveChanges();

            return(refundTransaction);
        }
Пример #21
0
        /// <summary>
        /// Handles the Click event of the btnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        protected void btnSave_Click(object sender, EventArgs e)
        {
            if (RegistrantState != null)
            {
                RockContext            rockContext                        = new RockContext();
                var                    personService                      = new PersonService(rockContext);
                var                    registrantService                  = new RegistrationRegistrantService(rockContext);
                var                    registrantFeeService               = new RegistrationRegistrantFeeService(rockContext);
                var                    registrationTemplateFeeService     = new RegistrationTemplateFeeService(rockContext);
                var                    registrationTemplateFeeItemService = new RegistrationTemplateFeeItemService(rockContext);
                RegistrationRegistrant registrant = null;
                if (RegistrantState.Id > 0)
                {
                    registrant = registrantService.Get(RegistrantState.Id);
                }

                var previousRegistrantPersonIds = registrantService.Queryable().Where(a => a.RegistrationId == RegistrantState.RegistrationId)
                                                  .Where(r => r.PersonAlias != null)
                                                  .Select(r => r.PersonAlias.PersonId)
                                                  .ToList();

                bool newRegistrant     = false;
                var  registrantChanges = new History.HistoryChangeList();

                if (registrant == null)
                {
                    newRegistrant             = true;
                    registrant                = new RegistrationRegistrant();
                    registrant.RegistrationId = RegistrantState.RegistrationId;
                    registrantService.Add(registrant);
                    registrantChanges.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, "Registrant");
                }

                if (!registrant.PersonAliasId.Equals(ppPerson.PersonAliasId))
                {
                    string prevPerson = (registrant.PersonAlias != null && registrant.PersonAlias.Person != null) ?
                                        registrant.PersonAlias.Person.FullName : string.Empty;
                    string newPerson = ppPerson.PersonName;
                    newRegistrant = true;
                    History.EvaluateChange(registrantChanges, "Person", prevPerson, newPerson);
                }

                int?personId = ppPerson.PersonId.Value;
                registrant.PersonAliasId = ppPerson.PersonAliasId.Value;

                // Get the name of registrant for history
                string registrantName = "Unknown";
                if (ppPerson.PersonId.HasValue)
                {
                    var person = personService.Get(ppPerson.PersonId.Value);
                    if (person != null)
                    {
                        registrantName = person.FullName;
                    }
                }

                // set their status (wait list / registrant)
                registrant.OnWaitList = !tglWaitList.Checked;

                History.EvaluateChange(registrantChanges, "Cost", registrant.Cost, cbCost.Text.AsDecimal());
                registrant.Cost = cbCost.Text.AsDecimal();

                History.EvaluateChange(registrantChanges, "Discount Applies", registrant.DiscountApplies, cbDiscountApplies.Checked);
                registrant.DiscountApplies = cbDiscountApplies.Checked;

                if (!Page.IsValid)
                {
                    return;
                }

                // Remove/delete any registrant fees that are no longer in UI with quantity
                foreach (var dbFee in registrant.Fees.ToList())
                {
                    if (!RegistrantState.FeeValues.Keys.Contains(dbFee.RegistrationTemplateFeeId) ||
                        RegistrantState.FeeValues[dbFee.RegistrationTemplateFeeId] == null ||
                        !RegistrantState.FeeValues[dbFee.RegistrationTemplateFeeId]
                        .Any(f =>
                             f.RegistrationTemplateFeeItemId == dbFee.RegistrationTemplateFeeItemId &&
                             f.Quantity > 0))
                    {
                        var feeOldValue = string.Format("'{0}' Fee (Quantity:{1:N0}, Cost:{2:C2}, Option:{3}",
                                                        dbFee.RegistrationTemplateFee.Name, dbFee.Quantity, dbFee.Cost, dbFee.Option);

                        registrantChanges.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, "Fee").SetOldValue(feeOldValue);
                        registrant.Fees.Remove(dbFee);
                        registrantFeeService.Delete(dbFee);
                    }
                }

                // Add/Update any of the fees from UI
                foreach (var uiFee in RegistrantState.FeeValues.Where(f => f.Value != null))
                {
                    foreach (var uiFeeOption in uiFee.Value)
                    {
                        var dbFee = registrant.Fees
                                    .Where(f =>
                                           f.RegistrationTemplateFeeId == uiFee.Key &&
                                           f.RegistrationTemplateFeeItemId == uiFeeOption.RegistrationTemplateFeeItemId)
                                    .FirstOrDefault();

                        if (dbFee == null)
                        {
                            dbFee = new RegistrationRegistrantFee();
                            dbFee.RegistrationTemplateFeeId = uiFee.Key;
                            var registrationTemplateFeeItem = uiFeeOption.RegistrationTemplateFeeItemId != null?registrationTemplateFeeItemService.GetNoTracking(uiFeeOption.RegistrationTemplateFeeItemId.Value) : null;

                            if (registrationTemplateFeeItem != null)
                            {
                                dbFee.Option = registrationTemplateFeeItem.Name;
                            }

                            dbFee.RegistrationTemplateFeeItemId = uiFeeOption.RegistrationTemplateFeeItemId;
                            registrant.Fees.Add(dbFee);
                        }

                        var templateFee = dbFee.RegistrationTemplateFee;
                        if (templateFee == null)
                        {
                            templateFee = registrationTemplateFeeService.Get(uiFee.Key);
                        }

                        string feeName = templateFee != null ? templateFee.Name : "Fee";
                        if (!string.IsNullOrWhiteSpace(uiFeeOption.FeeLabel))
                        {
                            feeName = string.Format("{0} ({1})", feeName, uiFeeOption.FeeLabel);
                        }

                        if (dbFee.Id <= 0)
                        {
                            registrantChanges.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, "Fee").SetNewValue(feeName);
                        }

                        History.EvaluateChange(registrantChanges, feeName + " Quantity", dbFee.Quantity, uiFeeOption.Quantity);
                        dbFee.Quantity = uiFeeOption.Quantity;

                        History.EvaluateChange(registrantChanges, feeName + " Cost", dbFee.Cost, uiFeeOption.Cost);
                        dbFee.Cost = uiFeeOption.Cost;
                    }
                }

                if (this.RegistrationTemplate.RequiredSignatureDocumentTemplate != null)
                {
                    var person = new PersonService(rockContext).Get(personId.Value);

                    var documentService        = new SignatureDocumentService(rockContext);
                    var binaryFileService      = new BinaryFileService(rockContext);
                    SignatureDocument document = null;

                    int?signatureDocumentId = hfSignedDocumentId.Value.AsIntegerOrNull();
                    int?binaryFileId        = fuSignedDocument.BinaryFileId;
                    if (signatureDocumentId.HasValue)
                    {
                        document = documentService.Get(signatureDocumentId.Value);
                    }

                    if (document == null && binaryFileId.HasValue)
                    {
                        var instance = new RegistrationInstanceService(rockContext).Get(RegistrationInstanceId);

                        document = new SignatureDocument();
                        document.SignatureDocumentTemplateId = this.RegistrationTemplate.RequiredSignatureDocumentTemplate.Id;
                        document.AppliesToPersonAliasId      = registrant.PersonAliasId.Value;
                        document.AssignedToPersonAliasId     = registrant.PersonAliasId.Value;
                        document.Name = string.Format(
                            "{0}_{1}",
                            instance != null ? instance.Name : this.RegistrationTemplate.Name,
                            person != null ? person.FullName.RemoveSpecialCharacters() : string.Empty);
                        document.Status         = SignatureDocumentStatus.Signed;
                        document.LastStatusDate = RockDateTime.Now;
                        documentService.Add(document);
                    }

                    if (document != null)
                    {
                        int?origBinaryFileId = document.BinaryFileId;
                        document.BinaryFileId = binaryFileId;

                        if (origBinaryFileId.HasValue && origBinaryFileId.Value != document.BinaryFileId)
                        {
                            // if a new the binaryFile was uploaded, mark the old one as Temporary so that it gets cleaned up
                            var oldBinaryFile = binaryFileService.Get(origBinaryFileId.Value);
                            if (oldBinaryFile != null && !oldBinaryFile.IsTemporary)
                            {
                                oldBinaryFile.IsTemporary = true;
                            }
                        }

                        // ensure the IsTemporary is set to false on binaryFile associated with this document
                        if (document.BinaryFileId.HasValue)
                        {
                            var binaryFile = binaryFileService.Get(document.BinaryFileId.Value);
                            if (binaryFile != null && binaryFile.IsTemporary)
                            {
                                binaryFile.IsTemporary = false;
                            }
                        }
                    }
                }

                if (!registrant.IsValid)
                {
                    // Controls will render the error messages
                    return;
                }

                // use WrapTransaction since SaveAttributeValues does it's own RockContext.SaveChanges()
                rockContext.WrapTransaction(() =>
                {
                    rockContext.SaveChanges();

                    registrant.LoadAttributes();
                    // NOTE: We will only have Registration Attributes displayed and editable on Registrant Detail.
                    // To Edit Person or GroupMember Attributes, they will have to go the PersonDetail or GroupMemberDetail blocks
                    foreach (var field in this.RegistrationTemplate.Forms
                             .SelectMany(f => f.Fields
                                         .Where(t =>
                                                t.FieldSource == RegistrationFieldSource.RegistrantAttribute &&
                                                t.AttributeId.HasValue)))
                    {
                        var attribute = AttributeCache.Get(field.AttributeId.Value);
                        if (attribute != null)
                        {
                            string originalValue = registrant.GetAttributeValue(attribute.Key);
                            var fieldValue       = RegistrantState.FieldValues
                                                   .Where(f => f.Key == field.Id)
                                                   .Select(f => f.Value.FieldValue)
                                                   .FirstOrDefault();
                            string newValue = fieldValue != null ? fieldValue.ToString() : string.Empty;

                            if ((originalValue ?? string.Empty).Trim() != (newValue ?? string.Empty).Trim())
                            {
                                string formattedOriginalValue = string.Empty;
                                if (!string.IsNullOrWhiteSpace(originalValue))
                                {
                                    formattedOriginalValue = attribute.FieldType.Field.FormatValue(null, originalValue, attribute.QualifierValues, false);
                                }

                                string formattedNewValue = string.Empty;
                                if (!string.IsNullOrWhiteSpace(newValue))
                                {
                                    formattedNewValue = attribute.FieldType.Field.FormatValue(null, newValue, attribute.QualifierValues, false);
                                }

                                History.EvaluateChange(registrantChanges, attribute.Name, formattedOriginalValue, formattedNewValue);
                            }

                            if (fieldValue != null)
                            {
                                registrant.SetAttributeValue(attribute.Key, fieldValue.ToString());
                            }
                        }
                    }

                    registrant.SaveAttributeValues(rockContext);
                });

                if (newRegistrant && this.RegistrationTemplate.GroupTypeId.HasValue && ppPerson.PersonId.HasValue)
                {
                    using (var newRockContext = new RockContext())
                    {
                        var reloadedRegistrant = new RegistrationRegistrantService(newRockContext).Get(registrant.Id);
                        if (reloadedRegistrant != null &&
                            reloadedRegistrant.Registration != null &&
                            reloadedRegistrant.Registration.Group != null &&
                            reloadedRegistrant.Registration.Group.GroupTypeId == this.RegistrationTemplate.GroupTypeId.Value)
                        {
                            int?groupRoleId = this.RegistrationTemplate.GroupMemberRoleId.HasValue ?
                                              this.RegistrationTemplate.GroupMemberRoleId.Value :
                                              reloadedRegistrant.Registration.Group.GroupType.DefaultGroupRoleId;
                            if (groupRoleId.HasValue)
                            {
                                var groupMemberService = new GroupMemberService(newRockContext);
                                var groupMember        = groupMemberService
                                                         .Queryable().AsNoTracking()
                                                         .Where(m =>
                                                                m.GroupId == reloadedRegistrant.Registration.Group.Id &&
                                                                m.PersonId == reloadedRegistrant.PersonId &&
                                                                m.GroupRoleId == groupRoleId.Value)
                                                         .FirstOrDefault();
                                if (groupMember == null)
                                {
                                    groupMember                   = new GroupMember();
                                    groupMember.GroupId           = reloadedRegistrant.Registration.Group.Id;
                                    groupMember.PersonId          = ppPerson.PersonId.Value;
                                    groupMember.GroupRoleId       = groupRoleId.Value;
                                    groupMember.GroupMemberStatus = this.RegistrationTemplate.GroupMemberStatus;
                                    groupMemberService.Add(groupMember);

                                    newRockContext.SaveChanges();

                                    registrantChanges.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, string.Format("Registrant to {0} group", reloadedRegistrant.Registration.Group.Name));
                                }
                                else
                                {
                                    registrantChanges.AddChange(History.HistoryVerb.Modify, History.HistoryChangeType.Record, string.Format("Registrant to existing person in {0} group", reloadedRegistrant.Registration.Group.Name));
                                }

                                if (reloadedRegistrant.GroupMemberId.HasValue && reloadedRegistrant.GroupMemberId.Value != groupMember.Id)
                                {
                                    groupMemberService.Delete(reloadedRegistrant.GroupMember);
                                    newRockContext.SaveChanges();
                                    registrantChanges.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, string.Format("Registrant to previous person in {0} group", reloadedRegistrant.Registration.Group.Name));
                                }

                                // Record this to the Person's and Registrants Notes and History...

                                reloadedRegistrant.GroupMemberId = groupMember.Id;
                            }
                        }
                        if (reloadedRegistrant.Registration.FirstName.IsNotNullOrWhiteSpace() && reloadedRegistrant.Registration.LastName.IsNotNullOrWhiteSpace())
                        {
                            reloadedRegistrant.Registration.SavePersonNotesAndHistory(reloadedRegistrant.Registration.FirstName, reloadedRegistrant.Registration.LastName, this.CurrentPersonAliasId, previousRegistrantPersonIds);
                        }
                        newRockContext.SaveChanges();
                    }
                }

                HistoryService.SaveChanges(
                    rockContext,
                    typeof(Registration),
                    Rock.SystemGuid.Category.HISTORY_EVENT_REGISTRATION.AsGuid(),
                    registrant.RegistrationId,
                    registrantChanges,
                    "Registrant: " + registrantName,
                    null,
                    null);
            }

            NavigateToRegistration();
        }
Пример #22
0
        /// <summary>
        /// This method is called in the
        /// <see cref="M:Rock.Data.Model`1.PreSaveChanges(Rock.Data.DbContext,System.Data.Entity.Infrastructure.DbEntityEntry,System.Data.Entity.EntityState)" />
        /// method. Use it to populate <see cref="P:Rock.Data.Model`1.HistoryItems" /> if needed.
        /// These history items are queued to be written into the database post save (so that they
        /// are only written if the save actually occurs).
        /// </summary>
        /// <param name="dbContext">The database context.</param>
        /// <param name="entry">The entry.</param>
        /// <param name="state">The state.</param>
        protected override void BuildHistoryItems(Data.DbContext dbContext, DbEntityEntry entry, EntityState state)
        {
            /*
             * 12/18/2019 BJW
             *
             * We want to log the history of attribute values within a person matrix. Most of this logging occurs from
             * the attribute value model. However, when a matrix item (row in the table) is deleted, the pre-save event
             * of the attribute values is not called. Therefore, the delete event needs to be logged here. Additionally,
             * when the matrix item is added, the history is much cleaner when added here so that all the values of the
             * row are consolidated to one history item.  Modified state is not possible to log here because the
             * matrix item is not actually modified when its attributes change.
             *
             * Task: https://app.asana.com/0/1120115219297347/1136643182208595/f
             */

            if (state != EntityState.Deleted && state != EntityState.Added)
            {
                return;
            }

            var rockContext = new RockContext();
            var matrixId    = AttributeMatrixId != default ?
                              AttributeMatrixId :
                              entry.OriginalValues["AttributeMatrixId"].ToStringSafe().AsIntegerOrNull();

            var matrix = AttributeMatrix;

            if (matrix == null && matrixId.HasValue)
            {
                var matrixService = new AttributeMatrixService(rockContext);
                matrix = matrixService.Queryable().AsNoTracking().FirstOrDefault(am => am.Id == matrixId);
            }

            if (matrix == null)
            {
                return;
            }

            // The root attribute matrix attribute value is linked to the matrix by the guid as the attribute value
            var matrixGuidString      = matrix.Guid.ToString();
            var personEntityTypeId    = EntityTypeCache.Get(typeof(Person)).Id;
            var attributeValueService = new AttributeValueService(rockContext);
            var rootAttributeValue    = attributeValueService.Queryable().AsNoTracking().FirstOrDefault(av =>
                                                                                                        av.Value.Equals(matrixGuidString, System.StringComparison.OrdinalIgnoreCase) &&
                                                                                                        av.Attribute.EntityTypeId == personEntityTypeId
                                                                                                        );

            if (rootAttributeValue?.EntityId == null)
            {
                return;
            }

            var rootAttributeCache = AttributeCache.Get(rootAttributeValue.AttributeId);

            if (rootAttributeCache == null)
            {
                return;
            }

            // Evaluate the history changes
            var historyChangeList = new History.HistoryChangeList();

            if (AttributeValues == null || !AttributeValues.Any())
            {
                this.LoadAttributes();
            }

            var isDelete = state == EntityState.Deleted;

            foreach (var attributeValue in AttributeValues.Values)
            {
                var attributeCache    = AttributeCache.Get(attributeValue.AttributeId);
                var formattedOldValue = isDelete ? GetHistoryFormattedValue(attributeValue.Value, attributeCache) : string.Empty;
                var formattedNewValue = isDelete ? string.Empty : GetHistoryFormattedValue(attributeValue.Value, attributeCache);
                History.EvaluateChange(historyChangeList, attributeCache.Name, formattedOldValue, formattedNewValue, attributeCache.FieldType.Field.IsSensitive());
            }

            if (!historyChangeList.Any())
            {
                historyChangeList.AddChange(
                    isDelete ? History.HistoryVerb.Delete : History.HistoryVerb.Add,
                    History.HistoryChangeType.Record,
                    $"{rootAttributeCache.Name} Item");
            }

            HistoryItems = HistoryService.GetChanges(
                typeof(Person),
                SystemGuid.Category.HISTORY_PERSON_DEMOGRAPHIC_CHANGES.AsGuid(),
                rootAttributeValue.EntityId.Value,
                historyChangeList,
                rootAttributeCache.Name,
                typeof(Attribute),
                rootAttributeCache.Id,
                dbContext.GetCurrentPersonAlias()?.Id,
                dbContext.SourceOfChange);
        }
Пример #23
0
        /// <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;
                        }
                    }
                }
            }
        }
Пример #24
0
        /// <summary>
        /// Handles the Swipe event of the csPayWithCard control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="SwipeEventArgs"/> instance containing the event data.</param>
        protected void csPayWithCard_Swipe(object sender, SwipeEventArgs e)
        {
            using (var rockContext = new RockContext())
            {
                try
                {
                    var swipeInfo = e.PaymentInfo;
                    var person    = Customer;

                    if (person == null)
                    {
                        person = new PersonAliasService(rockContext).GetPerson(GetAttributeValue("GuestCustomer").AsGuid());

                        if (person == null)
                        {
                            nbSwipeErrors.Text = "No guest customer configured. Transaction not processed.";
                            return;
                        }
                    }

                    //
                    // Get the gateway to use.
                    //
                    FinancialGateway financialGateway = null;
                    GatewayComponent gateway          = null;
                    Guid?            gatewayGuid      = GetAttributeValue("CreditCardGateway").AsGuidOrNull();
                    if (gatewayGuid.HasValue)
                    {
                        financialGateway = new FinancialGatewayService(rockContext).Get(gatewayGuid.Value);

                        if (financialGateway != null)
                        {
                            financialGateway.LoadAttributes(rockContext);
                        }

                        gateway = financialGateway.GetGatewayComponent();
                    }

                    if (gateway == null)
                    {
                        nbSwipeErrors.Text = "Invalid gateway provided. Please provide a gateway. Transaction not processed.";
                        return;
                    }

                    swipeInfo.Amount = Cart.Total;

                    //
                    // Process the transaction.
                    //
                    string errorMessage = string.Empty;
                    var    transaction  = gateway.Charge(financialGateway, swipeInfo, out errorMessage);

                    if (transaction == null)
                    {
                        nbSwipeErrors.Text = String.Format("An error occurred while process this transaction. Message: {0}", errorMessage);
                        return;
                    }

                    //
                    // Set some common information about the transaction.
                    //
                    transaction.AuthorizedPersonAliasId = person.PrimaryAliasId;
                    transaction.TransactionDateTime     = RockDateTime.Now;
                    transaction.FinancialGatewayId      = financialGateway.Id;
                    transaction.TransactionTypeValueId  = DefinedValueCache.Get(GetAttributeValue("TransactionType")).Id;
                    transaction.SourceTypeValueId       = DefinedValueCache.Get(GetAttributeValue("Source")).Id;
                    transaction.Summary = swipeInfo.Comment1;

                    //
                    // Ensure we have payment details.
                    //
                    if (transaction.FinancialPaymentDetail == null)
                    {
                        transaction.FinancialPaymentDetail = new FinancialPaymentDetail();
                    }
                    transaction.FinancialPaymentDetail.SetFromPaymentInfo(swipeInfo, gateway, rockContext);

                    //
                    // Setup the transaction details to credit the correct account.
                    //
                    GetTransactionDetails(rockContext).ForEach(d => transaction.TransactionDetails.Add(d));

                    var batchService = new FinancialBatchService(rockContext);

                    //
                    // Get the batch
                    //
                    var batch = batchService.Get(
                        GetAttributeValue("BatchNamePrefix"),
                        swipeInfo.CurrencyTypeValue,
                        swipeInfo.CreditCardTypeValue,
                        transaction.TransactionDateTime.Value,
                        financialGateway.GetBatchTimeOffset());

                    var batchChanges = new History.HistoryChangeList();

                    if (batch.Id == 0)
                    {
                        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);
                    }

                    //
                    // Update the control amount.
                    //
                    decimal newControlAmount = batch.ControlAmount + transaction.TotalAmount;
                    History.EvaluateChange(batchChanges, "Control Amount", batch.ControlAmount.FormatAsCurrency(), newControlAmount.FormatAsCurrency());
                    batch.ControlAmount = newControlAmount;

                    //
                    // Add the transaction to the batch.
                    //
                    transaction.BatchId = batch.Id;
                    batch.Transactions.Add(transaction);

                    //
                    // Generate the receipt.
                    //
                    int receiptId;
                    using (var rockContext2 = new RockContext())
                    {
                        var receipt = GenerateReceipt(rockContext2);
                        receiptId = receipt.Id;
                    }

                    //
                    // Update each transaction detail to reference the receipt.
                    //
                    foreach (var transactionDetail in transaction.TransactionDetails)
                    {
                        transactionDetail.EntityTypeId = EntityTypeCache.Get(typeof(InteractionComponent)).Id;
                        transactionDetail.EntityId     = receiptId;
                    }

                    rockContext.WrapTransaction(() =>
                    {
                        rockContext.SaveChanges();

                        HistoryService.SaveChanges(
                            rockContext,
                            typeof(FinancialBatch),
                            Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(),
                            batch.Id,
                            batchChanges
                            );
                    });

                    ShowReceiptPanel();
                }
                catch (Exception ex)
                {
                    nbSwipeErrors.Text = String.Format("An error occurred while process this transaction. Message: {0}", ex.Message);
                }
            }
        }
Пример #25
0
        /// <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
            Person person = 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.GetWorklowAttributeValue(guidPersonAttribute.Value);
                    if (!string.IsNullOrWhiteSpace(attributePersonValue))
                    {
                        Guid personAliasGuid = attributePersonValue.AsGuid();
                        if (!personAliasGuid.IsEmpty())
                        {
                            person = new PersonAliasService(rockContext).Queryable()
                                     .Where(a => a.Guid.Equals(personAliasGuid))
                                     .Select(a => a.Person)
                                     .FirstOrDefault();
                            if (person == null)
                            {
                                errorMessages.Add(string.Format("Person could not be found for selected value ('{0}')!", guidPersonAttribute.ToString()));
                                return(false);
                            }
                        }
                    }
                }
            }

            if (person == null)
            {
                errorMessages.Add("The attribute used to provide the person was invalid, or not of type 'Person'.");
                return(false);
            }

            // determine the location type to edit
            DefinedValueCache locationType = null;
            var locationTypeAttributeValue = action.GetWorklowAttributeValue(GetAttributeValue(action, "LocationTypeAttribute").AsGuid());

            if (locationTypeAttributeValue != null)
            {
                locationType = DefinedValueCache.Get(locationTypeAttributeValue.AsGuid());
            }
            if (locationType == null)
            {
                locationType = DefinedValueCache.Get(GetAttributeValue(action, "LocationType").AsGuid());
            }
            if (locationType == null)
            {
                errorMessages.Add("The location type to be updated was not selected.");
                return(false);
            }

            // get the new phone number value
            Location location      = null;
            string   locationValue = GetAttributeValue(action, "Location");
            Guid?    locationGuid  = locationValue.AsGuidOrNull();

            if (!locationGuid.HasValue || locationGuid.Value.IsEmpty())
            {
                string locationAttributeValue     = GetAttributeValue(action, "LocationAttribute");
                Guid?  locationAttributeValueGuid = locationAttributeValue.AsGuidOrNull();
                if (locationAttributeValueGuid.HasValue)
                {
                    locationGuid = action.GetWorklowAttributeValue(locationAttributeValueGuid.Value).AsGuidOrNull();
                }
            }

            if (locationGuid.HasValue)
            {
                location = new LocationService(rockContext).Get(locationGuid.Value);
            }

            if (location == null)
            {
                errorMessages.Add("The location value could not be determined.");
                return(false);
            }

            // gets value indicating if location is a mailing location
            string mailingValue     = GetAttributeValue(action, "IsMailing");
            Guid?  mailingValueGuid = mailingValue.AsGuidOrNull();

            if (mailingValueGuid.HasValue)
            {
                mailingValue = action.GetWorklowAttributeValue(mailingValueGuid.Value);
            }
            else
            {
                mailingValue = mailingValue.ResolveMergeFields(GetMergeFields(action));
            }
            bool?mailing = mailingValue.AsBooleanOrNull();

            // gets value indicating if location is a mapped location
            string mappedValue     = GetAttributeValue(action, "IsMapped");
            Guid?  mappedValueGuid = mappedValue.AsGuidOrNull();

            if (mappedValueGuid.HasValue)
            {
                mappedValue = action.GetWorklowAttributeValue(mappedValueGuid.Value);
            }
            else
            {
                mappedValue = mappedValue.ResolveMergeFields(GetMergeFields(action));
            }
            bool?mapped = mappedValue.AsBooleanOrNull();

            var savePreviousAddress = GetAttributeValue(action, "SavePreviousAddress").AsBoolean();

            var locationService = new LocationService(rockContext);

            locationService.Verify(location, false);

            var groupLocationService = new GroupLocationService(rockContext);

            foreach (var family in person.GetFamilies(rockContext).ToList())
            {
                bool locationUpdated = false;

                if (savePreviousAddress)
                {
                    // Get all existing addresses of the specified type
                    var groupLocations = family.GroupLocations.Where(l => l.GroupLocationTypeValueId == locationType.Id).ToList();

                    // Create a new address of the specified type, saving all existing addresses of that type as Previous Addresses
                    // Use the specified Is Mailing and Is Mapped values from the action's parameters if they are set,
                    // otherwise set them to true if any of the existing addresses of that type have those values set to true
                    GroupService.AddNewGroupAddress(rockContext, family, locationType.Guid.ToString(), location.Id, true,
                                                    $"the {action.ActionTypeCache.ActivityType.WorkflowType.Name} workflow",
                                                    mailing ?? groupLocations.Any(x => x.IsMailingLocation),
                                                    mapped ?? groupLocations.Any(x => x.IsMappedLocation));
                }
                else
                {
                    var    groupLocation = family.GroupLocations.FirstOrDefault(l => l.GroupLocationTypeValueId == locationType.Id);
                    string oldValue      = string.Empty;
                    if (groupLocation == null)
                    {
                        groupLocation         = new GroupLocation();
                        groupLocation.GroupId = family.Id;
                        groupLocation.GroupLocationTypeValueId = locationType.Id;
                        groupLocationService.Add(groupLocation);
                    }
                    else
                    {
                        oldValue = groupLocation.Location.ToString();
                    }

                    locationUpdated = oldValue != location.ToString();

                    groupLocation.Location = location;

                    if (mailing.HasValue)
                    {
                        if (((oldValue == string.Empty) ? null : groupLocation.IsMailingLocation.ToString()) != mailing.Value.ToString())
                        {
                            locationUpdated = true;
                        }
                        groupLocation.IsMailingLocation = mailing.Value;
                    }

                    if (mapped.HasValue)
                    {
                        if (((oldValue == string.Empty) ? null : groupLocation.IsMappedLocation.ToString()) != mapped.Value.ToString())
                        {
                            locationUpdated = true;
                        }
                        groupLocation.IsMappedLocation = mapped.Value;
                    }
                }

                if (locationUpdated)
                {
                    var groupChanges = new History.HistoryChangeList();
                    groupChanges.AddChange(History.HistoryVerb.Modify, History.HistoryChangeType.Record, "Location").SourceOfChange = $"{action.ActionTypeCache.ActivityType.WorkflowType.Name} workflow";

                    foreach (var fm in family.Members)
                    {
                        HistoryService.SaveChanges(
                            rockContext,
                            typeof(Person),
                            Rock.SystemGuid.Category.HISTORY_PERSON_FAMILY_CHANGES.AsGuid(),
                            fm.PersonId,
                            groupChanges,
                            family.Name,
                            typeof(Group),
                            family.Id,
                            false,
                            null,
                            rockContext.SourceOfChange);
                    }
                }

                rockContext.SaveChanges();

                action.AddLogEntry(string.Format("Updated the {0} location for {1} (family: {2}) to {3}", locationType.Value, person.FullName, family.Name, location.ToString()));
            }

            return(true);
        }
Пример #26
0
        /// <summary>
        /// Updates the last login and writes to the person's history log
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        public static void UpdateLastLogin(string userName)
        {
            if (!string.IsNullOrWhiteSpace(userName))
            {
                using (var rockContext = new RockContext())
                {
                    int? personId     = null;
                    bool impersonated = userName.StartsWith("rckipid=");

                    if (!impersonated)
                    {
                        var userLogin = new UserLoginService(rockContext).GetByUserName(userName);
                        if (userLogin != null)
                        {
                            userLogin.LastLoginDateTime = RockDateTime.Now;
                            personId = userLogin.PersonId;
                        }
                    }
                    else
                    {
                        var impersonationToken = userName.Substring(8);
                        personId = new PersonService(rockContext).GetByImpersonationToken(impersonationToken, false, null)?.Id;
                    }

                    if (personId.HasValue)
                    {
                        var relatedDataBuilder  = new System.Text.StringBuilder();
                        int?relatedEntityTypeId = null;
                        int?relatedEntityId     = null;

                        if (impersonated)
                        {
                            var impersonatedByUser = HttpContext.Current?.Session["ImpersonatedByUser"] as UserLogin;

                            relatedEntityTypeId = EntityTypeCache.GetId <Rock.Model.Person>();
                            relatedEntityId     = impersonatedByUser?.PersonId;

                            if (impersonatedByUser != null)
                            {
                                relatedDataBuilder.Append($" impersonated by { impersonatedByUser.Person.FullName }");
                            }
                        }

                        if (HttpContext.Current != null && HttpContext.Current.Request != null)
                        {
                            string cleanUrl = PersonToken.ObfuscateRockMagicToken(HttpContext.Current.Request.Url.AbsoluteUri);

                            // obfuscate the url specified in the returnurl, just in case it contains any sensitive information (like a rckipid)
                            Regex returnurlRegEx = new Regex(@"returnurl=([^&]*)");
                            cleanUrl = returnurlRegEx.Replace(cleanUrl, "returnurl=XXXXXXXXXXXXXXXXXXXXXXXXXXXX");

                            relatedDataBuilder.AppendFormat(" to <span class='field-value'>{0}</span>, from <span class='field-value'>{1}</span>",
                                                            cleanUrl, HttpContext.Current.Request.UserHostAddress);
                        }

                        var historyChangeList = new History.HistoryChangeList();
                        var historyChange     = historyChangeList.AddChange(History.HistoryVerb.Login, History.HistoryChangeType.Record, userName);

                        if (relatedDataBuilder.Length > 0)
                        {
                            historyChange.SetRelatedData(relatedDataBuilder.ToString(), null, null);
                        }

                        HistoryService.SaveChanges(rockContext, typeof(Rock.Model.Person), Rock.SystemGuid.Category.HISTORY_PERSON_ACTIVITY.AsGuid(), personId.Value, historyChangeList, true);
                    }
                }
            }
        }
        /// <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;

            HistoryChangeList = new History.HistoryChangeList();

            switch (entry.State)
            {
            case 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, "Gateway", string.Empty, History.GetValue <FinancialGateway>(FinancialGateway, FinancialGatewayId, rockContext));
                History.EvaluateChange(HistoryChangeList, "Gateway Schedule Id", string.Empty, GatewayScheduleId);
                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, "Frequency", (int?)null, TransactionFrequencyValue, TransactionFrequencyValueId);
                History.EvaluateChange(HistoryChangeList, "Start Date", (DateTime?)null, StartDate);
                History.EvaluateChange(HistoryChangeList, "End Date", (DateTime?)null, EndDate);
                History.EvaluateChange(HistoryChangeList, "Number of Payments", (int?)null, NumberOfPayments);
                History.EvaluateChange(HistoryChangeList, "Is Active", (bool?)null, IsActive);
                History.EvaluateChange(HistoryChangeList, "Card Reminder Date", (DateTime?)null, CardReminderDate);
                History.EvaluateChange(HistoryChangeList, "Last Reminded Date", (DateTime?)null, LastRemindedDate);

                break;
            }

            case 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?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, "Gateway Schedule Id", entry.OriginalValues["GatewayScheduleId"].ToStringSafe(), GatewayScheduleId);
                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, "Frequency", entry.OriginalValues["TransactionFrequencyValueId"].ToStringSafe().AsIntegerOrNull(), TransactionFrequencyValue, TransactionFrequencyValueId);
                History.EvaluateChange(HistoryChangeList, "Start Date", entry.OriginalValues["StartDate"].ToStringSafe().AsDateTime(), StartDate);
                History.EvaluateChange(HistoryChangeList, "End Date", entry.OriginalValues["EndDate"].ToStringSafe().AsDateTime(), EndDate);
                History.EvaluateChange(HistoryChangeList, "Number of Payments", entry.OriginalValues["EndDate"].ToStringSafe().AsIntegerOrNull(), NumberOfPayments);
                History.EvaluateChange(HistoryChangeList, "Is Active", entry.OriginalValues["IsActive"].ToStringSafe().AsBooleanOrNull(), IsActive);
                History.EvaluateChange(HistoryChangeList, "Card Reminder Date", entry.OriginalValues["CardReminderDate"].ToStringSafe().AsDateTime(), CardReminderDate);
                History.EvaluateChange(HistoryChangeList, "Last Reminded Date", entry.OriginalValues["LastRemindedDate"].ToStringSafe().AsDateTime(), LastRemindedDate);

                break;
            }

            case EntityState.Deleted:
            {
                HistoryChangeList.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, "Transaction");

                break;
            }
            }

            base.PreSaveChanges(dbContext, entry);
        }
Пример #28
0
        /// <summary>
        /// This method is called in the
        /// <see cref="M:Rock.Data.Model`1.PreSaveChanges(Rock.Data.DbContext,System.Data.Entity.Infrastructure.DbEntityEntry,System.Data.Entity.EntityState)" />
        /// method. Use it to populate <see cref="P:Rock.Data.Model`1.HistoryItems" /> if needed.
        /// These history items are queued to be written into the database post save (so that they
        /// are only written if the save actually occurs).
        /// </summary>
        /// <param name="dbContext">The database context.</param>
        /// <param name="entry">The entry.</param>
        /// <param name="state">The state.</param>
        protected override void BuildHistoryItems(Data.DbContext dbContext, DbEntityEntry entry, EntityState state)
        {
            // Sometimes, especially if the model is being deleted, some properties might not be
            // populated, but we can query to try to get their original value. We need to use a new
            // rock context to get the actual value from the DB
            var rockContext   = new RockContext();
            var service       = new PersonSearchKeyService(rockContext);
            var originalModel = service.Queryable("PersonAlias")
                                .FirstOrDefault(fpsa => fpsa.Id == Id);

            // Use the original value for the person alias or the new value if that is not set
            var personId = (originalModel?.PersonAlias ?? PersonAlias)?.PersonId;

            if (!personId.HasValue)
            {
                // If this model is new, it won't have any virtual properties hydrated or an original
                // record in the database
                if (PersonAliasId.HasValue)
                {
                    var personAliasService = new PersonAliasService(rockContext);
                    var personAlias        = personAliasService.Get(PersonAliasId.Value);
                    personId = personAlias?.PersonId;
                }

                // We can't log history if we don't know who the saved account belongs to
                if (!personId.HasValue)
                {
                    return;
                }
            }

            History.HistoryVerb verb;

            switch (state)
            {
            case EntityState.Added:
                verb = History.HistoryVerb.Add;
                break;

            case EntityState.Deleted:
                verb = History.HistoryVerb.Delete;
                break;

            case EntityState.Modified:
                verb = History.HistoryVerb.Modify;
                break;

            default:
                // As of now, there is no requirement to log other events
                return;
            }

            var caption = verb == History.HistoryVerb.Modify ?
                          "Person Search Key" :
                          GetCaptionForHistory(originalModel?.SearchValue ?? SearchValue, originalModel?.SearchTypeValueId ?? SearchTypeValueId);

            var historyChangeList = new History.HistoryChangeList();

            if (verb != History.HistoryVerb.Modify)
            {
                historyChangeList.AddChange(verb, History.HistoryChangeType.Record, "Person Search Key");
            }
            else
            {
                History.EvaluateChange(historyChangeList, $"SearchValue", entry.OriginalValues["SearchValue"].ToStringSafe(), SearchValue, false);

                var originalSearchType = DefinedValueCache.Get(entry.OriginalValues["SearchTypeValueId"].ToStringSafe().AsInteger());
                var currentSearchType  = DefinedValueCache.Get(SearchTypeValueId);
                History.EvaluateChange(historyChangeList, $"SearchType", originalSearchType?.Value, currentSearchType?.Value, false);
            }

            HistoryItems = HistoryService.GetChanges(
                typeof(Person),
                Rock.SystemGuid.Category.HISTORY_PERSON.AsGuid(),
                personId.Value,
                historyChangeList,
                caption,
                typeof(PersonSearchKey),
                Id,
                dbContext.GetCurrentPersonAlias()?.Id,
                dbContext.SourceOfChange);
        }
Пример #29
0
        /// <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);
        }
Пример #30
0
        /// <summary>
        /// Updates the last login, writes to the person's history log, and saves changes to the database
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        public static void UpdateLastLogin(string userName)
        {
            if (string.IsNullOrWhiteSpace(userName))
            {
                return;
            }

            int? personId     = null;
            bool impersonated = userName.StartsWith("rckipid=");

            using (var rockContext = new RockContext())
            {
                if (!impersonated)
                {
                    var userLogin = new UserLoginService(rockContext).Queryable().Where(a => a.UserName == userName).FirstOrDefault();
                    if (userLogin != null)
                    {
                        userLogin.LastLoginDateTime = RockDateTime.Now;
                        personId = userLogin.PersonId;
                        rockContext.SaveChanges();
                    }
                }
                else
                {
                    var impersonationToken = userName.Substring(8);
                    personId = new PersonService(rockContext).GetByImpersonationToken(impersonationToken, false, null)?.Id;
                }
            }

            if (personId == null)
            {
                return;
            }

            var relatedDataBuilder  = new System.Text.StringBuilder();
            int?relatedEntityTypeId = null;
            int?relatedEntityId     = null;

            if (impersonated)
            {
                var impersonatedByUser = HttpContext.Current?.Session?["ImpersonatedByUser"] as UserLogin;

                relatedEntityTypeId = EntityTypeCache.GetId <Rock.Model.Person>();
                relatedEntityId     = impersonatedByUser?.PersonId;

                if (impersonatedByUser != null)
                {
                    relatedDataBuilder.Append($" impersonated by { impersonatedByUser.Person.FullName }");
                }
            }

            if (HttpContext.Current != null && HttpContext.Current.Request != null)
            {
                string cleanUrl = PersonToken.ObfuscateRockMagicToken(HttpContext.Current.Request.UrlProxySafe().AbsoluteUri);

                // obfuscate the URL specified in the returnurl, just in case it contains any sensitive information (like a rckipid)
                Regex returnurlRegEx = new Regex(@"returnurl=([^&]*)");
                cleanUrl = returnurlRegEx.Replace(cleanUrl, "returnurl=XXXXXXXXXXXXXXXXXXXXXXXXXXXX");

                string clientIPAddress;
                try
                {
                    clientIPAddress = Rock.Web.UI.RockPage.GetClientIpAddress();
                }
                catch
                {
                    // if we get an exception getting the IP Address, just ignore it
                    clientIPAddress = "";
                }

                relatedDataBuilder.AppendFormat(
                    " to <span class='field-value'>{0}</span>, from <span class='field-value'>{1}</span>",
                    cleanUrl,
                    clientIPAddress);
            }

            var historyChangeList = new History.HistoryChangeList();
            var historyChange     = historyChangeList.AddChange(History.HistoryVerb.Login, History.HistoryChangeType.Record, userName);

            if (relatedDataBuilder.Length > 0)
            {
                historyChange.SetRelatedData(relatedDataBuilder.ToString(), null, null);
            }

            var historyList = HistoryService.GetChanges(typeof(Rock.Model.Person), Rock.SystemGuid.Category.HISTORY_PERSON_ACTIVITY.AsGuid(), personId.Value, historyChangeList, null, null, null, null, null);

            if (historyList.Any())
            {
                Task.Run(async() =>
                {
                    // Wait 1 second to allow all post save actions to complete
                    await Task.Delay(1000);
                    try
                    {
                        using (var rockContext = new RockContext())
                        {
                            rockContext.BulkInsert(historyList);
                        }
                    }
                    catch (SystemException ex)
                    {
                        ExceptionLogService.LogException(ex, null);
                    }
                });
            }
        }