Jump to content

ERP5 Handbook/Print Version

From Wikibooks, open books for an open world

Table of Contents

Preface

This book tells about a leading Open Source ERP system. It is of French origin, but multilingual and deployed in many countries. It is versatile, powerful, complex, abstract and free. We (authors) think it is great, and we want it to be used by more people so that there is a community of users supporting each other in a true Open Source spirit. This is why we are writing this handbook.

Audience

This book is written for people, who are interested in developing, implementing ERP5 - ERP Open Source system. You will learn basics of ERP5 - usage, development - and ways of searching for more help. If you are a technician, consultant or hacker - this book is for you. If you are a businessman without time for hacking through big systems with many connections this book is not for you. Take a look at erp5.org and hand this page over to your IT guy.

Keep in mind that ERP systems are quite complex - you will need time to deploy its test installation.

What you should know before proceeding

An ERP5 system uses the following technologies (programming language, server side technology, relational database...). Your set-up should be similar, and familiarity with them will help.

  • Python programming language
  • Zope, version 2, application server
  • XML
  • MySQL relational database
  • Subversion - version control system

Of course experience in business and modelling business processes is quite helpful.

Part I: First shock

After this part the reader should be able to install and use an ERP5 system with some business templates and hack a little bit on it. Understanding of genericity of ERP5 system should be sufficient to explore it - every installed module, creation and update of objects, setting of relations.

Chapter 1

TODO: Proof reading and extending by experts is needed.

Getting Started

Terminology

Clipboard

To do:
We need to separate introduction about ERP in general (it is quite long topic: ERP definition, coverage, few words about history and link some references) and about ERP5.


ERP stands for Enterprise Resource Planning

(FIXME: What does a "ERP system" do? Can you summarize it in one sentence?)

(FIXME: What kind of person would ever use an ERP?)

(FIXME: Rewrite the cryptic english...)

A few words about ERP systems

Basic Ideas

ERP systems are quite complicated - they have to implement as much as possible the business logic of a company. ERP5 distinguish itself from other ERP systems (open and closed source) with its coherency from the lowest - theoretical - level. It is based on a well developed theoretical model and to understand the key concepts of ERP5 it is needed to understand briefly that model. Of course basic understanding of technical aspects is needed too.

Five classes - introduction

ERP5 defines an abstract model of business management. Thanks to a clean abstraction layer, new or specialised business modules can be implemented in a consistent way. This abstract business model can both be used to represent internal management activities as well as commercial and management activities across a group of companies

The ERP5 abstract model is based on 5 classes:

  • Resource: a resource describes an abstract resource in a business process (e.g. a skill of an individual, a currency, a raw material, a product). Relations between nodes allow to define BOM (Base Object Model) as well as prototypes.
  • Node: a node is a place which can receive amounts of resources and send amounts of resources. Nodes can relate to physical entities (e.g. a workshop which receives raw material, processes it and sends it) or abstract entities (e.g. a bank account which can receive money). Stocks are a kind of Node. Metanodes are nodes which contain other nodes. A company is a metanode. A project is both a resource and a node.
  • Movements: a movement describes the movement of an amount of resource between two nodes at a given time and for a given duration. For example, a movement may send raw material from a stock to a workshop, another movement may send money from one account to another.
  • Path: a path allows to define a way for a node to access a resource it may eventually need. Prices and commercial profiles may be attached to a path in order to define the default price for a given resource procured at a given maker. Path may also define the way a workshop gets its resource from a stock. Path have a start date and an end date. Path may be used to represent the assignment of an individual to a temporary project.
  • Item: an item describes a physical instance of a resource. A movement can be expanded into a series of trackable movements through items. items also allow to define how a given amount of resources was actually shipped (e.g. parcels, serial numbers of items in each container, etc.)

Those five classes are sufficient to represent business ranging from chemical plants to manufacturing, trading or services, and can model everything that goes on in an organisation. For example:

  • a sale of goods is a movement of a certain quantity of a product (resource) from our company (node) to the buyer (node) at a given price (path)
  • an accounting entry is a movement of some money (resource) between two accounts (nodes)
  • an phone call is a movement of an employee's time (resource) between the two interlocutors
  • a training is a movement of skill (resource) from nowhere (surprise!) to the trainee

It sounds very abstract, but that's exactly why it is so powerful...

Modelling reality like this, we use the same attributes to describe very different things: every movement has its source and destination, plus some variations of them (e.g. in sale transaction source is a physical location from which goods are shipped, while source_section is the owner who is selling the goods). And we can use standard, optimised API to calculate the results.

The key question is always: how much do we have of (this or that). In this model, a node doesn't really have "content"; when we want to know how much goods are there in a warehouse, or what is the amount on account, or how much time our support guy spent answering phone calls, we sum up quantities of all movements incoming to and outgoing from the node. For this, we use a standard "getInventory" method which serve every purpose of this kind.

Simulation model

Simulations are one of the most powerful features of ERP5, although they are entirely hidden from the user. The idea is that movements which are supposed to have an impact on the future - or, in other words, which are going to cause some other movements - are equipped with so-called "rules" which are used to generate "simulation movements", which in turn can have their own rules and generate further simulation movements, thus "simulating" the future of our business. When the future becomes present and it's time to create real movements, we use simulation movements to check what, how much, for whom etc.

It is best explained on an example: if we accept a sale order, we know we'll sooner or later have to ship; and once we ship, we'd like to invoice; and once we invoice, we are going to get money. So a sale order is broken into lines, each line representing delivery of one product, and each line generates a simulation movement representing shipment. Shipment then generates simulated invoice line, etc.

The benefit of this is twofold:

  • once we accepted an order, we can get a financial forecast straight from the system
  • when we start packing, we can aggregate orders in any way we like - we don't have to pack order by order, instead we can generate a separate packing list for each product line, or combine all orders from the same customer into one big list, or even do both - create a separate packing list for products from the same product line ordered by the same customer over the last month, for instance. The point is to equip our ERP5 with appropriately configured "builders" which will do the job.

Affiliation between MySQL and ZODB

In ERP5 all objects are put into ZODB (Zope Object Database) and they are indexed in SQL database (run on MySQL RDBMS). Such attitude results in fast object searching and access, and from other side - easy object manipulation.

User interface - listboxes, views

Reporting and printing

Reports allow users to generate summaries and specifications for the data stored in modules. Reports can be generated in two forms: an OpenOffice.org document or a PDF form.

A place on a form where icon appears.

Reports are attached to the specific module. If there are any reports defined for that module, then on the standard module view form, with a listbox containing that module's data, the report icon will appear in the toolbar. (if there's no data the icon will still appear :) )

Although reports are in this way associated with the module and one expects to find data related to the module, they may practically contain any kind of data.

The detailed HowTos on creating reports may be found on ERP5 Wiki pages, both for OpenOffice reports and PDF reports. There is also a guide on how to add created reports to ERP5 site.

Background process invocation - CMFActivity system

ERP system logic might be very complicated - any scripts can be attached to any object in the system. It is possible that on encumbered systems the server resources become overloaded. The advantage of this approach is that the consultant or application manager might want to have the ability to set up some scripts one by one, or to choose some special conditions which will happen before invoking some actions.

ERP5 provides a built-in background process invocation system called CMFActivity. With this the resource-consuming tasks can be prioritised and put into background. They will be invoked in whatever desired order, one at a time, such that resources of the machine won't be overconsumed. After invoking such tasks an icon appears on the user interfaces of objects which are directly related to this object, informing the user that this object is waiting to be processed by a pending activity.

On a properly configured system CMFActivity may send messages about failed tasks. Developers and consultants are able to attach a special console - from Zope, and even from a system shell - to observe, cancel or force invocation of activities.

In technical sense every task put into activity is a row in the SQL table. Here is described with each object what activity shall be run, what that activity is and other properties. CMFActivity supports clustering and load-balancing of task queues.

In depth background process invocation is described on the ERP5 wiki page HowToUseTheCmfActivityTool.

Categories

The ERP5 system is based on categories, they are used to define the categorization and descriptive relation between objects in the system.

Categories are accessible and configurable through the Zope interface. To do this, go to:

[your_site]/portal_categories

(user "zope" can access if from the "My favourites" dropdown menu in the top left corner)

You will see a long list of "Base Categories". Click on any of them, you'll see it has lots of fields which you don't need to know anything about at this stage. Under the Action dropdown menu there is an option with which you can create a sub-category. Then you can create sub-sub-categories, and for each of those sub-sub-sub-categories, and so on ad infinitum.

Some base categories (region, site, group, function, skill...) are used for categorization, so you can build your trees within them; others (source, destination, subordination...) are used for setting relations between objects, and they don't need any subcategories.

