Every coder is more or less familiar with a concept of "inheritance": if object
A has a certain property or method, and object B "is-a-kind-of" A, the object B
has the same property, unless it overwrites it. This is simple.
Table of Contents
Acquistion¶
Zope users should know the concept of "acquisition": if object B is contained in
A, then if you ask B about a certain property which it does not have, it "acquires"
this property from A. Simple at the first glance, can be used in mindbogglingly
complicated ways.
ERP5 extends the concept by allowing the developer to define which property is
acquired from which object and in what way. This is called "programmable acquisition".
It allows for easy implementation of statements like:
A person works in the same industry as the company he is working for
or
A child has the same nationality as his parent, unless we explicitly say he has a different one
The property can be acquired from any object which is in any way related to the
object; the developer can decide:
-
what relation is used to find the object from which we aquire
(see how to configure Relation String Field
for some information about relations)
- what portal type we want to acquire from
- what accessor is to be used on the "source" object
and define some more precise settings, which are described below.
The acquisition can be defined in a Property Sheet, to be used only by objects
which use it, or site-wide by configuring a base category (e.g. region).
In many cases, in practically boils down to setting a default value for a property;
yes, it can be done by putting a simple instruction in TALES tab on a field in
Formulator - but by using programmable acquisition we work on the data model,
not on GUI, thus maintaining a clean separation between Model and View.
Simple Example¶
This is a simple, real-life example, from a running CRM implementation.
The properties being recorded are:
- when did we have the first contact with an Organisation
- when did we first meet a Person
- where do we know them from
The first two information are recorded as a property "first_contact_date" in a
Property Sheet, which is defined as follows:
{ 'id' : 'first_contact_date'
, 'description' : 'Date of first contact.'
, 'type' : 'date'
, 'acquisition_base_category': ( 'subordination', )
, 'acquisition_portal_type' : ( 'Organisation', 'Career')
, 'acquisition_accessor_id' : 'getFirstContactDate'
, 'acquisition_copy_value' : 0
, 'acquisition_mask_value' : 1
, 'acquisition_sync_value' : 0
, 'mode' : 'w'
}
What this says is:
The date we first met a Person is the same as the date we first met the company
he is working for, unless we met him some other time.
This is useful, because if we meet many people from the same company at the same
time, we have to enter the date only once - for the Organisation, and all the
Persons will acquire it. If we meet somebody from the same company later on,
we can set another date for this Person only, and it will "mask" the acquired
value (because we set acquisition_mask_value to 1).
The acquisition uses 'subordination' base category to find the Organisation;
it is a bit more complicated because it has to go two steps, through a Career
object, so we have to specify two portal types as acquisition_portal_type.
The information about where do we know them from is recorded as membership in an
"origin" category, which has the same settings as the first_contact_date property,
but is configured through portal_categories tool, and has acquisition_copy_value
set to 1, because we want to use it for listbox' domain tree.
Acquisition parameters¶
-
acquisition_base_category:
Where we are looking for the "source" object. Usually a relation name - one
of base categories. Can also be 'object', then we acquire from self.
-
acquisition_object_id:
Instead of looking for an object related by a given category, we can acquire
from a contained object of a given id.
-
acquisition_portal_type:
This limits the search for a property source to objects of certain portal types.
-
fallback_base_category:
What category to search if the above fails (XXX not sure).
-
acquisition_accessor_id:
What property we want to get from "source" (which accessor is to be run on
it). This is used only in Property Sheets, not in base category configuration,
because accessor for category membership is derived from category name.
-
alt_accessor_id:
A list of alternative accessor id; if you make it a tuple containing one
item - the one you gave as acquisition_accessor_id - it will work. (XXX
real use for it?)
-
acquisition_copy_value:
Do we want to copy the property value to the local object, or do we rather
acquire it every time it is needed. In most cases it does not matter (maybe
it has some impact on performance?), with one exception: if the property
being acquired is a category membership, and you want to build a listbox
domain tree using this property, then you need to have a local "copy" of
the property, so set it to 1. (XXX probably needed for searching too)
-
acquisition_mask_value:
Does locally set value overwrite the acquired one - required if you want it
editable. If you set value locally, it will overwrite the acquired value;
when you delete it or set to an empty value, you'll get the acquired value again.
-
acquisition_sync_value:
not used
-
acquisition_append_value:
not used
-
category_type:
not used
-
mode:
Not used (though must be present in property sheet).
A special case - "content" data type¶
Instead of 'string', 'int', 'float' or 'date', you can set the type of property
you are defining to 'content'. This is for special cases, when you want to
create a content object to store the property you are setting, and then
acquire the property back from the new object.
This is best explained by looking at a Person object and how it stores, for
instance, street address. When you create a Person, it has no address. If
you set a street address, it is not really set on the Person object -
instead there emerges a new object with id 'default_address' which has
the street address you've just set. The Person object displays the new
street address because it acquires the address from default_address object.
Edit the street address in either of the two places - the other place will
show the new value. Change the id from 'default_address' to anything else -
the Person no longer shows the street address.
The key to achieve this is specify the following:
- type: Make it 'content'.
- : The id of content object (like default_address).
- portal_type: Must be given, and only one, so that ERP5 knows what to create.
- acquired_property_idA tuple of properties which will be 'synchronized' between the current object and the content object.
The system will generate special accessors, built from storage_id and acquired_property_id;
for example, Person object has methods getDefaultAddressStreetAddress and
setDefaultAddressStreetAddress.
Related Articles¶