Adding a chained rule using a property on another Business Object

Adding a chained rule using a property on another Business Object

Old forum URL: forums.lhotka.net/forums/t/12750.aspx


kreid posted on Monday, September 15, 2014

I have a BO called Payment.

When a Customer makes a payment, I need to require that Customer to have a BillingAddress set, if it is an account payment.

However, I'm not sure how to do this in practice. What I have so far is shown below - it is throwing "given key not present in the dictionary". I can understand why. Really I just don't know if this is possible.

CODE:

private class ValidCustomerBusinessAddressRequiredForAccountPayments : BusinessRule

        {

            private readonly IBusinessRule _addressRequiredRule;

            private readonly IBusinessRule _addressCompletedRule;

            public ValidCustomerBusinessAddressRequiredForAccountPayments()

                : base(MethodProperty)

            {

                InputProperties = new List<IPropertyInfo> { MethodProperty };

                _addressRequiredRule = new Required(Customer.BillingAddressProperty);

                _addressCompletedRule = new FullAddressRule(Customer.BillingAddressProperty);

            }

            protected override void Execute(RuleContext context)

            {

                var target = (Payment)context.Target;

                var method = target.Method;

                var customer = Customer.Get(target.PrimaryContactId);

                if (customer != null && method == PaymentMethod.Account)

                {

                    context.ExecuteRule(_addressRequiredRule); // throws exception

                    context.ExecuteRule(_addressCompletedRule);

                }

            }

        }

JonnyBee replied on Monday, September 15, 2014

No, this is not possible!

You may add code in OnChildChanged event on Customer and revalidate these fields on the customer object when child properties are changed. 

thaehn replied on Monday, September 15, 2014

What I do in a situation like this is create a command object that goes out to the database and does the check.  I set a logical property on the command object which is checked when it returns to the rule.

    /// <summary>

    /// The UPS chargeback code validate billable rule.

    /// </summary>

    public class UpsChargebackCodeValidateBillableRule : BusinessRule

    {

        public UpsChargebackCodeValidateBillableRule(IPropertyInfo primaryProperty)

            : base(primaryProperty)

        {

            ProvideTargetWhenAsync = true;

            IsAsync = true;

 

            AffectedProperties.Add(UpsChargebackCodeItem.BillableProperty);

        }

 

        /// <summary>

        /// The execute.

        /// </summary>

        /// <param name="context">

        /// The context.

        /// </param>

        protected override void Execute(RuleContext context)

        {

            UpsChargebackCodeItem target = (UpsChargebackCodeItem)context.Target;

            if (target.Billable == false)           

            {

                UpsChargebackCodeValidateBillableCommand.BeginExecute(target.Id, (o, e) =>

                {

                    if (e.Error != null)

                    {

                        context.AddErrorResult(e.Error.Message);

                        context.Complete();

                    }

                    else

                    {

                        if (e.Object.OverrideUsed)

                        {

                            context.AddErrorResult("Code Is Overridden by Customer.  Please Remove Code from Customer First.");

                            context.Complete();

                        }

                        else

                        {

                            context.AddSuccessResult(true);                           

                        }

 

                        context.Complete();

                    }

                });

            }

            else

            {

                context.AddSuccessResult(true);

                context.Complete();

            }

        }

    }

Todd

Copyright (c) Marimer LLC