Module CustomFields Cases

This page lists a compilation of concrete, practical examples uses of CustomFields and of its various features.

If you had an experience with CustomFields, you can also add here your case as an example for others to get inspired.

= How to make a generic PDF template listing all custom fields =

To make a generic PDF template listing all custom fields, you just need to take an existing PDF template, then you need to follow these 3 steps:

1/ Edit the class name (required, else it will conflict with the original template).

Eg: if we take the crabe template for invoices, we change:

into:

2/ Copy this generic function at the end of the PDF:

Alternative function (with a bit less functionalities, but more controllable):

3/ Call the _pagecustomfields function at the right place (generally, after _pagefoot and just before $pdf->Close):

Then go to the module's admin panel (eg: invoice admin panel) and enable the template you've just created.

You can now use it to test if your customfields work.

= Conditions on fields selection =

Sometimes you may want to show a DropdownBox or Constraint (or another multi-choice type), but you may want to show or hide choices based on conditions (eg: only if it's a prospect, only if this zone was selected, only if this category was selected, etc..).

To know which is the best solution you should choose to implement your condition, you should first know in which category your condition falls in.

Conditions categories
Conditions can be categorized into 4 types:


 * static condition: choices are restrained on a condition that never changes (eg: only show third-parties that are suppliers, or lowercase all data on sql insertion, or check that a field is above a certain number, etc.).
 * semi-dynamic condition: choices that are constrained on a static table but based on the value of another field/customfield.
 * dynamic: everything is dynamic: choices are based on a subfield of a field of the current module, so that there's no material table and it's impossible to create a view (because you would need to create one view per id) (eg: show only the contacts attached to the third-party being accessed)
 * timed condition: a condition that is based on time or recurrence (eg: at 5:00 AM delete old records, etc..)

Conditions solutions
Now that you know what kind of condition you want to set, you can choose one of the following solutions depending on your preferences and knowledge.

In any case, you can always use the CustomFields's overload functions to fit your needs for nearly every type of condition.

Static condition
WARNING: foreign keys (and thus constraints) can't be used on views with MySQL, and materialized views neither exist, so you can't use this method with MySQL.
 * View: create a view on the table based on the condition, and then create a custom field constrained on this view (which is just like any table), eg: only show third-parties that are suppliers:
 * Check
 * Trigger
 * SQL Transformations
 * CustomFields's overload functions

Semi-dynamic condition

 * View
 * Check
 * Trigger
 * CustomFields's overload functions

Dynamic condition

 * CustomFields's overload functions
 * Making your own module, which calls the CustomFields class

Timed condition

 * SQL scheduled events
 * Cron job
 * CustomFields's overload functions

= Overloading functions =

Here are a few concrete use cases of overloading functions to achieve various goals.

Dynamic list selection based on another one
The goal is to show two custom fields on the Third-Party module: one which gives the zone (secteur) of the third-party (Isere, Alpes du sud, Haute-Savoie...) and the other which gives relative to the zone the list of all the ski resorts (station_a) inside the selected zone.

We have one table llx_k_station (rowid, station (char50), secteur(char50)) which contains the following: 1,les 2 alpes,isère 2,chamrousse,isère 3,alpe d'huez,isère 4,vars,alpes du sud 5,risoul,alpes du sud etc...

In CustomFields's admin panel, we create two custom fields:

1- secteur: returns the list of all zones - type DropdownBox: enum('- Aucun','Alpes du Sud','export','Haute-Savoie','Isère', etc...)

2- station_a: returns the list of all ski resorts - type constraint on llx_k_station

Here is the code to put in customfields_fields_extend.lib.php that will allow to show only the ski resorts corresponding to the selected zone:

Thank's to manub for giving this case.

Dynamic discount computation per products lines on propales
The goal here is to compute the discount for a product line in propales based on a computation on three custom fields.

First, create three custom fields for "Line commercial proposals": vl, cpl and lc.

Then add the following overloading function at the end of your customfields_fields_extend.lib.php file (read the comments for more informations):

= Linking Dolibarr objects from two different modules =

Dolibarr sometimes offers the possibility to link two different modules. Eg: when you convert an Intervention card into an Invoice.

In this case, you might want in your templates to fetch the custom fields of the linked object. Eg: you generate a PDF from the Invoice, but you want to get the custom fields from the Intervention that was converted into the Invoice.

The key here is to use the llx_element_element table or the llx_element_* tables (eg: llx_element_contact): this is a standard Dolibarr table that stores all links between objects of two different modules.

Here is the structure: rowid | fk_source | sourcetype | fk_target | targettype --- 1 | 2 | fichinter | 5 | facture

You can then use a php code like the following to populate your $object with customfields:

Thank's to netassopro for the tip.

= Modify the total price of every product/service line with a coefficient (without tampering the discount) =

Here we will go through the creation and management of a custom field called coefficient that will change the total price of each product by modifying it by the coefficient.

The preliminary and necessary step is to first create a custom field that will be used to modify the total price. We will create one for Client Invoice Lines.

Go to the CustomFields administration panel, then into the Client Invoice Lines tab, then click on the button New Field, name the field coefficient, and set the type to Double.

When you go to client invoices in Dolibarr, you should then see something similar to this: You can see that our coefficient field was successfully created.

Then here are two alternative ways of implementing the change of the total price of each product relativery to this coefficient.

Change total price in database
Here we will use a "save" overloading function to change the total price directly in the database, thus we won't have to modify anything else (eg: in PDT or ODT) since the total price will be already updated in the database.

Warning: this method will work only with CustomFields => 3.2.23 since the "save" overloading function did not work for products lines before.

Just add the following overloading function in your customfields_fields_extend.lib.php file:

This should show the correct total price on the Dolibarr's interface without modifying the unit subprice (P.U. Unit):



You have nothing to edit in your PDF or ODT template, since the new subprice with applied coefficient will be automatically printed instead of the old one without coefficient.

Change printed total price per product without tampering the subprice in the database
Here is a way to change the printed total price (the one shown on screen and in PDF/ODT) but without changing the total price in the database.

The following sub-chapters are all independent, thus you can only follow the ones that you require, eg: if you only need to change the price in your PDF documents, just create a custom field then jump to the sub-chapter to Implement the change of price in PDF.

Implementing the change of price in ODT templates
There's no eval implementation currently inside ODT templates, but there is a kind of hook implementation, called substitution functions.

You can either create your own module, then create your own substitution function, but for the sake of simplicity in this tutorial, we will directly use the CustomFields substitution function. However, please remember that you will have to redo your changes everytime you will update the CustomFields module, so if you don't want to do that it would be better if you create your own module and substitution function.

Open the file htdocs/customfields/core/substitutions/functions_customfields.lib.php and go to the function customfields_completesubstitutionarray_lines.

At the very end of this function, but inside the customfields check:

But just before the ending bracket, you should add the following code:

This code will add a new tag {line_price_full} that you can then use inside your ODT templates.

Just place this tag in a table in your ODT document, between the table tags ( [!-- BEGIN row.lines --] ... [!-- END row.lines --] ), and this will print your full price.

Implementing the change of price in PDF templates
First, we will create our own PDF template by copying an existing template, and then we will edit it to change the price of items.

Creating your own PDF template by copying an existing template
Go into the following folder: htdocs/core/modules/facture/doc/, then copy the file pdf_crabe.modules.php and name the new one pdf_crabecoeff.modules.php.

Then open it in your favourite editor, and change the following lines:

That's it, now you have your own PDF template!

Now you should enable your PDF template before doing anything else, by going into the Modules Administration panel, and into the Invoice admin page, then click on the ON button at the right of the crabecoeff entry to enable the template.

Now, let's proceed onto modifying the prices.

Changing the prices automatically in your PDF
You can now do pretty much anything you want in your PDF template, but I will give you a mean to automatically change the prices of every products with our coefficient, as well as the total price, without editing too much the template.

First, try to find the following code of line (should be inside the write_file method):

Now, just copy/paste the following code below pdf_getInstance:

That's it, now you should try to generate your PDF document, and you should get something like this:

Note: printing the coefficient as a column in your PDF document is also possible but will not be covered here because PDF templates will vary for every persons depending on your needs. For guidelines about how to do this, you can read the documentation on how to create a PDF template and how to use custom fields in PDF templates.

Hint: you should be looking inside the following conditional block, inside the write_file method:

Implementing the change of price in the Dolibarr interface
Unluckily there is not (yet) any hooking context to modify how lines of products/services are printed, thus the only thing you can do is directly edit the template file and manually put inside your code to load your custom field and print it the way you want using HTML formatting, for our example:


 * For Dolibarr 3.3 and above, edit the file htdocs/core/tpl/objectline_view.tpl.php
 * For Dolibarr 3.1 and 3.2, edit the file htdocs/core/tpl/freeproductline_view.tpl.php AND predefinedproductline_view.tpl.php (apply the same changes to both files)

In the template file you opened, find the following code:

And replace it by:

This should produce something like this:

Technical note: here we are using customfields_fill_object instead of customfields_fill_object_lines (the latter being specifically adapted to lines and thus should theoretically be used here) for performance reasons because the template file we are editing is called in a loop, and customfields_fill_object_lines should be called outside a loop (because it already does the job that is done by the loop), so here we 'tricks' the customfields_fill_object function to avoid this loop by submitting 'facturedet' as a module by itself (when in fact it's a product lines table, but it works the same way nevertheless). This is a good demonstration of the flexibility of the CustomFields functions and methods.