The system accesses categories using special accessors, which makes categories translatable.

Categorization usage

By defining a tree in a given base category a consultant is able to set up categorization with required depth. Examples of categorization categories are:

  • region - to tell where a Person lives or where the Organisation has its headquarters
  • skill - to tell who can do what
  • quantity_unit - for definitions of quantity units for resources
  • delivery_mode - describes modes of transport for orders
  • gap - used for General Accounting Plan

The beauty of this category mechanism in ERP5 is that you can assign an object to one or more categories at your discretion, and that the notion of "category membership" goes all the way up the base category tree (meaning that if an object belongs to category "a/b/c", it belongs to category "a/b" and "a" too. That way, you can set up a category tree:

skill/dance
skill/dance/latino
skill/dance/latino/samba
skill/dance/latino/salsa
skill/dance/latino/rumba
skill/dance/classic
skill/dance/classic/waltz
skill/dance/classic/tango
skill/dance/ballet
skill/coding/c

Then assign persons to categories:

Joan
skill/dance/latino/samba
skill/dance/classic/tango
Mary
skill/dance/latino
Paul
skill/dance/ballet
Peter
skill/coding/c

Now, if you ask the system who can dance samba - you get Joan, Latino - you get Mary and Joan, classic/tango - Joan, classic - Joan, too; ask who can dance anything - you get Mary, Joan and Paul; and if you want to know who can't dance at all, you can get it too. All by using auto-generated accessor methods, without any fuss.

To see it in action, go to the "Persons" module and turn on the "domain tree" mode of the module's listbox; select "skill" from the dropdown, and you can browse your dancing resources.

If you plan to open a dance school, then the system is perfect for you.

Have a look at the Understanding listboxes section for more details, and some screenshots.

Relation usage

As opposed to categorization usage some categories are used for relation system. Lets say, that we have Organisation object ACME and Sale Order object SO-1. We can define a relation between SO-1 and ACME using a source category. The sale system is implemented in such a way that the source category means that goods will be send from ACME.

Most popular relation categories are:

  • source
  • source_section
  • destination
  • destination_section
  • parent

Using relations is described in detail here: http://wiki.erp5.org/HowToConfigureRelationField

TODO: How reader shall identify distinction between categories in portal_categories?

Workflows

General introduction

Workflows are one of the key concepts of ERP5. They are used everywhere, for everything. They are so important because a workflow represents a process - and everything that is done in a business is a process. A workflow can represent any process, e.g. editing and publishing an article, recruiting a person, receiving and processing a sale order, making an accounting entry etc.

  • States and Transitions

When an object is managed by a workflow, it means that it is subject to a procedure which this workflow represents. A procedure consists of some states and transitions between the states, and can be nicely represented by a graph, where boxes represent states, and arrows represent transitions. The workflow has an initial state, which the object assumes when it is created. If a transition is made, it changes its state to a destination state of the transition. Then another transition can be made, and so on until the object reaches a state from which there is no more transitions.

ERP5 standard interface shows the object's workflow state in the main form, and available transitions in the "Action" dropdown.

  • Security

An important thing a workflow does is managing access rights to an object. For example, an article which is in a "draft" state should be accessible only to its author (for read and write), while "published" article should be readable by everyone and writable by nobody. Access rights can be defined and set separately for every workflow state.

  • Conditions

A transition can be made available only to users who have certain rights in the system - for example, you have to be a "chief editor" to be allowed to publish an article. If you are not, you won't see the "Publish" action in your action box. A transition can also depend or other object properties - an article can be submitted for publication only if it contains some text, or an accounting entry can be confirmed only if credit and debit are equal.

  • Side effects

Workflow transitions can have "side effects" - actions to be executed when a transition is being made. Sticking to our publication workflow, when a document is being published, the system can send email notification to all subscribers. A more business-oriented example is that when a sale order is confirmed, the system generates a planned invoice.

  • Interaction workflows

This is a different kind of a workflow - it has no states, and no transitions. Instead, it has "interactions", which are triggered when a given action is being made on an object. Interaction workflows are basically a cleaner and more portable way of implementing side effects - if we want a notification send when a document is published, we can do it by tweaking publication workflow, but we can instead add an interaction workflow with a "send notifications" interaction hooked to the "publish" action of the publication workflow.

  • Edit workflow

This is a special workflow, which is hooked to almost every object in ERP5. It is quite unusual because it has only one state - "current" - and one transition which goes back to the same state. This transition is executed every time an object is edited; the sole purpose of this workflow is recording the object's history.

How to implement

See http://wiki.erp5.org/HowToUseAndDefineWorkflows for detailed instruction and technical information.

Introduction to security

Please refer to this article:

http://wiki.erp5.org/HowToDesignSecurity

for guidelines about how to design security for an ERP5 application, and to this:

http://wiki.erp5.org/HowTo/HowToUseNewSecurity

for how to implement it.

Five classes - extended

Chapter 2

Let's go...

Installation of the core

An alternative way of installing and running an ERP5 site is by using RPM repositories. Below is a short and concise description of how to make ERP5 up and running in just a few steps.

First of all we need to get the Zope/ERP5 sources as well as some additional software packages. If there's a Zope installation in the system, we have to uninstall it. ERP5 uses a patched Zope version which is downloaded and installed together with ERP5. It is possible to have two installations of Zope, but that is an advanced topic and won't be covered here.

For very good downloading instructions read the Download How To on ERP5 home site. After successfully downloading and installing all the packages we can proceed with configuration and setup.

Still as a root user we go to the Products sub-directory of a newly created Zope INSTANCE_HOME directory and run the svn_update script which will do all the hard work. Since INSTANCE_HOME should be in /var/lib/zope/ we type:

cd /var/lib/zope/Products
ls (as shown on a screenshot this should show us some dirs and a script)
sh svn_update.sh

After the data from SVN repository has been updated we need to make sure Zope can access it. We do it by making all the sub-directories and files therein Zope's own:

chown -R zope:zope *

On the console it should look like this: Using SVN to update Products and Business Templates

One last thing is needed to be done, before we run the Zope instance. We need to create the main manager user. It doesn't matter what the username will be, as long as it contains only the standard letters. For example if we'd want to create user 'zope' with password 'zope' we need to run the commands:

zopectl stop (to make sure Zope is stopped for adding a user)
zopectl adduser zope zope
zopectl start

With the output not unlike this:

Adding a manager user to new Zope instance

Don't be scared by DeprecationWarnings. If you don't mind them, they won't mind you. :)
After the final command Zope should be up and running which we can check, by going to the address: http://localhost:9080/manage in an internet browser of our choosing.
The Authorization Dialog should pop-up asking for username and password. We enter the newly created zope user name and password.

Creating a new database and assigning rights to it

If the dialog does not appear and the browser displays some kind of 'Unable to connect' message it means the Zope instance didn't truly startup. To check what's preventing the correct start up, it's best to go to zopectl interface and check the startup output. To do that we can enter:

zopectl

and after receiving the zopectl> prompt either enter:

zopectl> logtail

to display last lines of the startup log (hopefully with error message there) or type :

zopectl> stop
zopectl> foreground
(or zopectl> fg)

to see whole output of the startup procedure. Eliminating eventual errors is out of scope of this section.

Before we go on to creating and starting the ERP5 site, we need to make sure it has its very own space in the MySQL server. This is important since the default test database that exists in MySQL is used for the testing procedures and using it also for the regular ERP5 site might cause unexpected problems. To make a erp5 database for our new site we need to do the following (we assume the name of the database is 'erp5', but that can be anything else):

mysql (enter the mysql interface)
mysql> CREATE DATABASE erp5;
mysql> GRANT ALL ON erp5.* TO erp5@localhost IDENTIFIED BY 'erp5';
mysql> quit

The output should look similar to this:

Creating a new database and assigning rights to it

This will create an 'erp5' database which can be accessed by MySQL user 'erp5@localhost' with password 'erp5' just like that:

Once we have database set up, Zope up and running and we're logged in as a manager user, we can install ERP5 site object to be able to use all the wonders of ERP5.

Main Zope Management Interfaces screen

While in the root manage page like the one on the screenshot above we should choose from the dropdown box an 'ERP5 Site' object. After that we are presented with the configuration page for the new ERP5 site. The only thing that should be reconfigured is the ERP5/MySQL connectivity settings. Here in all three fields we enter the name of the database, user of that database and his password.
In our case that would be: erp5 erp5 erp5
The database type should stay as an InnoDB.

The ERP5 creation dialog page

Finally we click the 'Create a new ERP5 instance' button and wait a bit for everything to set itself up.

If the process is successful we will be redirected to the front page of ERP5 site, just like the one on the screenshot below.

The ERP5 main page

Congratulations!

Enabling preferences

Before going further, enable default_site_preference by navigating to http://localhost:9080/erp5/default_site_preference and choosing Action...->Enable Preference from actionbox. Without enabling preference you might have cryptic messages (related to user interface - forms).

Validating portal rules

New simulation system in ERP5 need rules to be validated. Navigate to http://localhost:9080/erp5/portal_rules and validate every rule in that container, using rule's action box or mass validation action from container. Without validated rules many simulations won't be created, and builders won't be able to generate documents.

Adding packages

As you probably noticed, the screen is almost empty and there is nothing you can do, except to stare in admiration at the beautiful logo of ERP5. This is normal - it is because you created an empty site and haven't yet installed any packages - we call them "business templates" (see Business Templates for more).

Have a look at "Manage Business Templates" tool (accessible from "My favourites" dropdown in the top left corner) - you will see that you have only three templates: core, xhtml_style and mysql_innodb_catalog. These three are needed to make ERP5 running and are installed upon bootstrap.

To get started, install erp5_base first - it brings the most basic functionality, and anyway is required by all the other templates.

See Installation techniques for instructions how to download, install and upgrade your templates.

General Idea

Typical Business Template repository configuration

From developer point of view Business Template is a package which includes developer works with some metadata and functionality typical for packaging system: dependencies, provisions, scripts, installation/upgrade/uninstallation system. Developer is able to put almost any modification of ZODB into Business Template. There are some restrictions, but BT system is evolving all the time.

From consultant point of view Business Template is installable/upgradeable/uninstallable set of objects for which dependency will be computed automatically. Business Template file - ending with .bt5 extensions usually - could be compared to popular .rpm or .deb file format. Business Template system in ERP5 is like yum, rpmdrake or dselect.

Business Template files exists in some kind of repository - on http server, on local filesystem - with generated XML file bt5list. One ERP5 installation is able to be connected to many Business Template repositories; and of course developers are able to publish many types of repositories, e.g. development, testing or stable.

erp5_base

This bt5 installs three basic data types: Person, Organisation and Currency, and some auxiliary types. It also installs three modules:

  • person_module (Persons)
  • organisation_module (Organisations)
  • currency_module (Currencies)

It also installs some mechanism for processing basic information about people and organisations they might be working for.

Basic use case

We would like to record information about a company and one person who is working for this company.

Step 1 - create an Organisation

Go to the Organisations module, and select "Add Organisation" from the "Action" dropdown. A new form will appear. Fill it in with some data.

Note the "Contact" listbox at the bottom of the first tab ("View"). It is empty; if you enter an email and save the form, after a while the listbox will show "default_email" - it is an object of a type "Email", which contains the email address you've just entered. The way it works is that the "email" field on the Organisation's "View" tab is somehow linked to the "default_email" object. You can add more email addresses; if you'd like to change the default email, change the id of "default_email" to anything you like, and then change the id of the other email into "default_email". It works the same way for phone number, fax and address, and many other things.

If you want to record country or activity you have to go to portal_categories and create subcategory trees under the appropriate base categories (region and activity in this case)).

