Most Powerful Open Source ERP

How To Use Constraints

How To showing how to use constraints to handle object validation inside ERP5.
  • Last Update:2016-02-11
  • Version:001
  • Language:en

(extract intro!) see

Table of Contents

Consistency

An ERP5 can manage so many objects that we probably want to check how strong they are. Many objects have many relations with others objects, and it's possible that one of them could be broken for any reason (for example the object pointed was deleted). An object could have some mandatory data, but for some reasons, we can't put them when this object is created, so we have to check at some moment whenever or not those mandatory data are present or not.

Definition of the consistency

The definition of the consistency will be defined inside the PropertySheet of our object. This is an example :

_constraints = (
  { 'id'            : 'forme',
    'description'   : 'There must be one and one only Forme',
    'type'          : 'CategoryExistence',
    'portal_type'   : ('Forme',),
    'base_category' : ('specialise',),
    'message_category_not_set': 'Forme must be defined',
   },
  { 'id'            : 'gamme',
    'description'   : 'There must be one or two Gamme',
    'type'          : 'CategoryMembershipArity',
    'min_arity'     : '1',
    'max_arity'     : '2',
    'portal_type'   : ('Gamme',),
    'base_category' : ('specialise'),
    'message_arity_not_in_range': 'One or Two Gamme must be defined',
   },
)

As you can see, we needs to set properly the constraint. In this example we want to check category membership of two components of an object. So we should create two constraints inside the PropertySheet, one for each component from which we want to check the arity. So for each constraint we first give an id and a description.

The type corresponds to the name of the class inside the ERP5/Constraint folder. Here this we use CategoryExistence and CategoryMembershipArity. You can have a look at this class in svn

from Constraint import Constraint

class CategoryMembershipArity(Constraint):
  """...
  """
  """

Every specific Constraint class have to be a subclass of Constraint and should have at least one method : checkConsistency. This is what we can see in CategoryMembershipArity:

def checkConsistency(self, obj, fixit=0):
  """...
  """

The fixit parameter of checkConsistency can be used in order to fix problems. Indeed, most of the time, it's almost the same code if we want to find inconsistencies or if we want to fix them. So instead to create a fixConsistency with a code very similar to checkConsistency, by subclassing the Constraint class, we already have a fixConstency method defined like this :

def fixConsistency(self, obj):
  """
    Default method is to call checkConsistency with
    fixit set to 1
  """
  return self.checkConsistency(obj, fixit=1)

Like this, inside your checkConsistency method, when you found an error, you can simply add :

if fixit==1:
  do_whatever_to_fix

Conditional constraints

It is possible to check conditions for constraints. For example, it might be needed to check for given constraint, only if object is related to specific object or have specific state.

Condition is defined in PropertySheet constraint definition:

_constraints = (
  { 'id'            : 'conditional_forme',
    'description'   : 'There must be one and one only Forme',
    'type'          : 'CategoryExistence',
    'portal_type'   : ('Forme',),
    'base_category' : ('specialise',),
    'message_category_not_set': 'Forme must be defined',
    'condition'     : 'python: object.getSimulationState() not in ["draft","invalidated"]',
   },
)

In above example, constraint will be only checked if object is not in draft or invalidated states.

Creating conditional constraints

Note: I thought it will work without below, but it is not. Am I wrong? (ŁukaszNowak)

In top of checkConsistency method of your Constraint class there is need to check for constraint condition:

def checkConsistency(self, obj, fixit=0):
  """...
  """
  if not self._checkConstraintCondition(obj):
    return []

Related Articles