howto transf. customfields from proposal to order

Hi,

I’m just adapting the brilliant dolibarr 3.2.2 for my needs by using customfields (free edition) which I use for quotations, orders and invoices.

How can I achieve that customfields are automatically transfer from my quotations to orders and orders to invoices?

  1. is this a feature of the customfield pro edition?

  2. or is there an article in dollibars wiki (I couldn’t find any)?

any help is appreciated - thanks in advance.

best regards

Hello,

I am the developper of CustomFields.

I don’t understand what you mean by quotation, could you provide more details about what module you are talking about?

About your question, no there’s no automatic transfer of custom fields from modules to modules, because noone asked for such a feature before.

However, this may not be necessary. For example, orders that are converted to invoices produce a link between the order and the invoice. Thus, you can access the order’s custom fields from the invoice. For example, if you want to print custom fields of your order but print them on the PDF generated from the invoice, this is totally possible.

You can find a full tutorial on how to do this with CustomFields Pro here:
http://wiki.dolibarr.org/index.php/Module_CustomFields_Cases#Linking_Dolibarr_objects_from_two_different_modules

And a full documentation is available on the Dolibarr’s wiki:
http://wiki.dolibarr.org/index.php/Module_CustomFields

CustomFields Free edition should also be able to do that, but it will be a lot more complex because the customfields_fill_object() function, which does a lot of the job for you, is not available in the Free edition.

If this is not a viable solution for what you want to achieve, please give me more details so that I can better understand your goal.

Hi Irq3000… quotation means: offre de prix

Ah ok thank’s Humphrey. Your first translation quotation = propale was better in the context of Dolibarr since it’s how the module is called :happy:

Ok then Tom, when you convert a quotation to order and then to invoice, every one of these gets linked inside the Dolibarr database in the table llx_element_element, so then you can easily recreate the link with CustomFields using customfields_fill_object() as indicated in the tutorial I’ve given you, thus avoiding you the need to transfer/copy the custom fields (which would not be very clean: with the method I present you, you can set different custom fields for every one of these modules, and still link them, fetch them and use them whenever you need).

Hi lrq3000, thank’s for your answers.

  1. since I am new to dolibarr I would like to know if it’s a good way to use a trigger-event (e.g. ORDER_CREATE) to run customfields_fill_object() (as per “linking dolibarr objects from two diff. modules”) to fill CustomFields of my new Order with CustomFields from my Quotation (=propale). I assume that I can see (and edit) these newly filled CustomFields afterwards in the invoice module.

  2. Is there a way to distinguish in an ORDER_CREATE trigger event between a new order converted from a quote (propale) or a “blank” new order?
    (maybe some kind of state information?)

Thanks in advance for helping me !
best regards
Tom

Hello Tom,

  1. Yes that would be a pretty clean way to do that. You could make a trigger file on ORDER_CREATE which would fetch the Quotation’s custom fiels using customfields_fill_object() and table llx_element_element (or maybe directly $object may contain the link) and create a new custom field for orders using createCustomField() by just passing the object returned by customfields_fill_object (just be sure that the $object->table_element = ‘order’ or ‘commande’ and not ‘propal’).
    But as I said, copying custom fields is not necessary to fetch them since you can get the links using llx_element_element.

  2. In any case you should be able to get the state using the table llx_element_element, but you may also find the quotation to be a sub-element of $object (order), but this is not necessarily the case! Objects linking in Dolibarr seems to be undergoing a refactoration to ease this kind of processing, but I’m not too sure about it.
    An alternative would be to find the class where the orders are created from a quote, and add your own trigger there (eg: ORDER_CREATE_FROM_PROPAL), but it may already exists. Just look inside the *.class.php files.

Hello lrq3000,

thanks for your last reply, which is a while ago.

In the meantime I bought the Pro version of CustomFields to be able to use ‘customfields_fill_object’.

To take some CustomFields from an existing ComercialProposal into an new CustomerOrder I created a trigger with action == ‘ORDER_CREATE’ and followed the example of the wiki you gave me a view posts above (Linking Dolibarr objects from two different modules) to get access to all the CustomFields (both ‘propal’ and ‘commande’) using customfields_fill_object.

$object->customfields->commande->cf_someCFofOrder = $object->customfields->propal->cf_someCFofPropale;
With above code dol_syslog shows me the same content in both CustomFields. So far so good.

But above code does not store into database of course.
How can I store my CustomFileds of the newly created CustomerOrder into the database?

I tried with ‘update’ which raised an error “Call to undefined method stdClass::update()”.

thanks again in advance.
best regards
Tom

Hello Tom,

Thank you for buying CustomFields Pro. I hope it will satisfy all your needs.

tom wrote:

You must use the $customfields object that is returned by the customfields_fill_object() function.

Then you can simply do:

$rtncode = $customfields->update($object);

This will both update or create the custom field whether the record already exists or not (will be automatically detected by the CustomFields class).

However, the update() method expects an object with customfields stored inside $object->customfields, not $object->customfields->orders.

Thus either you can modify the code you’ve given above like this:

$object->customfields->cf_someCFofOrder =
$object->customfields->propal->cf_someCFofPropale;

Either you can just use 2 different objects with customfields_fill_object($object, $fromobject); where $fromobject is the propal object, and $object is the order object. Then you will be able to directly use $customfields->update($object).