Step 2 - create a Person

Go to the person module, select "Add Person" from the "Action" dropdown. Fill in the person's name, email and other information.

Step 3 - employ the Person

Go to the person's "View" tab - there is a field labelled "Organisation", with a little gear next to it. This is called "Relation String Field". Click on the gear - you'll see a list of organisations you've created before. Tick one and click "Update Relation" button. Done - the person now works for this company. Now, next to the gear, you can see a little airplane - it takes you straight to the organisation the person is working for.

Look at the "Career" tab - there is a listbox "Career Steps", with one object labelled "default_career". This is an object of the type "Career", and it represents an employment contract; it is treated as current employment, because it's id is "default_career". You can edit the object; however, despite being the default, it is not active because it's status is "Draft" - this is a workflow state. To start the employment, select "Start Career Step" from the "Action" dropdown - the status will change, and the object will become read-only.

There is a shortcut for terminating the current employment and starting up a new one - go to the Person object and from the Action dropdown select "Terminate the current career step" - and see what happens.

Step 4 - make the person a user

To let the newly created person log into the system, you have to first create an Assignment for him (Action->Add Assignment), then open it (Action->Open). You don't even have to fill any data into the assignment, it just has to be there.

Then, go back to the person, select "Assignment" tab, give him a login and password, and you're done.

Caveat: if you use a bit older version of ERP5, you can skip the assignment part, but the Career tab has to say that the person's role is "internal", and login and password are on "Details" tab.

erp5_trade

This bt5 installs data types:

  • Internal Packing List
  • Internal Packing List Line
  • Purchase Order
  • Purchase Order
  • Purchase Packing List
  • Purchase Packing List Line
  • Sale Order
  • Sale Order Line
  • Sale Packing List
  • Sale Packing List Line
  • and many others

Most important modules provided by this business template are:

  • internal_packing_list_module (Internal Packing Lists)
  • sale_order_module (Sale Orders)
  • purchase_order_module (Purchase Orders)
  • sale_packing_list_module (Sale Packing Lists)
  • purchase_packing_list_module (Purchase Packing Lists)

Basic use case

Assumption: erp5_base, erp5_pdm and erp5_trade Business Templates properly installed.

Scenario description

We are ACME corp., John Smith is our sale and purchase manager. We want to purchase some goods from our supplier and then sell them to our customers.

System preparation

Create organisation ACME corp. in Organisations module, create John Smith in Persons. Also create EUR currency in Currencies.

Purchasing goods...

Go into Purchase Orders, create new Purchase Order.

...and selling them
  • instruct how to add erp5_base, erp5_trade and erp5_pdm from Nexedi's BT repository
  • basic use of installed BTses: add product, add companies, persons, add sale order, watch product movement history
  • invoke desire in reader to play with ERP5
  • clean up above - it is copy/pasted - need rearrangement

Chapter 3

Bits and pieces of user interface

Although based on a "thin client", ERP5 is a rich user interface which offers many functionalities. What is important is that the interface is uniform throughout the system, so if you know how to use Person module, you don't have to learn anything new when it comes to doing sales or accounting.

This section briefly describes various parts of user interface.

Module view

Module view is what you see when you enter something from the home page - module is meant for storing some "top-level" objects, so the only thing a module shows is a list of something (persons, organisations, sale orders or something else). Usually all the objects a module contains are of the same type, sometimes of a few similar types (e.g. Accounting Transactions show four or five types of transactions).

When you are in a module - assume it is Persons - you see something like this:

Let's examine every part of this screen.

Favourites

This dropdown list shows some options which are either user-specific or related to administration of the ERP Site; most of them are - or will be - covered in other parts of this handbook or on erp5 wiki, like:

Modules

This is basically a navigation aid - it lists all modules that are currently present in the system (and available for you to view), so that you don't have to go back to the site's main page to travel to another module.

Languages

This lists all translation packs that are currently installed, and allows you to change the user interface language whenever you feel like it.

Search box

It is a quick, site-wide search facility; may require some additional configuration to work properly.

Jump

Some modules or objects may define special "jump" actions, which bring up lists of object related in some way to the one you are currently looking at - e.g. if you have a CRM package, you'd be able to jump from a person to a list of all sale opportunities related to this person. On this picture, you have only one jump-list - to all queries that this person has posted in the system.

Action box

This is a dropdown that actually lets you do things in the system. It comprises three sub-lists of actions you may undertake:

Add
lists types of objects that can be added inside the module (or object) you are currently in; since we are in "Persons" module, the only thing that can be added here is a Person object.
Workflow
this list actions that are currently possible within a workflow which this object is in (will become more obvious when we are looking at an object, not a module)
Object
actions that are defined by the object itself.

Cut/copy/paste

These are standard actions that pertain to the objects shown on the list - if the listbox has checkboxes on the left and you select some objects, you can cut or copy, and then paste. There is nothing magic to it.

Print (optional)

This button may be present or absent, depending on whether the object defines some "object_print" actions. Usually it produces a pdf representation of what you currently have on your screen. It can be very handy when listbox is used, because you can filter and sort objects, show and hide columns, and then print the list as you see it.

New

When in a module, this button creates a new objects of the type which can be created within the module and shows it to you on the screen. If more than one type of objects can be created within the module it creates the first one (alphabetically). CAUTION: when you press this button, the object is created immediately and presented to you for editing. It is too late to cancel, the object is already there - if you change your mind, you have to go back and delete it.

Delete

Select some records, click this - you will see a confirmation dialog. This dialog will tell you if there are some other object related to the ones you are trying to delete. You can't delete an object if another objects has a "link" to it.

