Printable version XML version
Login
Name

Password


Join
Forgot your password?
erp5.org => wiki.erp5.org !

erp5.org has permanently moved to wiki.erp5.org !

Current status of ERP5 community websites:

  • www.erp5.org should redirect to wiki.erp5.org automaticcaly.
  • wiki.erp5.org is the place where fresh news and documentation are published.
  • cps.erp5.org is the old erp5 community website.

Note: if you created content in this ancient portal, please migrate it to the wiki. The old website will stay online as long as all contents are not mograted to the wiki.

Predicates
This document will describe how to well define a predicate, and wich tools
are used in order to find a predicate for a particular context.

What's a Mapped Value ?

A mapped value allow to define some values (properties or categories) corresponding to some conditions.

For example, you may need to define the price (the value) corresponding to a resource and a range of quantities (conditions).

The idea is to create in many places into ERP5 mapped values. Let's say you have a document, if you are looking for a value (for example a price) for this document, then a tool will look at all mapped value stored in ERP5, and it will give you all mapped value (most of the time you will get only one) where the conditions corresponds to your document, so you can know wich value you can take.

The document on wich you are looking for a value is usually called the "context".

If you want to define a mapped value, there is two different set of properties to update. The first set of properties defines the Value, the second set of properties defines the conditions. There is two classes in ERP5 corresponding to the two sets, the first one is MappedValue, the second one wich defines condition is Predicate.

On each predicate, there is a method called test defined like this:

    def test(self, context,**kw):

This method returns True if the context corresponds to this predicate, or it returns False otherwise.

For example, you have a mapped value A defined like this :

    value:
      base_price : 23
    conditions:
      5 < quantity < 23
      resource = product/openbrick

Then let's say you have an order whith a line (this is your context), the resource of this line is an openbrick and the quantity is 10. What is the base_price for this context ? You can look at all mapped value in your ERP5 site, then run the test method on each of them, if the result is true, you can see if the mapped value define a price. You will see later you the portal_domains tool will do all that for you.

Define the Mapped Value :

Here you will define value. There is two things to do. The first step is to define wich property or category you want to specify, then you have to store values.

In order to tell wich properties you want to define, you have to use the method setMappeValuePropertyList, like this :

    mapped_value.setMappedValuePropertyList(['base_price'])

In order to tell wich categories you want to define, you have to use the method setMappedValueBaseCategoryList, like this:

    mapped_value.setMappedValueBaseCategoryList(['destination'])

Finally, you can store values and categories, like it is already done everywhere in ERP5, with default setters :

    mapped_value.setBasePrice(34.5)
    mapped_value.setProperty('base_price',34.5)
    mapped_value.setDefaultDestination('person/111')

Once values are stored, you may want to define conditions, we usually said that we will define the Predicate.

Define Predicates :

First, you will learn how to define conditions based on properties and then conditions based on categories.

About, properties, you may want to define different types of conditions :

    - equality
    - more than
    - less than
    - a range

You first need to define what are the properties used in order to create your condition. This method is called setCriterionPropertyList and you can use it like this:

    mapped_value.setCriterionPropertyList(['quantity'])

Then, there is a method called setCriterion, defined like this :

    setCriterion(self, property, identity=None, min=None, max=None, **kw)

The name of arguments are quite obvious, it is easy to use, this is some examples:

    quantity==4: mapped_value.setCriterion('quantity',identity=4)
    quantity>=4: mapped_value.setCriterion('quantity',min=4)
    quantity<5: mapped_value.setCriterion('quantity',max=5)
    2<quantity<5: mapped_value.setCriterion('quantity',min=2,max=5)

Let's define now conditions on categories. You first need to set wich base categories are used for conditions. There is two possibilities for each base category. You may want that your context is a member of many categories with the same base category. Or you may want that your context is a member of at least one category from a list of categories.

