Line 1:
Line 1:
+
<!-- BEGIN origin interlang links -->
+
<!-- You can edit this section but do NOT remove these comments
+
Links below will be automatically replicated on translated pages by PolyglotBot -->
+
[[fr:Module_CustomFields_Cases_FR]]
+
<!-- END interlang links -->
+
[[Category:CustomFields]]
[[Category:CustomFields]]
{{TemplateDocDevEn}}
{{TemplateDocDevEn}}
Line 164:
Line 170:
=== Static condition ===
=== Static condition ===
+
* Constraint WHERE clause (when creating/editing a custom field, you can specify your own WHERE conditions).
* 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:
* 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:
<source lang="php">
<source lang="php">
Line 187:
Line 194:
* CustomFields's Cascade Custom and Overload functions
* CustomFields's Cascade Custom and Overload functions
+
* Recursive Remote Fields Access
* Making your own module, which calls the CustomFields class
* Making your own module, which calls the CustomFields class
Line 194:
Line 202:
* Cron job
* Cron job
* CustomFields's overload functions
* CustomFields's overload functions
+
+
= Cascading =
+
+
A simple example of [http://wiki.dolibarr.org/index.php/Module_CustomFields#Cascade cascading to select a location] can be found in the user manual.
+
+
But you can do a lot more with cascading if you combine it with other options, such as Duplication and Hide. Here is an example:
+
+
Let's say that in invoices, you want to be able to select a contact of the society selected for this invoice. Of course, you want that the list of contacts show only the contacts related to the society (ie: that you added on the Third-Party datasheet of this society).
+
+
To do that, you have to proceed in two steps:
+
+
1- Create a custom field "soccpy_nom" constrained on llx_society that will duplicate the society's id. This is necessary because other custom fields can only be cascaded using other custom fields, not any Dolibarr fields. Using duplication allows you to duplicate any Dolibarr field (and even $_GET and $_POST), so that you can use them to cascade. Copy the parameters as shown in this image:
+
+
[[File:Cf-case-cascade-contacts1.png]]
+
+
2- Create a custom field "contact_firstname_lastname" with Cascade option with parent "soccpy_nom" and constrained on the table llx_socpeople (the table of the contacts), which will show the list of contacts associated only to the selected society in soccpy_nom. Copy the parameters as shown in this image:
+
+
[[File:Cf-case-cascade-contacts2.png]]
+
+
And voila, you're done! The field soccpy_nom should be hidden so you won't see it, but you should see the field contact_firstname_lastname and you can check that only the contacts related to the society selected for the current invoice are shown.
= Overloading functions =
= Overloading functions =
Line 435:
Line 463:
Done, now try to add/edit a product/service line, and the total price should be affected by the global coefficient.
Done, now try to add/edit a product/service line, and the total price should be affected by the global coefficient.
+
+
Note that this modification '''needs only to be done once for all modules''', you then just have to create a custom field named "global_coefficient" in every module you want to apply this coefficient.
== Implementing the change of price in margin module ==
== Implementing the change of price in margin module ==
Line 459:
Line 489:
This is where the lines are filled with margin infos. The price has just been fetched here, and we will now modify it with the coefficient before the price gets used for margin computation.
This is where the lines are filled with margin infos. The price has just been fetched here, and we will now modify it with the coefficient before the price gets used for margin computation.
−
Just below the code we found, paste the following:
+
To optimize things up, we will load the custom fields before the loop (because they don't change between product/service lines, they are the custom fields of the parent object), and then apply the global_coefficient inside the loop.
+
+
Just above the code we found (just before the for loop), paste the following:
<source lang="php">
<source lang="php">
Line 468:
Line 500:
// Load custom fields records
// Load custom fields records
$customfields = customfields_fill_object($this);
$customfields = customfields_fill_object($this);
+
</source>
+
+
And now, just below the code we found, inside the loop (and just above the comment: "// calcul des marges"), paste the following:
+
+
<source lang="php">
+
// Global coefficient (CustomFields)
// Apply the coefficient
// Apply the coefficient
if (!empty($this->customfields->cf_global_coefficient)) {
if (!empty($this->customfields->cf_global_coefficient)) {
Line 478:
Line 516:
That's all, the price should be reflected in the margin. Just refresh the page to reflect the change.
That's all, the price should be reflected in the margin. Just refresh the page to reflect the change.
+
+
Note that this modification '''needs only to be done once for all modules''', you then just have to create a custom field named "global_coefficient" in every module you want to apply this coefficient.
+
+
== Refresh the price instantly ==
+
+
Maybe you noticed one glitch: when you modify the global_coefficient, the global total price isn't updated until you add/edit a product/service line. This is because the update_price() function is only called when we add/edit a product/service line.
+
+
To fix that, we need now to force the refreshing of price. To do that, we will use an "aftersave" overloading function, which will execute commands after our custom field is saved.
+
+
Go to the folder /htdocs/customfields/fields and rename the file customfields_fields_extend.lib.php.example into customfields_fields_extend.lib.php .
+
+
Now, open it in your favourite text editor, and add the following function :
+
+
<source lang="php">
+
function customfields_field_aftersave_facture_global_coefficient (&$currentmodule, &$object, &$action, &$user, &$customfields, &$field, &$name, &$value, $fields) {
+
// Force refreshing total price
+
$object->update_price(0, 'auto');
+
}
+
</source>
+
+
That's all. Now, when you edit your global_coefficient, this will force refresh the total price.
+
+
However, you will still notice one last glitch: when you edit the global_coefficient, the total price isn't reflected instantly, you must refresh the webpage once to see the new price. This is because of how the datasheet and the CustomFields hook are designed: CustomFields is called only exactly where the custom fields are place, thus it is called after the total price, the margin and the remaining debt are printed. Thus, CustomFields updates the value of your custom field only after all those informations get printed, and thus it cannot modify them at this stage. That's why those information are out-of-date, and you must refresh the webpage once to get to see the latest values.
+
+
There is a workaround for this: refresh automatically the webpage (but delete the POST data to avoid an infinite loop). You just need to use this overloading code instead of the one above:
+
+
<source lang="php">
+
function customfields_field_aftersave_facture_global_coefficient (&$currentmodule, &$object, &$action, &$user, &$customfields, &$field, &$name, &$value, $fields) {
+
// Force refreshing total price
+
$object->update_price(0, 'auto');
+
// Force refresh the page to update prices that were printed before the custom field aftersave was triggered (and only if not creating the object because then there's no need to refresh)
+
if ($action !== 'add') print('<script type="text/javascript">window.location.href = window.location.pathname + window.location.search;</script>');
+
}
+
</source>
+
+
Another way to fix this issue would be to modify how CustomFields save the custom fields, by moving this stage at the very top. However, this would need another hook, which should be called at the very beginning of the page loading, which should be made only for this purpose (PageLoading), and should be available in all modules supported by CustomFields in order to not break anything.
+
+
Note that you will need to create one overloading function for each module you want to support with the global_coefficient custom field. For example, if you want to support both invoices and commercial proposals, you will need two overloading functions:
+
+
<source lang="php">
+
// Global coefficient for invoices (note the "facture" in the name of the function)
+
function customfields_field_aftersave_facture_global_coefficient (&$currentmodule, &$object, &$action, &$user, &$customfields, &$field, &$name, &$value, $fields) {
+
// Force refreshing total price
+
$object->update_price(0, 'auto');
+
// Force refresh the page to update prices that were printed before the custom field aftersave was triggered (and only if not creating the object because then there's no need to refresh)
+
if ($action !== 'add') print('<script type="text/javascript">window.location.href = window.location.pathname + window.location.search;</script>');
+
}
+
+
// Global coefficient for commercial proposals (note the "propal" in the name of the function)
+
function customfields_field_aftersave_propal_global_coefficient (&$currentmodule, &$object, &$action, &$user, &$customfields, &$field, &$name, &$value, $fields) {
+
// Force refreshing total price
+
$object->update_price(0, 'auto');
+
// Force refresh the page to update prices that were printed before the custom field aftersave was triggered (and only if not creating the object because then there's no need to refresh)
+
if ($action !== 'add') print('<script type="text/javascript">window.location.href = window.location.pathname + window.location.search;</script>');
+
}
+
</source>
= Modify the total price PER product/service line with a coefficient (without tampering the discount) =
= Modify the total price PER product/service line with a coefficient (without tampering the discount) =
Line 888:
Line 982:
</source>
</source>
−
This should do the trick. Now go to one of your invoices (or whatever module you are targetting), and you should see this:
+
This should do the trick. Now go to one of your invoices (or whatever module you are targetting), and try to add/edit a product/service line to force refresh the total price. You should then see this:
[[File:Cf_wiki_coeff_remaining_debt.png]]
[[File:Cf_wiki_coeff_remaining_debt.png]]