/// <summary>
        /// Handles the SaveClick event of the dlgDiscount 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 dlgDiscount_SaveClick( object sender, EventArgs e )
        {
            RegistrationTemplateDiscount discount = null;
            var discountGuid = hfDiscountGuid.Value.AsGuidOrNull();
            if ( discountGuid.HasValue )
            {
                discount = DiscountState.Where( f => f.Guid.Equals( discountGuid.Value ) ).FirstOrDefault();
            }

            if ( discount == null )
            {
                discount = new RegistrationTemplateDiscount();
                discount.Guid = Guid.NewGuid();
                discount.Order = DiscountState.Any() ? DiscountState.Max( d => d.Order ) + 1 : 0;
                DiscountState.Add( discount );
            }

            discount.Code = tbDiscountCode.Text;
            if ( rblDiscountType.SelectedValue == "Amount" )
            {
                discount.DiscountPercentage = 0.0m;
                discount.DiscountAmount = cbDiscountAmount.Text.AsDecimal();
            }
            else
            {
                discount.DiscountPercentage = nbDiscountPercentage.Text.AsDecimal() * 0.01m;
                discount.DiscountAmount = 0.0m;
            }

            HideDialog();

            hfDiscountGuid.Value = string.Empty;

            BuildControls();
        }
        /// <summary>
        /// Shows the discount edit.
        /// </summary>
        /// <param name="discountGuid">The discount unique identifier.</param>
        private void ShowDiscountEdit( Guid discountGuid )
        {
            var discount = DiscountState.FirstOrDefault( d => d.Guid.Equals( discountGuid ));
            if ( discount == null )
            {
                discount = new RegistrationTemplateDiscount();
            }

            hfDiscountGuid.Value = discount.Guid.ToString();
            tbDiscountCode.Text = discount.Code;
            nbDiscountPercentage.Text = ( discount.DiscountPercentage * 100.0m ).ToString( "N0" );
            cbDiscountAmount.Text = discount.DiscountAmount.ToString();

            if ( discount.DiscountAmount > 0 )
            {
                rblDiscountType.SetValue( "Amount" );
                nbDiscountPercentage.Visible = false;
                cbDiscountAmount.Visible = true;
            }
            else
            {
                rblDiscountType.SetValue( "Percentage" );
                nbDiscountPercentage.Visible = true;
                cbDiscountAmount.Visible = false;
            }

            ShowDialog( "Discounts" );
        }
        /// <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 )
        {
            ParseControls( true );

            var rockContext = new RockContext();
            var service = new RegistrationTemplateService( rockContext );

            RegistrationTemplate RegistrationTemplate = null;

            int? RegistrationTemplateId = hfRegistrationTemplateId.Value.AsIntegerOrNull();
            if ( RegistrationTemplateId.HasValue )
            {
                RegistrationTemplate = service.Get( RegistrationTemplateId.Value );
            }

            bool newTemplate = false;
            if ( RegistrationTemplate == null )
            {
                newTemplate = true;
                RegistrationTemplate = new RegistrationTemplate();
            }

            RegistrationNotify notify = RegistrationNotify.None;
            foreach( ListItem li in cblNotify.Items )
            {
                if ( li.Selected )
                {
                    notify = notify | (RegistrationNotify)li.Value.AsInteger();
                }
            }

            RegistrationTemplate.IsActive = cbIsActive.Checked;
            RegistrationTemplate.Name = tbName.Text;
            RegistrationTemplate.CategoryId = cpCategory.SelectedValueAsInt();
            RegistrationTemplate.GroupTypeId = gtpGroupType.SelectedGroupTypeId;
            RegistrationTemplate.GroupMemberRoleId = rpGroupTypeRole.GroupRoleId;
            RegistrationTemplate.GroupMemberStatus = ddlGroupMemberStatus.SelectedValueAsEnum<GroupMemberStatus>();
            RegistrationTemplate.RequiredSignatureDocumentTemplateId = ddlSignatureDocumentTemplate.SelectedValueAsInt();
            RegistrationTemplate.SignatureDocumentAction = cbDisplayInLine.Checked ? SignatureDocumentAction.Embed : SignatureDocumentAction.Email;

            RegistrationTemplate.RegistrationWorkflowTypeId = wtpRegistrationWorkflow.SelectedValueAsInt();
            RegistrationTemplate.Notify = notify;
            RegistrationTemplate.AddPersonNote = cbAddPersonNote.Checked;
            RegistrationTemplate.LoginRequired = cbLoginRequired.Checked;
            RegistrationTemplate.AllowExternalRegistrationUpdates = cbAllowExternalUpdates.Checked;
            RegistrationTemplate.AllowGroupPlacement = cbAllowGroupPlacement.Checked;
            RegistrationTemplate.AllowMultipleRegistrants = cbMultipleRegistrants.Checked;
            RegistrationTemplate.MaxRegistrants = nbMaxRegistrants.Text.AsInteger();
            RegistrationTemplate.RegistrantsSameFamily = rblRegistrantsInSameFamily.SelectedValueAsEnum<RegistrantsSameFamily>();
            RegistrationTemplate.ShowCurrentFamilyMembers = cbShowCurrentFamilyMembers.Checked;
            RegistrationTemplate.SetCostOnInstance = !tglSetCostOnTemplate.Checked;
            RegistrationTemplate.Cost = cbCost.Text.AsDecimal();
            RegistrationTemplate.MinimumInitialPayment = cbMinimumInitialPayment.Text.AsDecimalOrNull();
            RegistrationTemplate.FinancialGatewayId = fgpFinancialGateway.SelectedValueAsInt();
            RegistrationTemplate.BatchNamePrefix = txtBatchNamePrefix.Text;

            RegistrationTemplate.ConfirmationFromName = tbConfirmationFromName.Text;
            RegistrationTemplate.ConfirmationFromEmail = tbConfirmationFromEmail.Text;
            RegistrationTemplate.ConfirmationSubject = tbConfirmationSubject.Text;
            RegistrationTemplate.ConfirmationEmailTemplate = ceConfirmationEmailTemplate.Text;

            RegistrationTemplate.ReminderFromName = tbReminderFromName.Text;
            RegistrationTemplate.ReminderFromEmail = tbReminderFromEmail.Text;
            RegistrationTemplate.ReminderSubject = tbReminderSubject.Text;
            RegistrationTemplate.ReminderEmailTemplate = ceReminderEmailTemplate.Text;

            RegistrationTemplate.PaymentReminderFromName = tbPaymentReminderFromName.Text;
            RegistrationTemplate.PaymentReminderFromEmail = tbPaymentReminderFromEmail.Text;
            RegistrationTemplate.PaymentReminderSubject = tbPaymentReminderSubject.Text;
            RegistrationTemplate.PaymentReminderEmailTemplate = cePaymentReminderEmailTemplate.Text;
            RegistrationTemplate.PaymentReminderTimeSpan = nbPaymentReminderTimeSpan.Text.AsInteger();

            RegistrationTemplate.RegistrationTerm = string.IsNullOrWhiteSpace( tbRegistrationTerm.Text ) ? "Registration" : tbRegistrationTerm.Text;
            RegistrationTemplate.RegistrantTerm = string.IsNullOrWhiteSpace( tbRegistrantTerm.Text ) ? "Registrant" : tbRegistrantTerm.Text;
            RegistrationTemplate.FeeTerm = string.IsNullOrWhiteSpace( tbFeeTerm.Text ) ? "Additional Options" : tbFeeTerm.Text;
            RegistrationTemplate.DiscountCodeTerm = string.IsNullOrWhiteSpace( tbDiscountCodeTerm.Text ) ? "Discount Code" : tbDiscountCodeTerm.Text;
            RegistrationTemplate.SuccessTitle = tbSuccessTitle.Text;
            RegistrationTemplate.SuccessText = ceSuccessText.Text;

            if ( !Page.IsValid || !RegistrationTemplate.IsValid )
            {
                return;
            }

            foreach ( var form in FormState )
            {
                if ( !form.IsValid )
                {
                    return;
                }

                if ( FormFieldsState.ContainsKey( form.Guid ) )
                {
                    foreach( var formField in FormFieldsState[ form.Guid ])
                    {
                        if ( !formField.IsValid )
                        {
                            return;
                        }
                    }
                }
            }

            // Get the valid group member attributes
            var group = new Group();
            group.GroupTypeId = gtpGroupType.SelectedGroupTypeId ?? 0;
            var groupMember = new GroupMember();
            groupMember.Group = group;
            groupMember.LoadAttributes();
            var validGroupMemberAttributeIds = groupMember.Attributes.Select( a => a.Value.Id ).ToList();

            // Remove any group member attributes that are not valid based on selected group type
            foreach( var fieldList in FormFieldsState.Select( s => s.Value ) )
            {
                foreach( var formField in fieldList
                    .Where( a =>
                        a.FieldSource == RegistrationFieldSource.GroupMemberAttribute &&
                        a.AttributeId.HasValue &&
                        !validGroupMemberAttributeIds.Contains( a.AttributeId.Value ) )
                    .ToList() )
                {
                    fieldList.Remove( formField );
                }
            }

            // Perform Validation
            var validationErrors = new List<string>();
            if ( ( ( RegistrationTemplate.SetCostOnInstance ?? false ) || RegistrationTemplate.Cost > 0 || FeeState.Any() ) && !RegistrationTemplate.FinancialGatewayId.HasValue )
            {
                validationErrors.Add( "A Financial Gateway is required when the registration has a cost or additional fees or is configured to allow instances to set a cost." );
            }

            if ( validationErrors.Any() )
            {
                nbValidationError.Visible = true;
                nbValidationError.Text = "<ul class='list-unstyled'><li>" + validationErrors.AsDelimited( "</li><li>" ) + "</li></ul>";
            }
            else
            {
                // Save the entity field changes to registration template
                if ( RegistrationTemplate.Id.Equals( 0 ) )
                {
                    service.Add( RegistrationTemplate );
                }
                rockContext.SaveChanges();

                var attributeService = new AttributeService( rockContext );
                var registrationTemplateFormService = new RegistrationTemplateFormService( rockContext );
                var registrationTemplateFormFieldService = new RegistrationTemplateFormFieldService( rockContext );
                var registrationTemplateDiscountService = new RegistrationTemplateDiscountService( rockContext );
                var registrationTemplateFeeService = new RegistrationTemplateFeeService( rockContext );
                var registrationRegistrantFeeService = new RegistrationRegistrantFeeService( rockContext );

                var groupService = new GroupService( rockContext );

                // delete forms that aren't assigned in the UI anymore
                var formUiGuids = FormState.Select( f => f.Guid ).ToList();
                foreach ( var form in registrationTemplateFormService
                    .Queryable()
                    .Where( f =>
                        f.RegistrationTemplateId == RegistrationTemplate.Id &&
                        !formUiGuids.Contains( f.Guid ) ) )
                {
                    foreach( var formField in form.Fields.ToList() )
                    {
                        form.Fields.Remove( formField );
                        registrationTemplateFormFieldService.Delete( formField );
                    }
                    registrationTemplateFormService.Delete( form );
                }

                // delete fields that aren't assigned in the UI anymore
                var fieldUiGuids = FormFieldsState.SelectMany( a => a.Value).Select( f => f.Guid ).ToList();
                foreach ( var formField in registrationTemplateFormFieldService
                    .Queryable()
                    .Where( a =>
                        formUiGuids.Contains( a.RegistrationTemplateForm.Guid ) &&
                        !fieldUiGuids.Contains( a.Guid ) ) )
                {
                    registrationTemplateFormFieldService.Delete( formField );
                }

                // delete discounts that aren't assigned in the UI anymore
                var discountUiGuids = DiscountState.Select( u => u.Guid ).ToList();
                foreach ( var discount in registrationTemplateDiscountService
                    .Queryable()
                    .Where( d =>
                        d.RegistrationTemplateId == RegistrationTemplate.Id &&
                        !discountUiGuids.Contains( d.Guid ) ) )
                {
                    registrationTemplateDiscountService.Delete( discount );
                }

                // delete fees that aren't assigned in the UI anymore
                var feeUiGuids = FeeState.Select( u => u.Guid ).ToList();
                var deletedfees = registrationTemplateFeeService
                    .Queryable()
                    .Where( d =>
                        d.RegistrationTemplateId == RegistrationTemplate.Id &&
                        !feeUiGuids.Contains( d.Guid ) )
                    .ToList();

                var deletedFeeIds = deletedfees.Select( f => f.Id ).ToList();
                foreach ( var registrantFee in registrationRegistrantFeeService
                    .Queryable()
                    .Where( f => deletedFeeIds.Contains( f.RegistrationTemplateFeeId ) )
                    .ToList() )
                {
                    registrationRegistrantFeeService.Delete( registrantFee );
                }

                foreach ( var fee in deletedfees )
                {
                    registrationTemplateFeeService.Delete( fee );
                }

                int? entityTypeId = EntityTypeCache.Read( typeof( Rock.Model.RegistrationRegistrant ) ).Id;
                var qualifierColumn = "RegistrationTemplateId";
                var qualifierValue = RegistrationTemplate.Id.ToString();

                // Get the registration attributes still in the UI
                var attributesUI = FormFieldsState
                    .SelectMany( s =>
                        s.Value.Where( a =>
                            a.FieldSource == RegistrationFieldSource.RegistrationAttribute &&
                            a.Attribute != null ) )
                    .Select( f => f.Attribute )
                    .ToList();
                var selectedAttributeGuids = attributesUI.Select( a => a.Guid );

                // Delete the registration attributes that were removed from the UI
                var attributesDB = attributeService.Get( entityTypeId, qualifierColumn, qualifierValue );
                foreach ( var attr in attributesDB.Where( a => !selectedAttributeGuids.Contains( a.Guid ) ).ToList() )
                {
                    attributeService.Delete( attr );
                    Rock.Web.Cache.AttributeCache.Flush( attr.Id );
                }

                rockContext.SaveChanges();

                // Save all of the registration attributes still in the UI
                foreach ( var attr in attributesUI )
                {
                    Helper.SaveAttributeEdits( attr, entityTypeId, qualifierColumn, qualifierValue, rockContext );
                }

                // add/updated forms/fields
                foreach ( var formUI in FormState )
                {
                    var form = RegistrationTemplate.Forms.FirstOrDefault( f => f.Guid.Equals( formUI.Guid ) );
                    if ( form == null )
                    {
                        form = new RegistrationTemplateForm();
                        form.Guid = formUI.Guid;
                        RegistrationTemplate.Forms.Add( form );
                    }
                    form.Name = formUI.Name;
                    form.Order = formUI.Order;

                    if ( FormFieldsState.ContainsKey( form.Guid ) )
                    {
                        foreach ( var formFieldUI in FormFieldsState[form.Guid] )
                        {
                            var formField = form.Fields.FirstOrDefault( a => a.Guid.Equals( formFieldUI.Guid ) );
                            if ( formField == null )
                            {
                                formField = new RegistrationTemplateFormField();
                                formField.Guid = formFieldUI.Guid;
                                form.Fields.Add( formField );
                            }

                            formField.AttributeId = formFieldUI.AttributeId;
                            if ( !formField.AttributeId.HasValue &&
                                formFieldUI.FieldSource == RegistrationFieldSource.RegistrationAttribute &&
                                formFieldUI.Attribute != null )
                            {
                                var attr = AttributeCache.Read( formFieldUI.Attribute.Guid, rockContext );
                                if ( attr != null )
                                {
                                    formField.AttributeId = attr.Id;
                                }
                            }

                            formField.FieldSource = formFieldUI.FieldSource;
                            formField.PersonFieldType = formFieldUI.PersonFieldType;
                            formField.IsInternal = formFieldUI.IsInternal;
                            formField.IsSharedValue = formFieldUI.IsSharedValue;
                            formField.ShowCurrentValue = formFieldUI.ShowCurrentValue;
                            formField.PreText = formFieldUI.PreText;
                            formField.PostText = formFieldUI.PostText;
                            formField.IsGridField = formFieldUI.IsGridField;
                            formField.IsRequired = formFieldUI.IsRequired;
                            formField.Order = formFieldUI.Order;
                        }
                    }
                }

                // add/updated discounts
                foreach ( var discountUI in DiscountState )
                {
                    var discount = RegistrationTemplate.Discounts.FirstOrDefault( a => a.Guid.Equals( discountUI.Guid ) );
                    if ( discount == null )
                    {
                        discount = new RegistrationTemplateDiscount();
                        discount.Guid = discountUI.Guid;
                        RegistrationTemplate.Discounts.Add( discount );
                    }
                    discount.Code = discountUI.Code;
                    discount.DiscountPercentage = discountUI.DiscountPercentage;
                    discount.DiscountAmount = discountUI.DiscountAmount;
                    discount.Order = discountUI.Order;
                }

                // add/updated fees
                foreach ( var feeUI in FeeState )
                {
                    var fee = RegistrationTemplate.Fees.FirstOrDefault( a => a.Guid.Equals( feeUI.Guid ) );
                    if ( fee == null )
                    {
                        fee = new RegistrationTemplateFee();
                        fee.Guid = feeUI.Guid;
                        RegistrationTemplate.Fees.Add( fee );
                    }
                    fee.Name = feeUI.Name;
                    fee.FeeType = feeUI.FeeType;
                    fee.CostValue = feeUI.CostValue;
                    fee.DiscountApplies = feeUI.DiscountApplies;
                    fee.AllowMultiple = feeUI.AllowMultiple;
                    fee.Order = feeUI.Order;
                }

                rockContext.SaveChanges();

                AttributeCache.FlushEntityAttributes();

                // If this is a new template, give the current user and the Registration Administrators role administrative
                // rights to this template, and staff, and staff like roles edit rights
                if ( newTemplate )
                {
                    RegistrationTemplate.AllowPerson( Authorization.ADMINISTRATE, CurrentPerson, rockContext );

                    var registrationAdmins = groupService.Get( Rock.SystemGuid.Group.GROUP_EVENT_REGISTRATION_ADMINISTRATORS.AsGuid() );
                    RegistrationTemplate.AllowSecurityRole( Authorization.ADMINISTRATE, registrationAdmins, rockContext );

                    var staffLikeUsers = groupService.Get( Rock.SystemGuid.Group.GROUP_STAFF_LIKE_MEMBERS.AsGuid() );
                    RegistrationTemplate.AllowSecurityRole( Authorization.EDIT, staffLikeUsers, rockContext );

                    var staffUsers = groupService.Get( Rock.SystemGuid.Group.GROUP_STAFF_MEMBERS.AsGuid() );
                    RegistrationTemplate.AllowSecurityRole( Authorization.EDIT, staffUsers, rockContext );
                }

                var qryParams = new Dictionary<string, string>();
                qryParams["RegistrationTemplateId"] = RegistrationTemplate.Id.ToString();
                NavigateToPage( RockPage.Guid, qryParams );
            }
        }