Firs case, you want that your context is a member of many categories for a particular base category, you will need to define the multimembership_criterion_base_category_list property and membership_criterion_category_list like this:

    mapped_value.setMultimemberhsipCriterionBaseCategoryList(['skill'])
    mapped_value.setMembershipCriterionCategoryList(['skill/a','skill/b'])

In this case, the mapped_value corresponds if the context is both member of skill/a and skill/b.

Second case, you want that your context is a member of at least one category from a list of categories, you will need to define the membership_criterion_base_category_list property like this:

    mapped_value.setMembershipCriterionBaseCategoryList(['region'])
    mapped_value.setMembershipCriterionCategoryList(['region/europe','region/africa'])

In this second case, the mapped_value corresponds if the context is a member of region/europe or region/africa.

The asPredicate Method :

There is also another way to specify some properties used for the test. The previous way of doing is quite annoying for resource, source and destination. Why should be defined it as a category on a document, and as a membership_criterion_category_list on a predicate ?

This is the same thing for the start and stop dates. So a method called asPredicate exists on predicates (and very soon on many other documents), and it will create predicate properties thanks to local properties.

If you want to define a period, you can use the newly created range parameter of properties. Indeed you can see the propertySheet of Task, and you will see that the start_date has a range value to True. This means that we can use ranges for the start_date, like this:

    setStartDateRangeMin()
    setStartDateRangeMax()
    getStartDateRangeMin()
    getStartDateRangeMax()

So if you create a predicate with a start_date_range_min property and also a start_date_range_max property, with the asPredicate method it is like to define a range criterion.Then the test method of this predicate will check that the start_date of the context is greater than the start_date_range_min and lesser than the start_date_range_max.

If you define a resource on your predicate, with the asPredicate method, this is like to define correctly membership_category_list and multimembership_criterion_category_list.

You may want to configure the list of local properties wich works like a criterion property and the list of base categories wich works like a membership criterion base category with 2 portal defaults values:

  • portal_criterion_base_category_list, default to (source,destination,resource,group)
  • portal_criterion_property_list, default to (start_date,stop_date)

Search Predicates

If you want to find a predicate for a particular context, you can use the portal_domains tools. There is a method call searchPredicateList defined like this:

      def searchPredicateList(self,context,test=1,sort_method=None,
                                            ignored_category_list=None,**kw)

This method wil give you all predicates corresponding to your context. If a sort_method is provided, you can define in wich order the list will be sorted. This is very usefull if you want to sort by date or by whatever you want.

You can give many parameters, for example a portal_type. Indeed, searchPredicateList will call the portal_catalog.searchResults methods, so searchPredicateList will be able to understand any parameter that searchResults can handle.

Generate a mapped Value

The domain tool provides another method called generateMappedValue. You can use it with the same list of parameters than searchPredicateList:

    def generateMappedValue(self,context,test=1,predicate_list=None,**kw)

You can also provide a sort method and anything that portal_catalog.searchResults will be able to understand.

This method will create a new mapped value for a particular context.

If no predicate_list provided, this method will call searchPredicateList in order to find the list of predicates corresponding to your context, then it will look at each of them for all mapped value properties and categories defined. So if you have a predicates wich defines a price, and another one a discount, the new mapped value generated will have both properties.

If you have several predicates wich defines the same properties for a particular context, generateMappedValue will take the value of the first predicate. That's why it is sometimes very important to specify how to sort the list.

Example.

Let's say that you have several supply lines defined for a resource, each of them defines a base price for several ranges of quantities, and each of them are available only in some periods.

So on each supply line you define a start_date_range_min and a star_date_range_max, and a cell is defined for each range of quantities ::

Then, let's say that you have a context : a movement of the resource for a particular quantity and a particular date.

If you want to get the right base price, for your context, the only thing you need to do is:

my_price = portal_domains.generateMappedValue(context).getProperty(base_price)


(c) 2001-2004 ERP5 Foundation
www.erp5.org
All Content Published Under Free Licenses
Powered by ERP5 Open Source ERP, Zope, CPS and Nexedi