in
Forums
Blogs
Files
Devexpress.Com
Client Center
Support Center
DevExpress Channel

Tough Rules

Last post 8/8/2007 12:37 PM by Oliver Sturm (Developer Express). 13 replies.
Page 1 of 1 (14 items)
Sort Posts:
Previous Next
  • 7/29/2007 8:50 AM

    Tough Rules

    Hi guys,

    I'm stuck with a somewhat difficult rules situation. Here's the scenario:

    I have three classes Account, Sale and SaleItem. Sale and SaleItem are related with a one-to-many relationship and Account and SaleItem are related with a one-to-many relationship. SaleItem has the following fields among others: These classes have the following fields among others:

    Account: InStock (Current count of Packages - Sum of Account.SaleItemCollection.Packages), Packages (Original count of Packages), SaleItemCollection

    Sale: SaleItemCollection

    SaleItem: Account, Packages

    The rule is such that SaleItem.Packages must never exceed Account.InStock i.e. the SaleItem.Packages <= Sum of Account.SaleItemCollection.Packages.

    How exactly do I translate this into a usable rule such as RuleCriteria.

    Any help is highly appreciated.

    Regards,

    Keith. 

  • 7/30/2007 3:24 AM In reply to

    Re: Tough Rules

    Hi Keith,

    Could you provide a code for these classes?

    Regards,
    Michal

  • 7/30/2007 6:26 AM In reply to

    Re: Tough Rules

    Here's the source:



        //Account
        [Custom("ImageName", "BO_Product")]
        [DefaultClassOptions]
        public class Account : BaseObject
        {
            public override void AfterConstruction()
            {
                base.AfterConstruction();
     
                if (this.Session.IsNewObject(this))
                {
                    this.Reprint = true;
                }
            }
     
            [NonPersistent]
            public int InStock
            {
                get
                {
                    int sales = 0;
     
                    foreach (SaleItem item in this.SaleItemCollection)
                        sales += item.Packages;
     
                    return (this.Packages - sales);
                }
            }
     
            int mPackages;
            public int Packages
            {
                get { return mPackages; }
                set { SetPropertyValue("Packages", ref mPackages, value); }
            }
     
            [Association("Account.SaleItem"), Aggregated]
            public XPCollection<SaleItem> SaleItemCollection
            {
                get { return GetCollection<SaleItem>("SaleItemCollection"); }
            }
     
            //....
     
            public Account(Session session) : base(session) { }
     
        }
     
        //Sale
        [Custom("ImageName", "BO_Sale")]
        [DefaultClassOptions]
        public class Sale : BaseObject
        {
            public override void AfterConstruction()
            {
                base.AfterConstruction();
     
                if (this.Session.IsNewObject(this))
                {
                }
            }
     
            [Custom("Caption", "Sale Items")]
            [Association("Sale.SaleItem"), Aggregated]
            public XPCollection<SaleItem> SaleItemCollection
            {
                get { return GetCollection<SaleItem>("SaleItemCollection"); }
            }
     
            //...
     
            public Sale(Session session) : base(session) { }
     
        }
     
        //SaleItem
        [Custom("ImageName", "BO_SaleItem")]
        [CreatableItem(false), NavigationItem(false), VisibleInReports(true)]
        public class SaleItem : BaseObject
        {
            public override void AfterConstruction()
            {
                base.AfterConstruction();
     
                if (this.Session.IsNewObject(this))
                {
                }
            }
     
            int mPackages;
            public int Packages
            {
                get { return mPackages; }
                set { SetPropertyValue("Packages", ref mPackages, value); }
            }
     
            Account mAccount;
            [Association("Account.SaleItem", typeof(Account))]
            public Account Account
            {
                get { return mAccount; }
                set { SetPropertyValue("Account", ref mAccount, value); }
            }
     
            //...
     
            public SaleItem(Session session) : base(session) { }
     
        }
      
    I hope this is complete enough.
     
    Regards,
     
    Keith 

  • 7/31/2007 6:44 PM In reply to

    Re: Tough Rules

    Hi Keith,

    I would add following property to SaleItem class:

    [System.ComponentModel.

    Browsable(false)]
    [
    RuleFromBoolProperty("SaleItem.IsEnoughPackages.Save",DefaultContexts.Save,"There is not enough packages")]
    public bool IsEnoughPackages {
      get {
        if (Account != null){
          if (Account.InStock >= 0) return true;
        }
        return false;
      }
    }

    Is it a solution you were looking for?

    Regards,
    Michal

  • 8/1/2007 4:26 AM In reply to

    Re: Tough Rules

     Hi Michal,

    Actually this is exactly how I thought It works. But it doesn't. You see, if you have 40 packages in an account, and you allocate say 15 to a sale you will have 25 in stock, right? If you edit the same SaleItem and increase the packages from 15 to 30 IsEnoughPackages will return false even though the data is valid. Besides that, it gets even tricker when you have more than one  SaleItem for the same account. Can you see?

    Regards,

    Keith. 

  • 8/1/2007 10:00 AM In reply to

    Re: Yet More Tough Rules

     Hi Guys,

    I have yet another one. I need to create a rule that ensures the following:

    Given two classes each with a property that is an enum (different for each case) I need to ensure that the values selected for one constrain the values available for the other. ClassA has the property AuctionType (enum: Main, Secondary, Other) and the other ClassB has a property SaleType (enum: Ordinary, Late, Private). ClassB is a collection of ClassA (one-to-many).

    If ClassA.AuctionType == Main | ClassA.AuctionType == Secondary then ClassB.SaleType ==* Ordinary.

    Else if ClassA.AuctionType == Other then ClassB.SaleType ==* Late | ClassB.SaleType ==* Private

    * Must Be 

    Does anyone know how to put this in a nice neat  attribute? Thanks.

    Regards,

    Keith. 

  • 8/1/2007 12:39 PM In reply to

    Re: Tough Rules

    Actually this is exactly how I thought It works. But it doesn't. You see, if you have 40 packages in an account, and you allocate say 15 to a sale you will have 25 in stock, right? If you edit the same SaleItem and increase the packages from 15 to 30 IsEnoughPackages will return false even though the data is valid. Besides that, it gets even tricker when you have more than one  SaleItem for the same account. Can you see?
     
    Keith,
     
    what you describe here is the problem known in computing as "Incremental Update".
     
    Following your example, you have 40 units in stock, and you sell 15 units, then you have 25 units in stock (40-15=25).
    Now if you edit the same(!) row and you increase the sale from 15 to 30, you get -5 in stock, which is wrong (25-30=-5)
    It is wrong, because you can't use the formula stock=stock-sale repeatedly on a single row.
    Instead use the formula stock=stock+saleOldValue-sale
    In your example stock=25+15-30 you get 10 in stock, which is correct.
     
    Now I can't tell you how to do this in XAF, because I never used XAF except for "playing around" ;-)
    But if you are able to get the "oldValue" of a property after it has been edited, then you should have no problem to implement it.
     
    HTH, Robert
     
  • 8/1/2007 12:54 PM In reply to

    • drew..
    • Top 25 Contributor
    • Joined on 5/7/2007
    • Victoria, BC
    • Posts 878

    Re: Tough Rules

    this is circumvented by taking your app to a more grounded audit-trail level. Any saved item should never be changeable, and should maintain a 'posted' state. If posted, no edits. If you are adding 5 items, do that in a second row. Any system that manages inventory should not rely on a relational db setup for its' state, but a pseudo-linear arrangement where each subsequent change is reflected in a new entry. Think accounting packages.. you need a solid audit trail or the numbers mean very little...  just my 2 cents... i am sure there are arguments to counter my thoughts..  Ü  drew..

  • 8/2/2007 3:41 AM In reply to

    Re: Tough Rules

    Thanks guys. Actually, besides InStock there's a property (Packages) that holds the original value which never changes. InStock is a PersistentAlias. That is what i was hoping to use to calculate the value.

    Keith. 

  • 8/2/2007 8:08 AM In reply to

    Re: Tough Rules

    I fully agree with Drew. To make your solution reliable, there should be a posted state or other way to keep track on real amount of posted sale items.

    But anyway - validation in Solution13.zip I've attached to my last post is working for me - I can increase existing saleitems amount with correct validation. Is your object schema the same?

    Michal

  • 8/2/2007 11:10 AM In reply to

    Re: Tough Rules

    I get Drew's point. Actually, the SaleItem must be editable since it must be 'Confirmed' (by adjusting no of packages and prices among other things) at a later time from when it is entered. This is an auction kind of scenario. I'm thinking of implementing Drew's idea. Thanks.

    Keith. 

  • 8/8/2007 9:21 AM In reply to

    Re: Yet More Tough Rules

    Hi,

    Keith Dennis wrote:

    > I have yet another one.



    I have created a sample solution for you that implements your exact
    requirements. This is a very good example of a custom validation case. Our
    validation system is extensible, and these cases that implement validation
    on the basis of business logic show the reason for this very well.

    Please let me know if the sample (attachment) is somehow not right for you.

    --
    Regards,
    Oliver Sturm
    Developer Express Inc.
    MVP C#
    --
    Regards,
    Oliver Sturm
    Developer Express Inc.
    MVP C#
  • 8/8/2007 12:04 PM In reply to

    Re: Yet More Tough Rules

    Thank you very much Oliver. Your example explains a lot. I've been trying to create custom validation rules but I try as much as possible to bend existing ones (much less code Big Smile) to suit my needs. This example paves the way to create other custom validation rules. However, I would like to see some validation such as a RuleUniqueValue that supports multiple fields come out of the box. Thanks again.

    Regards,

    Keith. 

  • 8/8/2007 12:37 PM In reply to

    Re: Yet More Tough Rules

    Hi,

    Keith Dennis wrote:

    > I would like to see some validation such as a RuleUniqueValue that
    > supports multiple fields come out of the box.

    I guess that's a good candidate for inclusion, sure.

    --
    Regards,
    Oliver Sturm
    Developer Express Inc.
    MVP C#
    --
    Regards,
    Oliver Sturm
    Developer Express Inc.
    MVP C#
Page 1 of 1 (14 items)
Copyright © 1998-2008 Developer Express Inc.
ALL RIGHTS RESERVED