Example #4
0
        /// <summary>
        /// Adds any registration templates given in the XML file.
        /// </summary>
        /// <param name="elemFamilies"></param>
        /// <param name="rockContext"></param>
        private void AddRegistrationTemplates( XElement elemRegistrationTemplates, RockContext rockContext )
        {
            if ( elemRegistrationTemplates == null )
            {
                return;
            }

            // Get attribute values from RegistrationTemplateDetail block
            // Get instance of the attribute.
            string defaultConfirmationEmail = string.Empty;
            string defaultReminderEmail = string.Empty;
            string defaultSuccessText = string.Empty;
            string defaultPaymentReminderEmail = string.Empty;

            //CodeEditorFieldAttribute MyAttribute = (CodeEditorFieldAttribute)System.Attribute.GetCustomAttribute( typeof( RockWeb.Blocks.Event.RegistrationTemplateDetail ), typeof( CodeEditorFieldAttribute ) );
            var blockAttributes = System.Attribute.GetCustomAttributes( typeof( RockWeb.Blocks.Event.RegistrationTemplateDetail ), typeof( CodeEditorFieldAttribute ) );
            foreach ( CodeEditorFieldAttribute blockAttribute in blockAttributes )
            {
                switch ( blockAttribute.Name )
                {
                    case "Default Confirmation Email":
                        defaultConfirmationEmail = blockAttribute.DefaultValue;
                        break;

                    case "Default Reminder Email":
                        defaultReminderEmail = blockAttribute.DefaultValue;
                        break;

                    case "Default Success Text":
                        defaultSuccessText = blockAttribute.DefaultValue;
                        break;

                    case "Default Payment Reminder Email":
                        defaultPaymentReminderEmail = blockAttribute.DefaultValue;
                        break;

                    default:
                        break;
                }
            }

            RegistrationTemplateService registrationTemplateService = new RegistrationTemplateService( rockContext );

            // Add a template for each...
            foreach ( var element in elemRegistrationTemplates.Elements( "registrationTemplate" ) )
            {
                // skip any illegally formatted items
                if ( element.Attribute( "guid" ) == null )
                {
                    continue;
                }

                int categoryId = CategoryCache.Read( element.Attribute( "categoryGuid" ).Value.Trim().AsGuid() ).Id;

                // Find the group type and
                var groupType = GroupTypeCache.Read( element.Attribute( "groupTypeGuid" ).Value.Trim().AsGuid() );

                RegistrantsSameFamily registrantsSameFamily;
                if ( element.Attribute( "registrantsInSameFamily" ) != null )
                {
                    Enum.TryParse( element.Attribute( "registrantsInSameFamily" ).Value.Trim(), out registrantsSameFamily );
                }
                else
                {
                    registrantsSameFamily = RegistrantsSameFamily.Ask;
                }

                bool setCostOnInstance = true;
                if ( element.Attribute( "setCostOn" ).Value.Trim() == "template" )
                {
                    setCostOnInstance = false;
                }

                RegistrationNotify notify = RegistrationNotify.None;
                RegistrationNotify matchNotify;
                foreach ( string item in element.Attribute( "notify" ).Value.SplitDelimitedValues( whitespace: false ) )
                {
                    if ( Enum.TryParse( item.Replace( " ", string.Empty ), out matchNotify ) )
                    {
                        notify = notify | matchNotify;
                    }
                }

                // Now find the matching financial gateway
                FinancialGatewayService financialGatewayService = new FinancialGatewayService( rockContext );
                string gatewayName = element.Attribute( "financialGateway" ) != null ? element.Attribute( "financialGateway" ).Value : "Test Gateway";
                var financialGateway = financialGatewayService.Queryable()
                    .Where( g => g.Name == gatewayName )
                    .FirstOrDefault();

                RegistrationTemplate registrationTemplate = new RegistrationTemplate()
                {
                    Guid = element.Attribute( "guid" ).Value.Trim().AsGuid(),
                    Name = element.Attribute( "name" ).Value.Trim(),
                    IsActive = true,
                    CategoryId = categoryId,
                    GroupTypeId = groupType.Id,
                    GroupMemberRoleId = groupType.DefaultGroupRoleId,
                    GroupMemberStatus = GroupMemberStatus.Active,
                    Notify = notify,
                    AddPersonNote = element.Attribute( "addPersonNote" ) != null ? element.Attribute( "addPersonNote" ).Value.AsBoolean() : false,
                    LoginRequired = element.Attribute( "loginRequired" ) != null ? element.Attribute( "loginRequired" ).Value.AsBoolean() : false,
                    AllowExternalRegistrationUpdates = element.Attribute( "allowExternalUpdatesToSavedRegistrations" ) != null ? element.Attribute( "allowExternalUpdatesToSavedRegistrations" ).Value.AsBoolean() : false,
                    AllowGroupPlacement = element.Attribute( "allowGroupPlacement" ) != null ? element.Attribute( "allowGroupPlacement" ).Value.AsBoolean() : false,
                    AllowMultipleRegistrants = element.Attribute( "allowMultipleRegistrants" ) != null ? element.Attribute( "allowMultipleRegistrants" ).Value.AsBoolean() : false,
                    MaxRegistrants = element.Attribute( "maxRegistrants" ).Value.AsInteger(),
                    RegistrantsSameFamily = registrantsSameFamily,
                    SetCostOnInstance = setCostOnInstance,
                    FinancialGatewayId = financialGateway.Id,
                    BatchNamePrefix = element.Attribute( "batchNamePrefix" ) != null ? element.Attribute( "batchNamePrefix" ).Value.Trim() : string.Empty,
                    Cost = element.Attribute( "cost" ).Value.AsDecimal(),
                    MinimumInitialPayment = element.Attribute( "minInitialPayment" ).Value.AsDecimal(),
                    RegistrationTerm = element.Attribute( "registrationTerm" ) != null ? element.Attribute( "registrationTerm" ).Value.Trim() : "Registration",
                    RegistrantTerm = element.Attribute( "registrantTerm" ) != null ? element.Attribute( "registrantTerm" ).Value.Trim() : "Registrant",
                    FeeTerm = element.Attribute( "feeTerm" ) != null ? element.Attribute( "feeTerm" ).Value.Trim() : "Additional Options",
                    DiscountCodeTerm = element.Attribute( "discountCodeTerm" ) != null ? element.Attribute( "discountCodeTerm" ).Value.Trim() : "Discount Code",
                    ConfirmationFromName = "{{ RegistrationInstance.ContactPersonAlias.Person.FullName }}",
                    ConfirmationFromEmail = "{{ RegistrationInstance.ContactEmail }}",
                    ConfirmationSubject = "{{ RegistrationInstance.Name }} Confirmation",
                    ConfirmationEmailTemplate = defaultConfirmationEmail,
                    ReminderFromName = "{{ RegistrationInstance.ContactPersonAlias.Person.FullName }}",
                    ReminderFromEmail = "{{ RegistrationInstance.ContactEmail }}",
                    ReminderSubject = "{{ RegistrationInstance.Name }} Reminder",
                    ReminderEmailTemplate = defaultReminderEmail,
                    SuccessTitle = "Congratulations {{ Registration.FirstName }}",
                    SuccessText = defaultSuccessText,
                    PaymentReminderEmailTemplate = defaultPaymentReminderEmail,
                    PaymentReminderFromEmail = "{{ RegistrationInstance.ContactEmail }}",
                    PaymentReminderFromName = "{{ RegistrationInstance.ContactPersonAlias.Person.FullName }}",
                    PaymentReminderSubject = "{{ RegistrationInstance.Name }} Payment Reminder",
                    PaymentReminderTimeSpan = element.Attribute( "paymentReminderTimeSpan" ) != null ? element.Attribute( "paymentReminderTimeSpan" ).Value.AsInteger() : 0,
                    CreatedDateTime = RockDateTime.Now,
                    ModifiedDateTime = RockDateTime.Now,
                };

                registrationTemplateService.Add( registrationTemplate );

                rockContext.SaveChanges();
                var x = registrationTemplate.Id;

                string name = element.Attribute( "name" ).Value.Trim();
                bool allowExternalUpdatesToSavedRegistrations = element.Attribute( "allowExternalUpdatesToSavedRegistrations" ).Value.AsBoolean();
                bool addPersonNote = element.Attribute( "addPersonNote" ).Value.AsBoolean();
                bool loginRequired = element.Attribute( "loginRequired" ).Value.AsBoolean();
                Guid guid = element.Attribute( "guid" ).Value.Trim().AsGuid();

                // Find any Form elements and add them to the template
                int formOrder = 0;
                var registrationAttributeQualifierColumn = "RegistrationTemplateId";
                int? registrationRegistrantEntityTypeId = EntityTypeCache.Read( typeof( Rock.Model.RegistrationRegistrant ) ).Id;
                if ( element.Elements( "forms" ).Count() > 0 )
                {
                    foreach ( var formElement in element.Elements( "forms" ).Elements( "form" ) )
                    {
                        formOrder++;
                        var form = new RegistrationTemplateForm();
                        form.Guid = formElement.Attribute( "guid" ).Value.Trim().AsGuid();
                        registrationTemplate.Forms.Add( form );
                        form.Name = formElement.Attribute( "name" ).Value.Trim();
                        form.Order = formOrder;

                        int ffOrder = 0;
                        if ( formElement.Elements( "formFields" ).Count() > 0 )
                        {
                            foreach ( var formFieldElement in formElement.Elements( "formFields" ).Elements( "field" ) )
                            {
                                ffOrder++;
                                var formField = new RegistrationTemplateFormField();
                                formField.Guid = Guid.NewGuid();
                                formField.CreatedDateTime = RockDateTime.Now;

                                form.Fields.Add( formField );

                                switch ( formFieldElement.Attribute( "source" ).Value.Trim().ToLowerInvariant() )
                                {
                                    case "person field":
                                        formField.FieldSource = RegistrationFieldSource.PersonField;
                                        break;
                                    case "person attribute":
                                        formField.FieldSource = RegistrationFieldSource.PersonAttribute;
                                        break;
                                    case "group member attribute":
                                        formField.FieldSource = RegistrationFieldSource.GroupMemberAttribute;
                                        break;
                                    case "registration attribute":
                                        formField.FieldSource = RegistrationFieldSource.RegistrationAttribute;

                                        //var qualifierValue = RegistrationTemplate.Id.ToString();
                                        var attrState = new Rock.Model.Attribute();

                                        attrState.Guid = formFieldElement.Attribute( "guid" ).Value.AsGuid();
                                        attrState.Name = formFieldElement.Attribute( "name" ).Value.Trim();
                                        attrState.Key = attrState.Name.RemoveSpecialCharacters().Replace( " ", string.Empty );
                                        var type = formFieldElement.Attribute( "type" ).Value.Trim();
                                        var fieldType = FieldTypeCache.All().Where( f => f.Name == type ).FirstOrDefault();
                                        attrState.FieldTypeId = fieldType.Id;
                                        var attribute = Helper.SaveAttributeEdits( attrState, registrationRegistrantEntityTypeId, registrationAttributeQualifierColumn, registrationTemplate.Id.ToString(), rockContext );
                                        //rockContext.ChangeTracker.DetectChanges();
                                        rockContext.SaveChanges( disablePrePostProcessing: true );
                                        formField.Attribute = attribute;

                                        break;
                                    default:
                                        throw new NotSupportedException( string.Format( "unknown form field source: {0}", formFieldElement.Attribute( "source" ).Value ) );
                                }

                                formField.AttributeId = null;
                                if ( !formField.AttributeId.HasValue &&
                                    formField.FieldSource == RegistrationFieldSource.RegistrationAttribute &&
                                    formField.Attribute != null )
                                {
                                    var attr = AttributeCache.Read( formField.Attribute.Guid, rockContext );
                                    if ( attr != null )
                                    {
                                        formField.AttributeId = attr.Id;
                                    }
                                }

                                RegistrationPersonFieldType registrationPersonFieldType;
                                if ( formField.FieldSource == RegistrationFieldSource.PersonField && formFieldElement.Attribute( "name" ) != null &&
                                    Enum.TryParse( formFieldElement.Attribute( "name" ).Value.Replace( " ", string.Empty ).Trim(), out registrationPersonFieldType ) )
                                {
                                    formField.PersonFieldType = registrationPersonFieldType;
                                }

                                formField.IsInternal = formFieldElement.Attribute( "isInternal" ) != null ? formFieldElement.Attribute( "isInternal" ).Value.AsBoolean() : false;
                                formField.IsSharedValue = formFieldElement.Attribute( "isCommon" ) != null ? formFieldElement.Attribute( "isCommon" ).Value.AsBoolean() : false;
                                formField.ShowCurrentValue = formFieldElement.Attribute( "showCurrentValue" ) != null ? formFieldElement.Attribute( "showCurrentValue" ).Value.AsBoolean() : false;
                                formField.PreText = formFieldElement.Attribute( "preText" ) != null ? formFieldElement.Attribute( "preText" ).Value : string.Empty;
                                formField.PostText = formFieldElement.Attribute( "postText" ) != null ? formFieldElement.Attribute( "postText" ).Value : string.Empty;
                                formField.IsGridField = formFieldElement.Attribute( "showOnGrid" ) != null ? formFieldElement.Attribute( "showOnGrid" ).Value.AsBoolean() : false;
                                formField.IsRequired = formFieldElement.Attribute( "isRequired" ) != null ? formFieldElement.Attribute( "isRequired" ).Value.AsBoolean() : false;
                                formField.Order = ffOrder;
                                formField.CreatedDateTime = RockDateTime.Now;
                            }
                        }
                    }
                }

                // Discounts
                int discountOrder = 0;
                if ( element.Elements( "discounts" ) != null )
                {
                    foreach ( var discountElement in element.Elements( "discounts" ).Elements( "discount" ) )
                    {
                        discountOrder++;
                        var discount = new RegistrationTemplateDiscount();
                        discount.Guid = Guid.NewGuid();
                        registrationTemplate.Discounts.Add( discount );

                        discount.Code = discountElement.Attribute( "code" ).Value;

                        switch ( discountElement.Attribute( "type" ).Value.Trim().ToLowerInvariant() )
                        {
                            case "percentage":
                                discount.DiscountPercentage = discountElement.Attribute( "value" ).Value.Trim().AsDecimal() * 0.01m;
                                discount.DiscountAmount = 0.0m;
                                break;
                            case "amount":
                                discount.DiscountPercentage = 0.0m;
                                discount.DiscountAmount = discountElement.Attribute( "value" ).Value.Trim().AsDecimal();
                                break;
                            default:
                                throw new NotSupportedException( string.Format( "unknown discount type: {0}", discountElement.Attribute( "type" ).Value ) );
                        }
                        discount.Order = discountOrder;
                    }
                }

                // Fees
                int feeOrder = 0;
                if ( element.Elements( "fees" ) != null )
                {
                    foreach ( var feeElement in element.Elements( "fees" ).Elements( "fee" ) )
                    {
                        feeOrder++;
                        var fee = new RegistrationTemplateFee();
                        fee.Guid = Guid.NewGuid();
                        registrationTemplate.Fees.Add( fee );

                        switch ( feeElement.Attribute( "type" ).Value.Trim().ToLowerInvariant() )
                        {
                            case "multiple":
                                fee.FeeType = RegistrationFeeType.Multiple;
                                fee.CostValue = FormatMultipleFeeCosts( feeElement.Elements( "option" ) );
                                break;
                            case "single":
                                fee.FeeType = RegistrationFeeType.Single;
                                fee.CostValue = feeElement.Attribute( "cost" ).Value.Trim();
                                break;
                            default:
                                throw new NotSupportedException( string.Format( "unknown fee type: {0}", feeElement.Attribute( "type" ).Value ) );
                        }

                        fee.Name = feeElement.Attribute( "name" ).Value.Trim();
                        fee.DiscountApplies = feeElement.Attribute( "discountApplies" ).Value.AsBoolean();
                        fee.AllowMultiple = feeElement.Attribute( "enableQuantity" ).Value.AsBoolean();
                        fee.Order = feeOrder;
                    }
                }
            }
        }