What happens when you confirm, depends on the implementation - objects can be either deleted, or moved to a "deleted" state.

Search button (optional)

Some modules define their own, dedicated search facilities (e.g. Accounting Transactions module), then this button appears. Clicking on it will bring up a search dialog.

Show all objects

If you had filtered the object in one way or another, this button will erase all filtering criteria you might have applied and show all records you can see in the current module.

Manual filtering

If you want the listbox to display only a few records selected manually by you, tick some checkboxes in the leftmost column and press this button.

Multi-column sorting

If you want to sort by one column, click on the column header (see below). If you want to do more elaborate sorting, like "first by this column, then by that one", use this button.

Exchange (optional)

Present if the module defines some "object_exchange" actions - usually there are things like: export data to CSV, generate dataset in spreadsheet format, import data from another application etc. If only one action is defined, it is launched immediately; if more than one, a selection dialog pops up. Can also produce a dialog asking for data input.

Report (optional)

Present if the module defines some "object_report" actions - like generating VAT transactions report, producing paysheet in MSWord format etc. If no report variables to specify exists it is launched immediately, otherwise it takes you to a dialog form on which you can choose report specific variables or limitations for report data. If more than one report is defined, a selection listbox appears on the dialog form.

Customize listbox

By default, listbox shows columns which were defined by the person who made the application. By using this tool, you can hide some columns and show other ones. Your settings will be seen only by you, and will be remembered even if you log out and in again.

Navigation breadcrumb

A standard web breadcrumb to show you where you are - some applications allow you to get fairly deep into the data structure. Also, allows you to go up as many steps as you want.

Listbox tools

Flat list mode