For more information about the update() method and customfields_fill_object() function, please check the wiki (I’ve just updated the customfields_fill_object() chapter to describe its full specification):

Hello lrq3000,

Everything is working fine now, but I had to make following changes:
(just for Information if someone else is reading this thread):

In order to make $customfields->update($object) work, I had to use

$object->cf_someCFofOrder = $object->customfields->propal->cf_someCFofPropale;
instead of

$object->customfields->cf_someCFofOrder = ...
because $object - which is passed to update() - must be an object containing the customfields data as its properties (and not another costomfields object).

Thanks again for your quick support.

Maybe I will need your help again when I’m going to extend dolibarr’s project functionalities with TimeTracking features. :unsure:

Best regards
Tom

Hello Tom,

Thank you for the feedback, indeed my bad! I will add a compatibility layer to easy this kind of operation in the future, so that in future versions of CustomFields one will be able to just use $object->customfields or even $object->customfields->propal.

Feel free to contact me again, your TimeTracking sure seems interesting! Don’t forget that if you make a module on top of the CustomFields class, it will also work with CustomFields Free normally (since both shares a lot of code in common).

Sorry lrq3000,
need your help earlier than expected.

Just noticed that I cannot copy CustomFields (from customorder to invoice) which are formatted as date.

$object->cf_invorderdate = $object->customfields->commande->cf_coorderdate;
e.g. the sourcefield is “30.10.2012” -> the destinationfield just shows “0000-00-00”.

Any suggestion would be appreciated.
Thamks in advanced.

Best regards
Tom

customfields_fill_object() by default will format and beautify values, thus it will convert SQL date, which are stored in the universal format ISO 8601 (year-month-day) into the locale one.

You can workaround this by two ways:

- either reformat the date back to universal format with something like

$object->cf_invorderdate = date("Y-m-d", strtotime($object->customfields->commande->cf_coorderdate));

- either if you only intend to use $object->customfields->commande to copy these fields elsewhere (you don’t plan to print them out), you can just fetch the raw, unformatted values by setting the $pdfformat parameter to null:

customfields_fill_object(&$object, $fromobject = null, $outputlangs = null, $prefix = null,$pdfformat = false); // set $pdfformat to null to get non formatted values

For example with something like that:

customfields_fill_object(&$object, null, null, 'commande->raw',null); // this will store the raw custom fields values inside $object->customfields->commande->raw->cf_yourfield

This second method has the advantage to also work for other complex kind of fields types like constrained types (where you can’t just copy the formatted value, you need to use the ID as the field will only accept an int).

Of course, when the raw values will be copied and saved into your target fields, when these fields will be accessed on the Dolibar datasheet or ODT templates, these values will be formatted and beautified (you only get the raw fields but from the raw fields, CustomFields will deduce the proper formatting it has to apply as long as both the source field and target field have the same SQL structure. eg: a source field that is constrained on a table, the target field should also be constrained on the same table).

So I would advise you to use the second method if you want to generalize your solution as it is pretty simple, elegant and robust, but if it’s only for a specific, punctal case, then the first method can be appropriate.

Hi lrq3000,

Since non of your above suggestions where working on my system, I checked the update() function in customfields.class.php and saw that you try to get the date as follows:

$dateday = $object->{$key.'day'}; $datemonth = $object->{$key.'month'}; $dateyear = $object->{$key.'year'};
In my case the elements day, month, year exist but are empty.
So I had to to do something like this:

$object->cf_invorderdate = date("d.m.Y",strtotime($object->customfields->commande->cf_coorderdate)); $object->{cf_invorderdate.'day'} = date("d",strtotime($object->customfields->commande->cf_coorderdate)); $object->{cf_invorderdate.'month'} = date("m",strtotime($object->customfields->commande->cf_coorderdate)); $object->{cf_invorderdate.'year'} = date("Y",strtotime($object->customfields->commande->cf_coorderdate)); in order to get things working.
Is this the way it should be?

One more thing which I noticed in update() function (line 388):

 else { // else if they are not submitted (or if they weren't assigned inside $object), we try to split the date into 3 values
    list($dateday, $datemonth, $dateyear) = explode('/',$object->$key);
}

This would not work if someone (like me) changed the delimiter of the date-format from “/” to “.”

Best regards
Tom

Hello Tom,

Thank you for the feedback.

I did not know you could change the date delimiter in Dolibarr. How did you do that so that I can reproduce this behaviour?

Your solution works for your specific case, but if I can reproduce the behaviour, I will fix that in the next update of CustomFields.

Hi,

you can change the dateformat in main.lang of your language directory (in my case …/langs/de_AT/main.lang).

FormatDateShort=%Y/%m/%d
change to
FormatDateShort=%d.%m.%Y

But this is actually not the origin of my strange behaviour.
Evenwhen I set the dateformat back to slashes I have to copy the date in my trigger with

$object->{cf_invorderdate.'day'} =  date("d", strtotime($object->customfields->commande->cf_coorderdate));
...

I think my problem ist that the emlements .day, .month and .year are set but have no content when I just use

$object->cf_invorderdate = $object->customfields->commande->cf_coorderdate;
I set some debugs in customfields/class/customfields.class.php function create($object, $notrigger=0).
I get the copied date in $object->$key (in Format “2012-11-03”) after line 381.
$object->{$key.‘day’} (and month, year) are set (line 383) but content is “” (line 384-386)

Hope this helps.
regards
tom