Example #5
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 )
        {
            ParseControls( true );

            var rockContext = new RockContext();
            var service = new RegistrationTemplateService( rockContext );

            RegistrationTemplate RegistrationTemplate = null;

            int? RegistrationTemplateId = hfRegistrationTemplateId.Value.AsIntegerOrNull();
            if ( RegistrationTemplateId.HasValue )
            {
                RegistrationTemplate = service.Get( RegistrationTemplateId.Value );
            }

            if ( RegistrationTemplate == null )
            {
                RegistrationTemplate = new RegistrationTemplate();
            }

            RegistrationNotify notify = RegistrationNotify.None;
            foreach( ListItem li in cblNotify.Items )
            {
                if ( li.Selected )
                {
                    notify = notify | (RegistrationNotify)li.Value.AsInteger();
                }
            }

            RegistrationTemplate.IsActive = cbIsActive.Checked;
            RegistrationTemplate.Name = tbName.Text;
            RegistrationTemplate.CategoryId = cpCategory.SelectedValueAsInt();
            RegistrationTemplate.GroupTypeId = gtpGroupType.SelectedGroupTypeId;
            RegistrationTemplate.GroupMemberRoleId = rpGroupTypeRole.GroupRoleId;
            RegistrationTemplate.GroupMemberStatus = ddlGroupMemberStatus.SelectedValueAsEnum<GroupMemberStatus>();
            RegistrationTemplate.Notify = notify;
            RegistrationTemplate.LoginRequired = cbLoginRequired.Checked;
            RegistrationTemplate.AllowMultipleRegistrants = cbMultipleRegistrants.Checked;
            RegistrationTemplate.MaxRegistrants = nbMaxRegistrants.Text.AsInteger();
            RegistrationTemplate.RegistrantsSameFamily = rblRegistrantsInSameFamily.SelectedValueAsEnum<RegistrantsSameFamily>();
            RegistrationTemplate.Cost = cbCost.Text.AsDecimal();
            RegistrationTemplate.MinimumInitialPayment = cbMinimumInitialPayment.Text.AsDecimalOrNull();
            RegistrationTemplate.FinancialGatewayId = fgpFinancialGateway.SelectedValueAsInt();

            RegistrationTemplate.ConfirmationFromName = tbConfirmationFromName.Text;
            RegistrationTemplate.ConfirmationFromEmail = tbConfirmationFromEmail.Text;
            RegistrationTemplate.ConfirmationSubject = tbConfirmationSubject.Text;
            RegistrationTemplate.ConfirmationEmailTemplate = ceConfirmationEmailTemplate.Text;

            RegistrationTemplate.ReminderFromName = tbReminderFromName.Text;
            RegistrationTemplate.ReminderFromEmail = tbReminderFromEmail.Text;
            RegistrationTemplate.ReminderSubject = tbReminderSubject.Text;
            RegistrationTemplate.ReminderEmailTemplate = ceReminderEmailTemplate.Text;

            RegistrationTemplate.RegistrationTerm = string.IsNullOrWhiteSpace( tbRegistrationTerm.Text ) ? "Registration" : tbRegistrationTerm.Text;
            RegistrationTemplate.RegistrantTerm = string.IsNullOrWhiteSpace( tbRegistrantTerm.Text ) ? "Registrant" : tbRegistrantTerm.Text;
            RegistrationTemplate.FeeTerm = string.IsNullOrWhiteSpace( tbFeeTerm.Text ) ? "Additional Options" : tbFeeTerm.Text;
            RegistrationTemplate.DiscountCodeTerm = string.IsNullOrWhiteSpace( tbDiscountCodeTerm.Text ) ? "Discount Code" : tbDiscountCodeTerm.Text;
            RegistrationTemplate.SuccessTitle = tbSuccessTitle.Text;
            RegistrationTemplate.SuccessText = ceSuccessText.Text;

            if ( !Page.IsValid || !RegistrationTemplate.IsValid )
            {
                return;
            }

            foreach ( var form in FormState )
            {
                if ( !form.IsValid )
                {
                    return;
                }

                if ( FormFieldsState.ContainsKey( form.Guid ) )
                {
                    foreach( var formField in FormFieldsState[ form.Guid ])
                    {
                        if ( !formField.IsValid )
                        {
                            return;
                        }
                    }
                }
            }

            // Get the valid group member attributes
            var group = new Group();
            group.GroupTypeId = gtpGroupType.SelectedGroupTypeId ?? 0;
            var groupMember = new GroupMember();
            groupMember.Group = group;
            groupMember.LoadAttributes();
            var validGroupMemberAttributeIds = groupMember.Attributes.Select( a => a.Value.Id ).ToList();

            // Remove any group member attributes that are not valid based on selected group type
            foreach( var fieldList in FormFieldsState.Select( s => s.Value ) )
            {
                foreach( var formField in fieldList
                    .Where( a =>
                        a.FieldSource == RegistrationFieldSource.GroupMemberAttribute &&
                        a.AttributeId.HasValue &&
                        !validGroupMemberAttributeIds.Contains( a.AttributeId.Value ) )
                    .ToList() )
                {
                    fieldList.Remove( formField );
                }
            }

            // Perform Validation
            var validationErrors = new List<string>();
            if ( ( RegistrationTemplate.Cost > 0 || FeeState.Any() ) && !RegistrationTemplate.FinancialGatewayId.HasValue )
            {
                validationErrors.Add( "A Financial Gateway is required when the registration has a cost or additional fees." );
            }

            if ( validationErrors.Any() )
            {
                nbValidationError.Visible = true;
                nbValidationError.Text = "<ul class='list-unstyled'><li>" + validationErrors.AsDelimited( "</li><li>" ) + "</li></ul>";
            }
            else
            {
                rockContext.WrapTransaction( () =>
                {
                    // Save the entity field changes to registration template
                    if ( RegistrationTemplate.Id.Equals( 0 ) )
                    {
                        service.Add( RegistrationTemplate );
                    }
                    rockContext.SaveChanges();

                    var attributeService = new AttributeService( rockContext );
                    var registrationTemplateFormService = new RegistrationTemplateFormService( rockContext );
                    var registrationTemplateFormFieldService = new RegistrationTemplateFormFieldService( rockContext );
                    var registrationTemplateDiscountService = new RegistrationTemplateDiscountService( rockContext );
                    var registrationTemplateFeeService = new RegistrationTemplateFeeService( rockContext );

                    // delete forms that aren't assigned in the UI anymore
                    var formUiGuids = FormState.Select( f => f.Guid ).ToList();
                    foreach ( var form in registrationTemplateFormService
                        .Queryable()
                        .Where( f =>
                            f.RegistrationTemplateId == RegistrationTemplate.Id &&
                            !formUiGuids.Contains( f.Guid ) ) )
                    {
                        registrationTemplateFormService.Delete( form );
                    }

                    // delete discounts that aren't assigned in the UI anymore
                    var discountUiGuids = DiscountState.Select( u => u.Guid ).ToList();
                    foreach ( var discount in registrationTemplateDiscountService
                        .Queryable()
                        .Where( d =>
                            d.RegistrationTemplateId == RegistrationTemplate.Id &&
                            !discountUiGuids.Contains( d.Guid ) ) )
                    {
                        registrationTemplateDiscountService.Delete( discount );
                    }

                    // delete fees that aren't assigned in the UI anymore
                    var feeUiGuids = FeeState.Select( u => u.Guid ).ToList();
                    foreach ( var fee in registrationTemplateFeeService
                        .Queryable()
                        .Where( d =>
                            d.RegistrationTemplateId == RegistrationTemplate.Id &&
                            !feeUiGuids.Contains( d.Guid ) ) )
                    {
                        registrationTemplateFeeService.Delete( fee );
                    }

                    var attributesUI = FormFieldsState
                        .SelectMany( s =>
                            s.Value.Where( a =>
                                a.FieldSource == RegistrationFieldSource.RegistrationAttribute &&
                                a.Attribute != null ) )
                        .Select( f => f.Attribute );

                    int? entityTypeId = EntityTypeCache.Read( typeof( Rock.Model.RegistrationRegistrant ) ).Id;
                    var qualifierColumn = "RegistrationTemplateId";
                    var qualifierValue = RegistrationTemplate.Id.ToString();

                    // Get the existing registration attributes for this entity type and qualifier value
                    var attributesDB = attributeService.Get( entityTypeId, qualifierColumn, qualifierValue );

                    // Delete any of the registration attributes that were removed in the UI
                    var selectedAttributeGuids = attributesUI.Select( a => a.Guid );
                    foreach ( var attr in attributesDB.Where( a => !selectedAttributeGuids.Contains( a.Guid ) ) )
                    {
                        attributeService.Delete( attr );
                        rockContext.SaveChanges();
                        Rock.Web.Cache.AttributeCache.Flush( attr.Id );
                    }

                    // Update the registration attributes that were assigned in the UI
                    foreach ( var attr in attributesUI )
                    {
                        Helper.SaveAttributeEdits( attr, entityTypeId, qualifierColumn, qualifierValue, rockContext );
                    }

                    // add/updated forms/fields
                    foreach ( var formUI in FormState )
                    {
                        var form = RegistrationTemplate.Forms.FirstOrDefault( f => f.Guid.Equals( formUI.Guid ) );
                        if ( form == null )
                        {
                            form = new RegistrationTemplateForm();
                            form.Guid = formUI.Guid;
                            RegistrationTemplate.Forms.Add( form );
                        }
                        form.Name = formUI.Name;
                        form.Order = formUI.Order;

                        if ( FormFieldsState.ContainsKey( form.Guid ) )
                        {
                            var fieldUiGuids = FormFieldsState[form.Guid].Select( a => a.Guid ).ToList();
                            foreach ( var formField in registrationTemplateFormFieldService
                                .Queryable()
                                .Where( a =>
                                    a.RegistrationTemplateForm.Guid.Equals( form.Guid ) &&
                                    !fieldUiGuids.Contains( a.Guid ) ) )
                            {
                                registrationTemplateFormFieldService.Delete( formField );
                            }

                            foreach ( var formFieldUI in FormFieldsState[form.Guid] )
                            {
                                var formField = form.Fields.FirstOrDefault( a => a.Guid.Equals( formFieldUI.Guid ) );
                                if ( formField == null )
                                {
                                    formField = new RegistrationTemplateFormField();
                                    formField.Guid = formFieldUI.Guid;
                                    form.Fields.Add( formField );
                                }

                                formField.AttributeId = formFieldUI.AttributeId;
                                if ( !formField.AttributeId.HasValue &&
                                    formFieldUI.FieldSource == RegistrationFieldSource.RegistrationAttribute &&
                                    formFieldUI.Attribute != null )
                                {
                                    var attr = AttributeCache.Read( formFieldUI.Attribute.Guid, rockContext );
                                    if ( attr != null )
                                    {
                                        formField.AttributeId = attr.Id;
                                    }
                                }

                                formField.FieldSource = formFieldUI.FieldSource;
                                formField.PersonFieldType = formFieldUI.PersonFieldType;
                                formField.IsSharedValue = formFieldUI.IsSharedValue;
                                formField.ShowCurrentValue = formFieldUI.ShowCurrentValue;
                                formField.PreText = formFieldUI.PreText;
                                formField.PostText = formFieldUI.PostText;
                                formField.IsGridField = formFieldUI.IsGridField;
                                formField.IsRequired = formFieldUI.IsRequired;
                                formField.Order = formFieldUI.Order;
                            }
                        }
                    }

                    // add/updated discounts
                    foreach ( var discountUI in DiscountState )
                    {
                        var discount = RegistrationTemplate.Discounts.FirstOrDefault( a => a.Guid.Equals( discountUI.Guid ) );
                        if ( discount == null )
                        {
                            discount = new RegistrationTemplateDiscount();
                            discount.Guid = discountUI.Guid;
                            RegistrationTemplate.Discounts.Add( discount );
                        }
                        discount.Code = discountUI.Code;
                        discount.DiscountPercentage = discountUI.DiscountPercentage;
                        discount.DiscountAmount = discountUI.DiscountAmount;
                        discount.Order = discountUI.Order;
                    }

                    // add/updated fees
                    foreach ( var feeUI in FeeState )
                    {
                        var fee = RegistrationTemplate.Fees.FirstOrDefault( a => a.Guid.Equals( feeUI.Guid ) );
                        if ( fee == null )
                        {
                            fee = new RegistrationTemplateFee();
                            fee.Guid = feeUI.Guid;
                            RegistrationTemplate.Fees.Add( fee );
                        }
                        fee.Name = feeUI.Name;
                        fee.FeeType = feeUI.FeeType;
                        fee.CostValue = feeUI.CostValue;
                        fee.DiscountApplies = feeUI.DiscountApplies;
                        fee.AllowMultiple = feeUI.AllowMultiple;
                        fee.Order = feeUI.Order;
                    }

                    rockContext.SaveChanges();

                } );

                var qryParams = new Dictionary<string, string>();
                qryParams["RegistrationTemplateId"] = RegistrationTemplate.Id.ToString();
                NavigateToPage( RockPage.Guid, qryParams );
            }
        }