Brings you back to the standard, "flat" mode of a listbox (see Understanding listboxes for detailed explanation, and http://wiki.erp5.org/HowToConfigureListbox for technical information).

Tree list mode

Goes into a "tree" mode whereby you can browse the listbox data by category tree (see Understanding listboxes for detailed explanation, and http://wiki.erp5.org/HowToConfigureListbox for technical information).

List Action

In module, does nothing. In an object, usually goes to a "folder contents" view which would allow you to cut, copy, paste and delete items.

Page selector

Standard page selector, if listbox has more items that it is configured to display on one page.

Select/unselect all items

Quicky check/uncheck all items in the listbox.

Apply

Applies filters which you typed into search/filter boxes (see below) - basically, has the same effect as pressing enter while cursor is in one of these boxes.

Sort by column links

If the configuration says a column is sortable, clicking on the link will sort listbox contents by this column in an ascending order; click again to reverse sort order.

Search/filter boxes

If the configuration says a column is searchable, enter something into the box and press enter. Columns differ int the search mode they use - some search by partial matches (type "John" to find "Johnny Knoxville", some accept wildcards ("John%").

Item selection column

Select items for copy, cut, delete etc.

Object view

When you click on an object (a person, in this case), you enter a slightly different view, like this:

Basic things are the same, here we briefly describe what is different.

New object

It is similar to the "new" button on the module level, except that it always creates the same type of object like the one you are currently working on.

Listbox navigation buttons

If you entered the object by clicking on a link in a listbox (which is the most common way of accessing an object), these buttons allow you to move to previous, next, first and last item in that listbox; importantly, the listbox "remembers" any filtering and sorting you did, so you move only among the items you selected before and in the order you sorted them.

Up to the listbox

Takes you back to the listbox from which you came here (if you want to move up, you can also use breadcrumb, but the breadcrumb always takes you to the "view" tab, while this one takes you to the place whence you came.

Object tabs (or "views")

An object often has lots of properties (or attributes), far too many to present on one screen - then it defines many "views". The first - and default - one is always called "view"; also, every object has "history" and "metadata" tabs.

Working with object

Save button

Saves any changes you might have made to the object. Sometimes it is not there, if the object is read-only for some reason.

Status message

This is the place ERP5 tells you if the operation you tried to perform was successful, and if not, then why. In this case it says the object was successfully saved.

Basic fields

Text box

Just a text box, nothing special - type anything you like, press save.

Any field in an ERP5 form may be additionally equipped with a "validator" - in such a case if you enter an invalid value and try to save the field will tell you what was wrong.

Relation field

This field represents a "relation" of this object to some other object - in this case it says that this person works for that company. It has some very nice features:

  • if it is empty, the little gear will show a list of object you can make a relation to - pick one and save
  • if it has some value, the little airplane takes you straight to the related object (the "ERP5 Polska" company in this case)
  • if it is empty and you type something into it and press the gear, it will make a search and present a limited list of objects
  • if it is empty, you type something into it and press Enter or click Save, it will check how many matching objects there are - if only one, the system will immediately set the relation; if more than one, it will present a dropdown for you to choose which one did you have in mind.

Category dropdown

The category system (described elsewhere) lets you classify objects - here you can choose the region in which the person lives, from a tree-like category structure.

Listbox

This is a similar listbox to the one you've seen before in the module view; the main difference is that because it shows a more customized selection of objects, it does not have the "select column"; also, the "list action" is now usually meaningful - it brings you to another listbox displaying all objects "contained within" this person, and then you can copy, paste, delete etc.

Chapter 4

Usage

Installation techniques

See http://wiki.erp5.org/HowToInstallBusinessTemplates.

Difference between Install and Upgrade

If you have installed erp5_forge business template, and are a bleeding-edge type, you can from time to time update your system to the latest svn revision - see http://wiki.erp5.org/HowToUseERP5Subversion#update_from_svn.

Usually, the recommended way would be to first update the source code (by running svn_update.sh script), then update all bt5 starting from the more basic ones and on to the application-level, so it'd go more or less like:

  • erp5_core
  • erp5_xhtml_style
  • erp5_mysql_innodb_catalog
  • erp5_pdm
  • erp5_trade
  • ...

Creation

See http://wiki.erp5.org/HowToCreateBusinessTemplates

Generic Business Templates

erp5_rss_style

Capable of rendering ERP5 data in a format recognizable by RSS readers, very configurable. Can be used in hundreds of ways, for example:

  • sale manager can use a news ticker application to monitor new sale orders entered by his team
  • while checking your email you can immediately see what's new in document management system
  • someone working on a project can use his news reader to see new task being started or completed

See wiki HowToUseRSSStyle for usage and configuration information.

erp5_ical_style

Capable of rendering ERP5 data in an iCalendar format recognized by many calendaring programs (KOrganizer, Microsoft Exchange, Microsoft Outlook, Lotus Notes, Novell GroupWise and many others). Very configurable, can be used for scheduling, user notification, presentation of project time schedule, and many other ways.

See wiki HowToUseICalStyle for usage and configuration information.

Part II: Behind the User Interface

This part will introduce some important internal concepts of ERP5 - accessors, simulations, relations, used types, taken decisions in ERP5, and so on. It shall be more descriptive to ERP5 wiki - after reading this part reader shall be able to resolve simple problems, hack ERP5 with some understanding what's going on and ask good questions on ERP5 related mailing lists.

From form to API - first look behind the scenes

Management interface of a form

When you look at the ERP5 screen, what you see is a rendered form (ERP5 Form, which is based on a Formulator form). Its name is usually at the end of the URL (like "Person_viewCareer"); often, the URL ends with "/view", which means that you are looking at the default form of an object. If you see a number of tabs (like "View / Details / Career"), click on any of them and you will have the form name in the URL. If you are in a module and there is no tabs, things are a bit more difficult, we will come to that a bit later.

Once you have the form name, append "/manage_main" to it - now you are in a management screen, and you have a complete list of fields which are visible in on the form (and possibly some which are not visible).

We won't be talking in detail about editing a form - you can consult Formulator documentation for that. The purpose here is show how fields are filled with values, and how they interact with the object.

Property fields and API

Simple fields - those containing strings, numbers, or checkboxes with boolean values, are bound to object attributes by naming convention. When a field is rendered, it invokes an appropriate accessor to get an attribute value. This is why all controls begin with "my_" - a field:

my_title

invokes a method:

.getTitle

to get value of an attribute:

title

Most of the accessors are auto-generated (see "Magic of ERP5" to know more) - if a property "title" is defined, an object has the accessor, but you won't find it in the code (!). Sometimes accessors are overwritten - e.g. a Person object has a different .getTitle method. This one you can find in the code.

When a form is submitted, and you had changed value of a "title" field, the script which is being called by the form (usu. "Base_edit") invokes a setter:

.setTitle

which, not surprisingly, sets the title. Replace the form_name/manage_main with "/Base_viewDict" - you will see raw data of the object, and you will find your title.

That's almost all there is to it. There is a number of special fields for different types of attributes - there is a StringField, TextAreaField, IntField, FloatField, DateField, EmailField. These fields check if the value you've entered is appropriate.

Relation fields and API

A relation field (specifically, RelationStringField) has already been described in UI section. Basically, it follows the same principle as property fields. The difference is that in most cases a relation field used for relation

source

is called

my_source_title

so it invokes accessor:

.getSourceTitle

the result being that it displays a nice title of the related object, instead of its relative url (like "/organisation_module/12"). And conversely, when you fill it and submit a form, it uses the title to search for the appropriate object.

You can also apply the same convention to use other properties then title, e.g. you could create a field:

my_source_relative_url

which will display and use a relative url of a related object.

There is also a MultiRelationStringField, which is used to get/set a relation to many objects:

my_destination_title_list

uses

.getDestinationTitleList

and has a funny behaviour, which will be explained somewhere else.

Category membership fields and API

Some fields allow you to assign an object to certain categories (in other words, to use categories for classification). For example, you can set a product_line on a product, or nationality on a person. For this purpose, a ListField is used. It follows the same principle:

my_nationality

allows you to choose a nationality, and it assigns the person to a chosen subcategory of "nationality" base category.

The way to field such a control with values is to give it a list of tuples containing title and url of categories, like:

'', '', ['German', 'd'], ['British', 'en']...

This is most easily achieved through the category's API; most commonly used method are:

.getCategoryChildLogicalPathItemList
and
getCategoryChildCompactLogicalPathItemList

The latter different from the former in that if the path made of titles becomes too long, it tries to trim it in a reasonable way.

A MultiListField works the same way, only it allows for selecting many categories (by ctrl-clicking), and, obviously, uses a:

.get[category]List

accessor.

Category trees in listboxes

Part III: The magic of ERP5

Chapter 5

Plan:

  • what are simulations
  • where they are used
  • what are their purpose
  • follow Yo guidelines from erp5-dev thread
  • base on Shufla's "Introduction to simulation system" ("Wprowadzenie do systemu symulacji") presentation from 2nd ERP5DevCon, February 2008, Warsaw
  • ...

Proposed TOC:

Simulations purpose

Decision and prevision

Example user-level scenario

Purchase Order

Purchase Packing List

Taken actions

Decrease quantity and adopt prevision

Decrease quantity and accept decision

Decrease quantity and split and defer

Technical stuff

Applied Rule

Simulation Movement

Other tools used with simulations

Delivery Builder

Predicates


Chapter 6

Playing with security

Needless to say, security is crucial in most projects. And designing a tight yet flexible permission system could be a developer's nightmare.

Fortunately, ERP5 comes with extremely powerful security machinery. Unfortunately, it does not work out of the box and need to be customized.

5A Security model

ERP5's security model is based on roles. Roles are a Zope concept and are explained in the Zope documentation (Zope Book). Generally speaking, a role describes who the user is (e.g. accountant, clerk, officer), but not what he can do. That is defined by permissions (e.g. view permission, modify permission). For each document there is a role-to-permission mapping. The user with the accountant role can be allowed to access some documents, but not allowed to access others.

ERP5 extends Zope's concept and introduces the 5A Security Model, which provides a simple and consistent view of business security. 5A stands for the ERP5 roles of Author, Auditor, Assignor, Assignee and Associate. Each of these roles have a specific purpose:

Author can create new documents. He doesn't necessarily need to be able to view documents (he would probably be able to view his own documents, thanks to Zope's role of Owner).

Auditor is allowed to view documents.

Assignor can view, modify, delete and create documents, as well as assign other users to specified documents.

Assignee can work only on some documents from the module. For example, he can access only documents related to a specified region.

Associate can work on documents under certain conditions (e.g., he can view Organisations only if they are related to the Invoice documents he is responsible for).

Roles are described in: http://wiki.erp5.org/HowToDesignSecurity

How can one become a user?

When a user tries to log into the ERP5 site, the security machinery tries to find a Person (in a person_module) that has the value of the reference property (called "user name" on the Details tab on Person form) set to the login name of a user. If such a Person exists, has 'Internal' role and is Validated (see chapter about workflows), and the password given by the user matches the password of this Person, then the user is allowed to log in.

(Important — Starting from revision r15915, the Person doesn't need to have an 'Internal' role any longer. Instead, the Person must have at least one open Assignment.)

So to let somebody log into the ERP5 site, you must:

  • define a Person;
  • set reference property to user login name;
  • set password;
  • set Person's role to Internal (not needed in revisions later than r15915);
  • validate a person;
  • open an Assignment for that Person (from revision r15915).

Security machinery

The concept

Security is divided into two parts – user side security and object side security.

User side security defines security settings user has after successful logging in.

Object side security defines conditions that should be met by the user to obtain role in context of the given object.

In ERP5 almost everything is an object – modules, preferences, categories and so on. Every time the user tries to access an object, ERP5 does the following:

  • checks if the user security settings and object security settings allow to grant user a role or roles in context of this object;
  • finds permissions granted for those role(s);
  • allows or disallows access to the object.
How does it work?

When a user logs to the ERP5, the security categories are calculated for him. Those security categories are analogous to a set of keys (by "key" I mean a small metal object, not the key in the sense used in cryptography!). Back to the programming, categories are just a list of strings, for example: ['MA_CS','MA_CS_WA']

Each ERP5 object has also its security categories. Those categories can be considered as keyholes. Each category has the role associated to it. For instance: [('HR','Assignor'),('SD','Assignee'),('MA_CS_WA','Auditor')]

When a user has a key that matches a given keyhole, he gets the role "hidden" behind the keyhole. In the previous examples the user gets the Auditor role for the object, as he has (among others) MA_CS_WA security category, and the object has Auditor role associated with it.

As each object can have different security categories, user can obtain different roles for different objects. If another object has the following category: [('HR','Assignor'),('SD','Assignee'),('MA_CS_LD','Auditor')] the user from the first example will not get any role and thus will not be able to access the object.

The main question now is - how are security categories calculated? Well, it depends if we are talking about user side security settings or object side security settings.

User side security settings

User side security is based on portal categories (see the explanation of the category tool if you are not familiar with it). As we mentioned earlier (see " How can one become a user?" above), each logged user has the associated Person object, defined in person module (this is not true for special users like Zope, so the ERP5 security machinery will not work for them!). This Person belongs to some categories (directly off by acquisition from contained Careers or Assignments), like function, group or site.

If you take a look at the portal categories, you'll find that each category value could have a codification defined, that is, a short string identifying that value. Let's assume that category function can have (among others) value of "Manager", which has "MA" codification. Category group can have value of "Customer Service", which has "CS" codification.

If the user Person's function is "Manager" and group is "Customer Service", the security category for this user could be "MA" (codification of "Manager") and "CS" (codification of "Customer Service"), joined with an underscore: MA_CS. For another user, which has function of "Clerk" ("CL" codification) and group "Customer Service", the security category would be CL_CS.

The key question is: what categories are used for security calculations and how does it work?

The insides

So let's take the screwdriver, remove the front panel of the ERP5 security machinery, and have a look at the insides.

The central point in calculating user security settings is the Python script called: ERP5Type_getSecurityCategoryMapping, which defines which scripts and which base categories would be used for security calculations. This script should return a tuple:

((e1),(e2),...,(en))

Each element of this tuple is also a tuple: (script_name, cat_list) where script is the name of the script that will be used to calculate security category, while cat_list a list of base categories that will be passed to this script as one of its parameters (rest of them will be discussed later). So if ERP5Type_getSecurityCategoryMapping returns: (('script1', ['function']),('script2',['function','group'])) then first script1 would be called with ['function'] then script2 would be called with ['function','group'].

What do those scripts do? They examine user's Person object, get values for specified categories and return them as a list of dicts. In previous example, script1 should get the function category value id, while script2 should get the function and group categories value ids. So for Person being Manager in Customer Service, script1 would probably return: [{'function':'manager'}] while script2 would return: [{'function':'manager'},{'group','customer_service'}].

One thing should be explained – why the scripts return list of dicts instead of a single dict? This is because some categories could be defined in objects contained in Person object, e.g. Assignments, and user could have several open Assignments, which results in multiple values for the given category.

What do those scripts look like? They should take the following arguments:

  • base_category_list: this was discussed earlier.
  • user_name: name (login) of a logged user,
  • object: generally not used here;
  • portal_type: the portal type of the object (not used here either).

ERP5Type_getSecurityCategoryMapping should be provided by the developer and be placed somewhere in portal skins. If there is no such script, the system behaves as if the script exists and returns the following tuple:

(('ERP5Type_getSecurityCategoryFromAssignment',
     self.getPortalAssignmentBaseCategoryList() ),)

which results in calling ERP5Type_getSecurityCategoryFromAssignment with a base_category_list parameter got from call to getPortalAssignmentBaseCategoryList(), which currently is: ('function', 'group', 'site')

The ERP5Type_getSecurityCategoryFromAssignment calculates security mappings from all open Assignments of the logged users Person object.

An (almost) real case example

Let's imagine there is an energy selling company that is spanned across multiple regions. The company has Customer Service department. Regional Managers of Customer Service should be able to access connection documents of end customers from their respective regions, but shouldn't be able to access documents of end customers from other regions. The region is stored as site category.

Assume that user jacek is a Manager. He has two open assignments – for the Warsaw and the Pruszkow regions. The first of these assignments has the following settings:

function: manager
group: customer_service
site: warsaw

while the second has the following settings:

function: manager
group: customer_service
site: pruszkow

Note: Having a manager with two assignments for two different regions is probably not very common for such companies. However, I want to show that even such uncommon needs could be easily fulfilled in ERP5.

The ERP5Type_getSecurityCategoryFromAssignment will return the following list of dicts for user jacek:

[{'function': 'manager', 'group': 'customer_service', 'site': 'warsaw'},
 {'function': 'manager', 'group': 'customer_service', 'site': 'pruszkow'}]

The user bartek is a manager in the Siedlce region. He has the following assignment:

function: manager
group: customer_service
site: siedlce

so the script returns for him:

[{'function': 'manager', 'group': 'customer_service', 'site': 'siedlce'},]

But what about the string representation of the security categories I've mentioned at the beginning of this chapter? For that, a codification is used. Let's imagine that: function/manager has the codification MA

group/production has the codification CS

site/warsaw has the codification WA

site/pruszkow has the codification PRS

and

site/siedlce has the codification SL

After obtaining list of dict, ERP5 security machinery for each dict:

  • sorts keys alphabetically;
  • replaces category value id by its codification;
  • joins all codifications in one string, separated by underscores;

So for user jacek and first dict, the codification would be: MA_CS_WA while for the second: MA_CS_PRS

And jacek finally gets the following mappings: ['MA_CS_WA','MA_CS_PRS']

User bartek gets : ['MA_CS_SL']

Note: If the codification is not defined for a given category, the category's id is taken. However, it is good practice to define codifications for categories used in security.

These security settings would be then used by ERP5 to control access to objects. It will be explained in next chapter.

Object side security settings

Object security settings (roles settings) are defined on Portal Type basis (if you are not familiar with Portal Types, read here). Those setting are "keyholes" that allows the keys owners to get access to specified roles.

Roles may be calculated either statically or dynamically. Unfortunately, there is no apparent difference between static and dynamic roles calculation, as both are defined in the same form. We well discuss that difference later.

To define security settings for the portal type, you should navigate to its management form and click the "Roles" tab.

<picture pending – role definition form>

In the Name field you can put a name of the setting. (it is NOT the role name). In practice, a short description is often put here. This is informational only.

In the Role field you can set a name of the role that would be granted to the user whose "key" matches this "keyhole" (that is, the user that has proper security category).

In the Description field you can set a more detailed description of the setting. This is informational only.

In the Condition field you can set a condition that should be fulfilled in order to apply the settings (it could be a Python script call, for instance).

In the Base Category field you can set space-separated list of names of base categories that would be used for role calculation.

In the Base Category Script field you can set the name of the Python script that would be called if dynamic role calculation method is used. If the static role calculation is used, the script is not called and the field value has no meaning.

In Category text area you can set a list of category values ids that would be used for role calculation. Each category value id should be put ion a separate line.

Static vs. dynamic

If, for each base category name defined in Base Category field, there is a matching definition in Category text area, the calculation is static, that is, the Base Category Script is not called. If there are base category names for whom there are no matching definition in Category text area, the calculation is dynamic, that is, the script would be called and its return value would be used for the missing definitions.

How does it work?

Static calculation is really simple – a mapping is created based on category values. If Base Category field contains function group and Category text area contains:

function/sale_manager
group/customer_service

then calculated mapping would be MA_CS, providing that codifications are the same as in previous examples. Any user that has MA_CS security category would be granted role for the object.

However, dynamic calculation is more difficult. If there are more entries in the Base Category field than category values in Category text area, then the script defined in Base Category Script field would be called for the missing categories.

The script gets following parameters:

  • base_category_list: a list of categories defined in Base Category field.
  • user_name: name (login) of a logged user,
  • object: object for which the role setting is calculated,
  • portal_type: the portal type of the object.

Script should return a list of dicts, just like scripts for user-side security calculation do (in fact, in some situations those can be the same scripts). Each dict contains names of categories from base_category_list and their respective value ids.

What should those scripts do? It's up to the developer.

Back to the (almost) real case example

In our example we wanted to restrict access to customer connection parameters only to managers in charge of the specified region (i.e. region in which the customer lives). Connection parameters are stored in objects of portal type Connection Parameters. This object is linked to the Person object (representing the end customer) by the source relation. The Person contains Address object, which in turn has city property.

Let's navigate to Connection Parameters management form, select Role tab and fill the form:

  • In the Name field put short description, e.g. Customer Service Management People.
  • In the Role field a name of the role to be granted to the user, e.g. Assignor;
  • In the Description field put description of the setting, e.g. Customer Management People should have Assignor access to all Connection Parameters for customers living in their region.
  • Leave the Condition field empty.
  • In the Base Category field put space-separated list of names of base categories: "function group site".
  • In the Base Category Script field put the name of the Python script. Let's name the script ConnectionParameters_getSecurityCategoryFromCustomerAddress, to follow ERP5 naming convention.
  • In Category text area put a list of category values ids:
function/manager
group/customer_service

(You should put each category value id in separate line) It can be easily seen, that we have three base categories defined, but only two category value ids. So for the missing category (site) the ConnectionParameters_getSecurityCategoryFromCustomerAddress script would be used.

The script should examine the Connection Parameters object, get linked Person object, get its default address city, calculate the region from the city name (it can have city-to-region mapping defined in categories; or call external GIS system; or use crystal ball), then return the appropriate dictionary list.

This script could be similar to the following one:

if portal_type != 'Connection Parameters':
 raise RuntimeError, 'Error: Script called for invalid portal type'

customer = object.getSourceValue()
city = customer.getDefaultAddressCity()
region = context.ERP5Site_GetRegionFromCity()  #guess the region somehow
category_dict = {}

for base_category in base_category_list:
  if base_category == 'site':
    category_dict[base_category]=region

For customer living in city in Pruszkow region the script should then return: [{'site':'pruszkow'}]

The rest of the mapping would be calculated statically – function/manager maps to MA, group/customer_service maps to CS, and as site/pruszkow maps to PRS, the final mapping would be MA_CS_PRS. Any user that have such security category (that is, a Manager of Customer Service in charge of Pruszków region) would be granted Assignor role for the document.

And what about documents related to more than one customer, possibly living in different regions? No problem, this just needs a small modification. The script should examine the list of Persons related to the document and return a list of dicts – one dict for one customer. So if the document is related to two customers – one in Pruszkow region and one in Jeziorna region, the return value would be as follows: [{'site':'pruszkow'},{'site':'jeziorna'}] and finally the document gets following mappings 'MA_CS_PRS','MA_CS_JEZ'


Extending the defaults

Let's assume there is a class of documents (say connection standards, portal type Connection Standard) that should be available to all managers, regardless of the region they are responsible for. How to achieve this? The first idea would be to write a Base Category Script for Connection Standard portal type so that it returns all possible mappings for all regions: MA_CS_PRS, MA_CS_WA, MA_CS_SL,... and so on. Well, if the company has twenty regions, there would be twenty different mappings. Quite a lot, huh? Worse, if the company grows and new regions appears, security settings for all documents would have to be redefined.

Better idea is to define mapping without the region code, that is MA_CS. Documents with this mapping would be accessible for all Customer Service Managers... or not?

Well, not exactly, as no manager would got MA_CS security category! So there is a need to modify the default ERP5 security machinery a little bit.

To do this, you must place the ERP5Type_getSecurityCategoryMapping script somewhere in skins. The script should look as follows:

return
(('ERP5Type_getSecurityCategoryFromAssignment', ['function','group','site']),
 ('ERP5Type_getSecurityCategoryFromAssignment', ['function','group']))

The first line looks similar to the system default (I replaced getPortalAssignmentBaseCategoryList() with explicit list of base categories), the second is new. Now, when user logs in, the ERP5Type_getSecurityCategoryFromAssignment would be called twice – once with ['function','group','site'], and once with ['function','group'] only. This second call produces MA_CS for any 'Customer Service Manager regardless of the region.

For the Connection Standard portal type we should define the following role definition (only relevant fields shown)

  • In the Role field: Assignor;
  • In the Base Category field: function group.
  • In Category text area:
function/manager
group/customer_service

This would produce mapping MA_CS, so all users with MA_CS security category would be given Assignor role.

Roles are NOT permissions

Well, at this point you may think that all that should be done has been done, but if you do, you are wrong. You have not defined the roles-to-permissions mapping yet.

What-to-what mapping? - you may ask. Well, despite their names, roles don't tell anything about privileges associated with them. There is nothing magical in the words Auditor or Assignor and ERP5 does not know by itself what those roles are allowed to do.

(This is true even for a Zope role of Manager! In many systems a Manager (or whatever he is called) is a mighty sheriff which can do everything. Not in ERP5, though. It is you who decide what permissions each role have. Even a Manager would have only as much power as you would give to him. You can define Managers without any permissions at all if you like to, thought it is rather a poor idea. However, you can easily grant a Manager insufficient privileges by mistake, and in such case you will find yourself in heavy troubles during development.)

How to define permissions for roles? It can be done either statically or dynamically.

Static permissions definition

This applies for objects that exists during the development time. They are mainly modules. To define permissions for such object, navigate to this object's management page and go to the Security tab. Read Zope documentation for details.

Dynamic permissions definition

This is the moment workflows enter the scene. As you probably know (and if you don't, read the section about workflows), each portal type can be assigned to one or more workflows. Objects (instances) of this portal type can be therefore in some workflow states. Each workflow state defines separate roles-to-permissions mapping. Object entering specific workflow state gets role-to-permission mapping defined for this workflow state.

This allows for a very flexible privileges manipulation. For instance, a newly created Connection Parameters document should be accessible only by its creator, so the draft state defines view and modify permissions for Owner only. After the document is completed, it can be submitted. In this state it can become readable to Assignees and Auditors and readable/writable to Assignors. Then the document goes through the rest of the workflow and finally ends in an archived state, where nobody can change it, but many can read.

To enable workflow-based security, navigate to the workflow management page, click the Permissions tab and add required permissions. At least the following permissions should be managed by workflow: View and Access content information (read), Modify portal content (write) and Add portal content (create new objects).

To define role-to-permission mapping for a workflow state, navigate to the workflow state management page and click the Permissions tab. You will see only permissions managed by this workflow.


Updating security settings

Security settings on objects are not updated automatically. This is developer's responsibility to update security settings after object state changes.

One way to achieve this is a separate interaction workflow, which have interactions defined for setters of properties that takes part in security calculation (in our "Almost real case example" the Person's Address city name is an example of such property – change of the city name can result in security settings change for related Connection Parameters documents, if the new city is in the different region then the old one). The interaction should fire a script that examines all related objects and recalculates security settings for them.

To recalculate security settings on object, call updateLocalRolesOnSecurityGroups() in context of that object. Then, reindex the object (this is necessary, as object permissions are stored in portal catalog -> see the explanation of catalog tool).

Debugging security

<to be written>

Chapter 7

ERP5 Handbook/Magic Accessors

Part IV: Become a good developer

Chapter 8

ERP5 Handbook/Comprehensive example of simple ERP5 implementation

Chapter 9

ERP5 Handbook/Indirect interactions between system components

Chapter 10

ERP5 Handbook/Understanding, testing and analysing impact of your changes

Chapter 11

ERP5 Handbook/Python debugger

Chapter 12

ERP5 Handbook/Deep view into unit tests

Part V: Become a happy user

Understanding listboxes

Example data table

Reference Title Start Date Simulation State
001 Sale Order 2007/10/11 Draft
002 Purchase Order 2006/10/11 Confirmed
003 Sale Invoice Transaction 2006/10/11 Planned
004 Production Order 2011/12/12 Planned

Listbox filtering

Take a look on above table and try to remember it. Above data will be used to explain some nice types of lixtbox filtering.

Simple filtering

You may filter by using full values of given columns. If you'd type Sale Invoice Transaction in Portal Type column then only object 003 would be shown.

% sign may be used as part of word. If you'd type Sale% in Portal Type column, then objects 001 and 003 would be shown.

Using this types of filtering - which may apply on any columns and types is almost enough.

Complex filtering

Date ranges

You may use two operators to define date range - >= which is mean after this date, including it and <= - before this date, including it. When Start Date would be set to >= 2007/10/11 then objects 001 and 004 would be shown. When it'd set to <=2006/10/11 objects 002 and 003 would be shown.

Not operator

If you'd type !=Draft in Simulation State column, then objects 002, 003 and 004 would be shown. Note, that you might not have any space after not operator != - != Draft won't work.

Domain Tree

If the listbox has a domain root defined, it will display this icon - when you click on it, the listbox will enter a "domain tree mode". Then you can select a base category from the dropdown that appears to the left of the listbox.

When you select a base category (like Region), the listbox will present an expandable tree of all regions that are defined in the system. When you click on any of them, the listbox will show only these people that live in this region (or in any sub-region). Here, we selected Europe/Poland/Mazowieckie region, and we see everyone who lives in Siedlce or Warszawa.

TODO: show accounting listbox with count/sum 
feature in domain tree mode
TODO: Report tree ???

Refer to http://wiki.erp5.org/HowToConfigureListbox for technical details about listbox configuration.

Appendix A: Reference documentation

Generic description about ERP5 Specific Zope tools needs to be here.

portal_activities

The idea of portal activities (aka CMF Activity Tool) is described in section:

Background process invocation - CMFActivity system

The way to use it is well described on the wiki:

http://wiki.erp5.org/HowToUseTheCmfActivityTool

The is little to add here, then.

portal_catalog

Used to index objects, relations between objects, security information and some other frequently used data, to allow fast access, searching and sorting.

An object is recorded in catalog when you call .reindexObject on it. This method is called automatically upon every edit (technically, every setter - a method setThisProperty - triggers a reindex; if you write a script which is going to set many properties, better use _setThisProperty which does not reindex, and then call reindexObject; or even better call edit(property1 = value, property2 = value2) which reindexes once after setting all given properties).

Basic usage of portal_catalog is described here:

http://wiki.erp5.org/HowToSearchPortalCatalog

TODO: advanced usage (I do not know enough...)

It is almost never needed to tweak catalog while implementing ERP5; some tricks are explained here:

http://wiki.erp5.org/HowToCreateRelatedKeys

http://wiki.erp5.org/HowToAddTableToCatalog

TODO: check if related keys are not deprecated

portal_categories

The idea and use of categories is described in:

Categories

Base categories can be added with no restrictions (although it is always advisable to think for a moment, maybe one of the existing categories can do the job). Categories are indexed in MySQL; importantly, category memberships and relations between objects are also indexed, so the data model can be extended with little overhead.

Base category can be assigned to a portal type through property sheets, or simply through ZMI in portal_types tool. If an object has a given base category, it has all auto-generated accessors (setXXX, getXXX, setXXXList, getXXXlist).

Categories have a rich API; most heavily used methods are:

.getCategoryChildLogicalPathItemList

returns all subcategories recursively as pairs, suitable for filling a dropdown or ListField;

.getCategoryChildTranslatedLogicalPathItemList

same, but translated;

.getCategoryMemberValueList

returns all object which are classified to this category, or any of its direct or indirect subcategories (this includes subcatories themselves, but you can give it portal_type argument).

From the other end, every ERP5 object (a Person, for instance) has a method

.isMemberOf

which returns True if the object belongs to the given category OR to any of its direct or indirect subcategories. For example, if a Person has a function: "sales/retail/specialist", then

.isMemberOf("function/sales") == True.

Base category has a rich user interface with many cryptic options, most of which refer to programmable acquisition which is explained here: http://wiki.erp5.org/HowToUseProgrammableAcquisition

portal_contributions

This is a versatile tool which can devour (or ingest, if you prefer) almost anything you throw into it, guess what it is, find the right place to put it, analyze it and set various attributes of it.

More specifically: you call portal_contributions.newContent method, giving it some data (an uploaded file, for instance) or a url, optionally many other things (see the method's docstring, it is quite good). The tool then:

  • uses WebDAV machinery to find out portal type for the content (it uses content_type_registry, so this is the place to set it up)
  • calls ZMI scripts:
    • [Type]_getPropertyDictFromFilename
    • [Type]_getPropertyDictFromContent

to find out properties of the object, and if it gets any, sets them on the object; the scripts are type-based, so e.g. if the object is qualified as Spreadsheet, the tool looks for a script named "Spreadsheet_getPropertyDictFromFilename" and if not found, calls a generic one "Document_getPropertyDictFromFilename".

These scripts should return dicts of properties derived from file name and content; they can also return portal type, and this one will be eventually applied, so you can encode the content's type in its filename.

  • finds out the right module to place the content in
  • places the content in the right module

Contribution tool is used mostly by DMS module to ingest documents uploaded through web interface, sent in by email, or drag&dropped through WebDAV. In the nearest future it may be used also to receive and ingest emails.

portal_rules

Generic description about portal_rules needs to be here.

Invoice Transaction Rule

This rule is used by a builder to create Accounting Transaction Line after confirming Sale Invoice Transaction. You need to create a matrix of rules, which will be used to generate predefined Accounting Transaction Line.

If you need to define accounting system, this rule is what you need. Its definition will create proper accounting movements, based on predicates.

Begin in portal rules tool create new Invoice Transaction Rule, give it an Id and follow steps below for example based explanation.

Setting Predicates

After adding predicate you will be presented with a predicate screen. Set descriptive Title, which will be used as matrix column or row header. After setting Membership Criteria you will be able to set some Membership Values.

Predicates are grouped by a common Dimension, so set it carefully.

Keep in mind, that predicates may be constructed for some type of objects. In case of accounting you might want to create separate predicates for Sale and Purchase. To achieve it fill Test Method ID field with Movement_explanationPortalTypeIsPurchase for purchase patch and Movement_explanationPortalTypeIsSale for sale path.

When your matrix is ready, you can go and edit a template for Accounting Transaction Line. To test it, confirm Sale Invoice Transaction which is in planned state and observe how Accounting Transaction Line objects are created and filled.

Do not forget to fill Source and Destination views with proper accounts. Until then, system won't be able to generate proper simulations.

Full example

This example is taken for real world situation - traders in Poland. Requirement is to have defined region category, at least 3 different regions - Poland, Europe Union and Rest of The World. Example region tree is:

  • region/africa
  • region/asia
  • region/europe
  • region/europe/eu
  • region/europe/eu/bg
  • region/europe/eu/de
  • region/europe/eu/fr
  • region/europe/eu/ie
  • region/europe/eu/pl (yes, it is Poland)
  • region/europe/eu/uk
  • region/europe/non-eu/ua
  • region/north_america
  • region/south_america

Create Predicates in your Invoice Transaction Rule:

  1. for purchase from Poland
    • title: Purchase from Poland
    • Dimension: region
    • Test method ID: Movement_explanationPortalTypeIsPurchase
    • Membership Criteria: source_region
    • Membership Values: only source_region/europe/eu/pl
  2. for purchase from Europe Union
    • title: Import from the Europe Union
    • Dimension: region
    • Test method ID: Movement_explanationPortalTypeIsPurchase
    • Membership Criteria: source_region
    • Membership Values: everything what is in source_region/europe/eu without source_region/europe/eu/pl and without source_region/europe/eu
  3. for purchase from rest of the world
    • title: Import from outside of the Europe Union
    • Dimension: region
    • Test method ID: Movement_explanationPortalTypeIsPurchase
    • Membership Criteria: source_region
    • Membership Values: everything in source_region without source_region/europe/eu and below
  4. for sale into Poland
    • title: Sale to Poland
    • Dimension: region
    • Test method ID: Movement_explanationPortalTypeIsSale
    • Membership Criteria: destination_region
    • Membership Values: destination_region/europe/eu/poland
  5. for sale to Europe Union
    • title: Export to the Europe Union
    • Dimension: region
    • Test method ID: Movement_explanationPortalTypeIsSale
    • Membership Criteria: destination_region
    • Membership Values: everything what is in destination_region/europe/eu without destination_region/europe/eu/pl and without destination_region/europe/eu
  6. for sale to rest of the world
    • title: Export to outside of the Europe Union
    • Dimension: region
    • Test method ID: Movement_explanationPortalTypeIsSale
    • Membership Criteria: destination_region
    • Membership Values: everything in destination_region without destination_region/europe/eu and below

Now play with created Accounting Rule Cell, then create some orders - sale and purchase, expand them (by ordering or planning) and check for simulations (e.g. by using Base_viewSimulationTree). Of course you may go further and create some invoices.

Beware: above configuration is for example purpose only. ERP5 Handbook/ERP5 Products

Appendix B: Products' functions index

Appendix C: ZODB's functions index

Appendix D: About this book

ERP5 Handbook/Rationale

ERP5's wiki lives on http://www.erp5.org/

Authors

Dear authors:

  • handbook shall be readable from chapter to chapter
  • do not go into details to fast, refer to wiki
  • be more descriptive than technical - technical information shall be on wiki/in code
  • better explain something few times with examples, short and technical explanation style shall be in wiki - handbook shall prepare reader to wiki-like documentation
  • you are kindly asked to add yourself to authors page.

What to put in handbook and what on wiki

HandBook

  • descriptive information and introductory content about ERP5
  • complete tutorial-like documents
  • group links to ERP5 wiki with descriptions - readers shall be lead
  • might be less precise, little inadequate - concentrate on what reader shall understand and not on details - this is wiki work

Wiki

  • everything what is ERP5's wiki like - look how wiki looks right now
  • various HowTos, Technical Notes, etc.

Handbook and wiki synchronisation

There is possibility that some information will start to duplicate on wiki and handbook. Then some decision shall be made - if it is on wiki, and is not so technical, propose to move it into handbook. If it is on handbook and it is to technical - create/reference to proper wiki page.

Decision shall be made by humans.

TODOs

Put here list of extensions, which you'd like to see in book. Sign yourself with 4 tildes.

Generic

  • automatic documentation reference generator, at least parts which are fetch able from source-code
  • maybe use of DocBook system or its derivative instead of wikibooks?

Wikibooks extensions

  • automatic TOC generation

Further Reading

GNU Free Documentation License

Version 1.3, 3 November 2008 Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. <http://fsf.org/>

Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

0. PREAMBLE

The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others.

This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software.

We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.

1. APPLICABILITY AND DEFINITIONS

This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law.

A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language.

A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them.

The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none.

The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words.

A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not "Transparent" is called "Opaque".

Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only.

The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text.

The "publisher" means any person or entity that distributes copies of the Document to the public.

A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorsements", or "History".) To "Preserve the Title" of such a section when you modify the Document means that it remains a section "Entitled XYZ" according to this definition.

The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License.

2. VERBATIM COPYING

You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3.

You may also lend copies, under the same conditions stated above, and you may publicly display copies.

3. COPYING IN QUANTITY

If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects.

If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.

If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public.

It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.

4. MODIFICATIONS

You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:

  1. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission.
  2. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement.
  3. State on the Title page the name of the publisher of the Modified Version, as the publisher.
  4. Preserve all the copyright notices of the Document.
  5. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices.
  6. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below.
  7. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice.
  8. Include an unaltered copy of this License.
  9. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence.
  10. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission.
  11. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein.
  12. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles.
  13. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified version.
  14. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section.
  15. Preserve any Warranty Disclaimers.

If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles.

You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties—for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard.

You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.

The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.

5. COMBINING DOCUMENTS

You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers.

The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.

In the combination, you must combine any sections Entitled "History" in the various original documents, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements".

6. COLLECTIONS OF DOCUMENTS

You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects.

You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.

7. AGGREGATION WITH INDEPENDENT WORKS

A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document.

If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate.

8. TRANSLATION

Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail.

If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title.

9. TERMINATION

You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, or distribute it is void, and will automatically terminate your rights under this License.

However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.

Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.

Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it.

10. FUTURE REVISIONS OF THIS LICENSE

The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/.

Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. If the Document specifies that a proxy can decide which future versions of this License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Document.

11. RELICENSING

"Massive Multiauthor Collaboration Site" (or "MMC Site") means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. A public wiki that anybody can edit is an example of such a server. A "Massive Multiauthor Collaboration" (or "MMC") contained in the site means any set of copyrightable works thus published on the MMC site.

"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 license published by Creative Commons Corporation, a not-for-profit corporation with a principal place of business in San Francisco, California, as well as future copyleft versions of that license published by that same organization.

"Incorporate" means to publish or republish a Document, in whole or in part, as part of another Document.

An MMC is "eligible for relicensing" if it is licensed under this License, and if all works that were first published under this License somewhere other than this MMC, and subsequently incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections, and (2) were thus incorporated prior to November 1, 2008.

The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing.

How to use this License for your documents

To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page:

Copyright (c) YEAR YOUR NAME.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".

If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the "with...Texts." line with this:

with the Invariant Sections being LIST THEIR TITLES, with the
Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.

If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation.

If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.