Example #6
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>();

            var mergeFields = GetMergeFields(action);

            var registrationTemplateService         = new RegistrationTemplateService(rockContext);
            var registrationTemplateDiscountService = new RegistrationTemplateDiscountService(rockContext);

            var registrationTemplate = registrationTemplateService.Get(GetAttributeValue(action, "RegistrationTemplate").ResolveMergeFields(mergeFields).AsGuid());

            if (registrationTemplate == null)
            {
                errorMessages.Add("Could not find selected registration template");
                return(false);
            }

            var length = GetAttributeValue(action, "DiscountCodeLength", true).ResolveMergeFields(mergeFields).AsInteger();

            if (length < 3)
            {
                length = 3;
            }

            string code = GetRandomCode(length);

            while (registrationTemplateDiscountService
                   .Queryable().AsNoTracking()
                   .Any(d =>
                        d.RegistrationTemplateId == registrationTemplate.Id &&
                        d.Code == code))
            {
                code = GetRandomCode(length);
            }

            var discountCode = new RegistrationTemplateDiscount();

            discountCode.Code = code;

            //Set discount value
            var     discountType   = GetAttributeValue(action, "DiscountType");
            decimal discountAmount = GetAttributeValue(action, "DiscountAmount", true).ResolveMergeFields(mergeFields).AsDecimal();

            if (discountType == "Percent")
            {
                discountCode.DiscountPercentage = discountAmount / 100;
            }
            if (discountType == "Amount")
            {
                discountCode.DiscountAmount = discountAmount;
            }

            var maximumUsage = GetAttributeValue(action, "MaximumUsage", true).ResolveMergeFields(mergeFields).AsInteger();

            if (maximumUsage > 0)
            {
                discountCode.MaxUsage = maximumUsage;
            }

            var maximumRegistrants = GetAttributeValue(action, "MaximumRegistrants", true).ResolveMergeFields(mergeFields).AsInteger();

            if (maximumRegistrants > 0)
            {
                discountCode.MaxRegistrants = maximumRegistrants;
            }

            var minimumRegistrants = GetAttributeValue(action, "MinimumRegistrants", true).ResolveMergeFields(mergeFields).AsInteger();

            if (minimumRegistrants < 0)
            {
                discountCode.MinRegistrants = minimumRegistrants;
            }

            var effectiveDates = GetAttributeValue(action, "EffectiveDates", true);

            if (!string.IsNullOrWhiteSpace(effectiveDates))
            {
                var dates = effectiveDates.Split(',');
                if (dates.Length > 1 &&
                    !string.IsNullOrWhiteSpace(dates[0]) &&
                    !string.IsNullOrWhiteSpace(dates[1]))
                {
                    discountCode.StartDate = dates[0].AsDateTime();
                    discountCode.EndDate   = dates[1].AsDateTime();
                }
            }

            registrationTemplate.Discounts.Add(discountCode);
            rockContext.SaveChanges();
            SetWorkflowAttributeValue(action, "DiscountCodeAttribute", code);
            return(true);
        }
        /// <summary>
        /// Applies a discount code to a registration entity
        /// </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>();

            if (entity is Dictionary <string, object> entityDictionary)
            {
                RegistrationInstance registrationInstanceState = ( RegistrationInstance)entityDictionary["RegistrationInstance"];
                RegistrationInfo     registrationState         = ( RegistrationInfo )entityDictionary["RegistrationInfo"];

                if (registrationState != null)
                {
                    registrationState.Registrants.ForEach(r => r.DiscountApplies = true);

                    RegistrationTemplateDiscount discount = null;
                    bool validDiscount = true;

                    string discountCode = GetAttributeValue(action, "DiscountCode", true).ResolveMergeFields(GetMergeFields(action));
                    if (!string.IsNullOrWhiteSpace(discountCode))
                    {
                        // Reload the discounts to make sure we have all the latest ones (workflow can create new codes)
                        RegistrationTemplateService registrationTemplateService = new RegistrationTemplateService(rockContext);
                        registrationInstanceState.RegistrationTemplate.Discounts = registrationTemplateService.Get(registrationInstanceState.RegistrationTemplate.Guid).Discounts;
                        discount = registrationInstanceState.RegistrationTemplate.Discounts
                                   .Where(d => d.Code.Equals(discountCode, StringComparison.OrdinalIgnoreCase))
                                   .FirstOrDefault();

                        if (discount == null)
                        {
                            validDiscount = false;
                            errorMessages.Add(string.Format("'{0}' is not a valid discount code.", discountCode));
                        }

                        if (validDiscount && discount.MinRegistrants.HasValue && registrationState.RegistrantCount < discount.MinRegistrants.Value)
                        {
                            validDiscount = false;
                            errorMessages.Add(string.Format("The '{0}' discount code requires at least {1} registrants.", discountCode, discount.MinRegistrants.Value));
                        }

                        if (validDiscount && discount.StartDate.HasValue && RockDateTime.Today < discount.StartDate.Value)
                        {
                            validDiscount = false;
                            errorMessages.Add(string.Format("The '{0}' discount code is not available yet.", discountCode));
                        }

                        if (validDiscount && discount.EndDate.HasValue && RockDateTime.Today > discount.EndDate.Value)
                        {
                            validDiscount = false;
                            errorMessages.Add(string.Format("The '{0}' discount code has expired.", discountCode));
                        }

                        if (validDiscount && discount.MaxUsage.HasValue && registrationInstanceState != null)
                        {
                            var instances = new RegistrationService(rockContext)
                                            .Queryable().AsNoTracking()
                                            .Where(r =>
                                                   r.RegistrationInstanceId == registrationInstanceState.Id &&
                                                   (!registrationState.RegistrationId.HasValue || r.Id != registrationState.RegistrationId.Value) &&
                                                   r.DiscountCode == discountCode)
                                            .Count();
                            if (instances >= discount.MaxUsage.Value)
                            {
                                validDiscount = false;
                                errorMessages.Add(string.Format("The '{0}' discount code is no longer available.", discountCode));
                            }
                        }

                        if (validDiscount && discount.MaxRegistrants.HasValue)
                        {
                            for (int i = 0; i < registrationState.Registrants.Count; i++)
                            {
                                registrationState.Registrants[i].DiscountApplies = i < discount.MaxRegistrants.Value;
                            }
                        }
                    }
                    else
                    {
                        validDiscount = false;
                    }

                    registrationState.DiscountCode       = validDiscount ? discountCode : string.Empty;
                    registrationState.DiscountPercentage = validDiscount ? discount.DiscountPercentage : 0.0m;
                    registrationState.DiscountAmount     = validDiscount ? discount.DiscountAmount : 0.0m;
                }
            }

            return(true);
        }
        /// <summary>
        /// Shows the discount edit.
        /// </summary>
        /// <param name="discountGuid">The discount unique identifier.</param>
        private void ShowDiscountEdit( Guid discountGuid )
        {
            var discount = DiscountState.FirstOrDefault( d => d.Guid.Equals( discountGuid ));
            if ( discount == null )
            {
                discount = new RegistrationTemplateDiscount();
            }

            hfDiscountGuid.Value = discount.Guid.ToString();
            tbDiscountCode.Text = discount.Code;
            nbDiscountPercentage.Text = ( discount.DiscountPercentage * 100.0m ).ToString( "N0" );
            cbDiscountAmount.Text = discount.DiscountAmount.ToString();

            if ( discount.DiscountAmount > 0 )
            {
                rblDiscountType.SetValue( "Amount" );
                nbDiscountPercentage.Visible = false;
                cbDiscountAmount.Visible = true;
            }
            else
            {
                rblDiscountType.SetValue( "Percentage" );
                nbDiscountPercentage.Visible = true;
                cbDiscountAmount.Visible = false;
            }

            nbDiscountMaxUsage.Text = discount.MaxUsage.HasValue ? discount.MaxUsage.ToString() : string.Empty;
            nbDiscountMaxRegistrants.Text = discount.MaxRegistrants.HasValue ? discount.MaxRegistrants.ToString() : string.Empty;
            nbDiscountMinRegistrants.Text = discount.MinRegistrants.HasValue ? discount.MinRegistrants.ToString() : string.Empty;
            drpDiscountDateRange.LowerValue = discount.StartDate;
            drpDiscountDateRange.UpperValue = discount.EndDate;

            ShowDialog( "Discounts" );
        }