dolibarr  19.0.0-dev
interface_20_modWorkflow_WorkflowManager.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2010 Regis Houssin <regis.houssin@inodbox.com>
3  * Copyright (C) 2011-2017 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2014 Marcos GarcĂ­a <marcosgdf@gmail.com>
5  * Copyright (C) 2022 Ferran Marcet <fmarcet@2byte.es>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <https://www.gnu.org/licenses/>.
19  */
20 
27 require_once DOL_DOCUMENT_ROOT.'/core/triggers/dolibarrtriggers.class.php';
28 
29 
35 {
41  public function __construct($db)
42  {
43  $this->db = $db;
44 
45  $this->name = preg_replace('/^Interface/i', '', get_class($this));
46  $this->family = "core";
47  $this->description = "Triggers of this module allows to manage workflows";
48  // 'development', 'experimental', 'dolibarr' or version
49  $this->version = self::VERSION_DOLIBARR;
50  $this->picto = 'technic';
51  }
52 
64  public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf)
65  {
66  if (empty($conf->workflow) || empty($conf->workflow->enabled)) {
67  return 0; // Module not active, we do nothing
68  }
69 
70  $ret = 0;
71 
72  // Proposals to order
73  if ($action == 'PROPAL_CLOSE_SIGNED') {
74  dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
75  if (isModEnabled('commande') && !empty($conf->global->WORKFLOW_PROPAL_AUTOCREATE_ORDER)) {
76  $object->fetchObjectLinked();
77  if (!empty($object->linkedObjectsIds['commande'])) {
78  if (empty($object->context['closedfromonlinesignature'])) {
79  $langs->load("orders");
80  setEventMessages($langs->trans("OrderExists"), null, 'warnings');
81  }
82  return $ret;
83  } else {
84  include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
85  $newobject = new Commande($this->db);
86 
87  $newobject->context['createfrompropal'] = 'createfrompropal';
88  $newobject->context['origin'] = $object->element;
89  $newobject->context['origin_id'] = $object->id;
90 
91  $ret = $newobject->createFromProposal($object, $user);
92  if ($ret < 0) {
93  $this->error = $newobject->error;
94  $this->errors[] = $newobject->error;
95  }
96 
97  $object->clearObjectLinkedCache();
98 
99  return $ret;
100  }
101  }
102  }
103 
104  // Order to invoice
105  if ($action == 'ORDER_CLOSE') {
106  dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
107  if (isModEnabled('facture') && !empty($conf->global->WORKFLOW_ORDER_AUTOCREATE_INVOICE)) {
108  include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
109  $newobject = new Facture($this->db);
110 
111  $newobject->context['createfromorder'] = 'createfromorder';
112  $newobject->context['origin'] = $object->element;
113  $newobject->context['origin_id'] = $object->id;
114 
115  $ret = $newobject->createFromOrder($object, $user);
116  if ($ret < 0) {
117  $this->error = $newobject->error;
118  $this->errors[] = $newobject->error;
119  }
120 
121  $object->clearObjectLinkedCache();
122 
123  return $ret;
124  }
125  }
126 
127  // Order classify billed proposal
128  if ($action == 'ORDER_CLASSIFY_BILLED') {
129  dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
130  if (isModEnabled("propal") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_ORDER_CLASSIFY_BILLED_PROPAL)) {
131  $object->fetchObjectLinked('', 'propal', $object->id, $object->element);
132  if (!empty($object->linkedObjects)) {
133  $totalonlinkedelements = 0;
134  foreach ($object->linkedObjects['propal'] as $element) {
135  if ($element->statut == Propal::STATUS_SIGNED || $element->statut == Propal::STATUS_BILLED) {
136  $totalonlinkedelements += $element->total_ht;
137  }
138  }
139  dol_syslog("Amount of linked proposals = ".$totalonlinkedelements.", of order = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht));
140  if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
141  foreach ($object->linkedObjects['propal'] as $element) {
142  $ret = $element->classifyBilled($user);
143  }
144  }
145  }
146  return $ret;
147  }
148  }
149 
150  // classify billed order & billed propososal
151  if ($action == 'BILL_VALIDATE') {
152  dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
153 
154  // First classify billed the order to allow the proposal classify process
155  if (isModEnabled('commande') && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER)) {
156  $object->fetchObjectLinked('', 'commande', $object->id, $object->element);
157  if (!empty($object->linkedObjects)) {
158  $totalonlinkedelements = 0;
159  foreach ($object->linkedObjects['commande'] as $element) {
160  if ($element->statut == Commande::STATUS_VALIDATED || $element->statut == Commande::STATUS_SHIPMENTONPROCESS || $element->statut == Commande::STATUS_CLOSED) {
161  $totalonlinkedelements += $element->total_ht;
162  }
163  }
164  dol_syslog("Amount of linked orders = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht));
165  if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
166  foreach ($object->linkedObjects['commande'] as $element) {
167  $ret = $element->classifyBilled($user);
168  }
169  }
170  }
171  }
172 
173  // Second classify billed the proposal.
174  if (isModEnabled("propal") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_INVOICE_CLASSIFY_BILLED_PROPAL)) {
175  $object->fetchObjectLinked('', 'propal', $object->id, $object->element);
176  if (!empty($object->linkedObjects)) {
177  $totalonlinkedelements = 0;
178  foreach ($object->linkedObjects['propal'] as $element) {
179  if ($element->statut == Propal::STATUS_SIGNED || $element->statut == Propal::STATUS_BILLED) {
180  $totalonlinkedelements += $element->total_ht;
181  }
182  }
183  dol_syslog("Amount of linked proposals = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht));
184  if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
185  foreach ($object->linkedObjects['propal'] as $element) {
186  $ret = $element->classifyBilled($user);
187  }
188  }
189  }
190  }
191 
192  if (isModEnabled("expedition") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE)) {
193  $object->fetchObjectLinked('', 'shipping', $object->id, $object->element);
194  if (!empty($object->linkedObjects)) {
195  $totalonlinkedelements = 0;
196  foreach ($object->linkedObjects['shipping'] as $element) {
197  if ($element->statut == Expedition::STATUS_VALIDATED) {
198  $totalonlinkedelements += $element->total_ht;
199  }
200  }
201  dol_syslog("Amount of linked shipment = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht), LOG_DEBUG);
202  if ($totalonlinkedelements == $object->total_ht) {
203  foreach ($object->linkedObjects['shipping'] as $element) {
204  $ret = $element->setClosed();
205  if ($ret < 0) {
206  return $ret;
207  }
208  }
209  }
210  }
211  }
212 
213  return $ret;
214  }
215 
216  // classify billed order & billed proposal
217  if ($action == 'BILL_SUPPLIER_VALIDATE') {
218  dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
219 
220  // Firstly, we set to purchase order to "Billed" if WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER is set.
221  // After we will set proposals
222  if ((isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && !empty($conf->global->WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER)) {
223  $object->fetchObjectLinked('', 'order_supplier', $object->id, $object->element);
224  if (!empty($object->linkedObjects)) {
225  $totalonlinkedelements = 0;
226  foreach ($object->linkedObjects['order_supplier'] as $element) {
228  $totalonlinkedelements += $element->total_ht;
229  }
230  }
231  dol_syslog("Amount of linked orders = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht));
232  if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
233  foreach ($object->linkedObjects['order_supplier'] as $element) {
234  $ret = $element->classifyBilled($user);
235  if ($ret < 0) {
236  return $ret;
237  }
238  }
239  }
240  }
241  }
242 
243  // Secondly, we set to linked Proposal to "Billed" if WORKFLOW_INVOICE_CLASSIFY_BILLED_SUPPLIER_PROPOSAL is set.
244  if (isModEnabled('supplier_proposal') && !empty($conf->global->WORKFLOW_INVOICE_CLASSIFY_BILLED_SUPPLIER_PROPOSAL)) {
245  $object->fetchObjectLinked('', 'supplier_proposal', $object->id, $object->element);
246  if (!empty($object->linkedObjects)) {
247  $totalonlinkedelements = 0;
248  foreach ($object->linkedObjects['supplier_proposal'] as $element) {
249  if ($element->statut == SupplierProposal::STATUS_SIGNED || $element->statut == SupplierProposal::STATUS_BILLED) {
250  $totalonlinkedelements += $element->total_ht;
251  }
252  }
253  dol_syslog("Amount of linked supplier proposals = ".$totalonlinkedelements.", of supplier invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht));
254  if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
255  foreach ($object->linkedObjects['supplier_proposal'] as $element) {
256  $ret = $element->classifyBilled($user);
257  if ($ret < 0) {
258  return $ret;
259  }
260  }
261  }
262  }
263  }
264 
265  // Then set reception to "Billed" if WORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE is set
266  if (isModEnabled("reception") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE)) {
267  $object->fetchObjectLinked('', 'reception', $object->id, $object->element);
268  if (!empty($object->linkedObjects)) {
269  $totalonlinkedelements = 0;
270  foreach ($object->linkedObjects['reception'] as $element) {
271  if ($element->statut == Reception::STATUS_VALIDATED) {
272  $totalonlinkedelements += $element->total_ht;
273  }
274  }
275  dol_syslog("Amount of linked reception = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht), LOG_DEBUG);
276  if ($totalonlinkedelements == $object->total_ht) {
277  foreach ($object->linkedObjects['reception'] as $element) {
278  $ret = $element->setBilled();
279  if ($ret < 0) {
280  return $ret;
281  }
282  }
283  }
284  }
285  }
286 
287  return $ret;
288  }
289 
290  // Invoice classify billed order
291  if ($action == 'BILL_PAYED') {
292  dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
293 
294  if (isModEnabled('commande') && !empty($conf->global->WORKFLOW_INVOICE_CLASSIFY_BILLED_ORDER)) {
295  $object->fetchObjectLinked('', 'commande', $object->id, $object->element);
296  if (!empty($object->linkedObjects)) {
297  $totalonlinkedelements = 0;
298  foreach ($object->linkedObjects['commande'] as $element) {
299  if ($element->statut == Commande::STATUS_VALIDATED || $element->statut == Commande::STATUS_SHIPMENTONPROCESS || $element->statut == Commande::STATUS_CLOSED) {
300  $totalonlinkedelements += $element->total_ht;
301  }
302  }
303  dol_syslog("Amount of linked orders = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht));
304  if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
305  foreach ($object->linkedObjects['commande'] as $element) {
306  $ret = $element->classifyBilled($user);
307  }
308  }
309  }
310  return $ret;
311  }
312  }
313 
314  // If we validate or close a shipment
315  if (($action == 'SHIPPING_VALIDATE') || ($action == 'SHIPPING_CLOSED')) {
316  dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
317 
318  if (isModEnabled('commande') && isModEnabled("expedition") && !empty($conf->workflow->enabled) &&
319  (
320  (!empty($conf->global->WORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING) && ($action == 'SHIPPING_VALIDATE')) ||
321  (!empty($conf->global->WORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING_CLOSED) && ($action == 'SHIPPING_CLOSED'))
322  )
323  ) {
324  $qtyshipped = array();
325  $qtyordred = array();
326  require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
327 
328  // Find all shipments on order origin
329  $order = new Commande($this->db);
330  $ret = $order->fetch($object->origin_id);
331  if ($ret < 0) {
332  $this->error = $order->error;
333  $this->errors = $order->errors;
334  return $ret;
335  }
336  $ret = $order->fetchObjectLinked($order->id, 'commande', null, 'shipping');
337  if ($ret < 0) {
338  $this->error = $order->error;
339  $this->errors = $order->errors;
340  return $ret;
341  }
342  //Build array of quantity shipped by product for an order
343  if (is_array($order->linkedObjects) && count($order->linkedObjects) > 0) {
344  foreach ($order->linkedObjects as $type => $shipping_array) {
345  if ($type == 'shipping' && is_array($shipping_array) && count($shipping_array) > 0) {
346  foreach ($shipping_array as $shipping) {
347  if (is_array($shipping->lines) && count($shipping->lines) > 0) {
348  foreach ($shipping->lines as $shippingline) {
349  $qtyshipped[$shippingline->fk_product] += $shippingline->qty;
350  }
351  }
352  }
353  }
354  }
355  }
356 
357  //Build array of quantity ordered to be shipped
358  if (is_array($order->lines) && count($order->lines) > 0) {
359  foreach ($order->lines as $orderline) {
360  // Exclude lines not qualified for shipment, similar code is found into calcAndSetStatusDispatch() for vendors
361  if (empty($conf->global->STOCK_SUPPORTS_SERVICES) && $orderline->product_type > 0) {
362  continue;
363  }
364  $qtyordred[$orderline->fk_product] += $orderline->qty;
365  }
366  }
367  //dol_syslog(var_export($qtyordred,true),LOG_DEBUG);
368  //dol_syslog(var_export($qtyshipped,true),LOG_DEBUG);
369  //Compare array
370  $diff_array = array_diff_assoc($qtyordred, $qtyshipped);
371  if (count($diff_array) == 0) {
372  //No diff => mean everythings is shipped
373  $ret = $order->setStatut(Commande::STATUS_CLOSED, $object->origin_id, $object->origin, 'ORDER_CLOSE');
374  if ($ret < 0) {
375  $this->error = $order->error;
376  $this->errors = $order->errors;
377  return $ret;
378  }
379  }
380  }
381  }
382 
383  // If we validate or close a shipment
384  if (($action == 'RECEPTION_VALIDATE') || ($action == 'RECEPTION_CLOSED')) {
385  dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
386 
387  if ((isModEnabled("fournisseur") || isModEnabled("supplier_order")) && isModEnabled("reception") && !empty($conf->workflow->enabled) &&
388  (
389  (!empty($conf->global->WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION) && ($action == 'RECEPTION_VALIDATE')) ||
390  (!empty($conf->global->WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED) && ($action == 'RECEPTION_CLOSED'))
391  )
392  ) {
393  $qtyshipped = array();
394  $qtyordred = array();
395  require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
396 
397  // Find all reception on purchase order origin
398  $order = new CommandeFournisseur($this->db);
399  $ret = $order->fetch($object->origin_id);
400  if ($ret < 0) {
401  $this->error = $order->error;
402  $this->errors = $order->errors;
403  return $ret;
404  }
405  $ret = $order->fetchObjectLinked($order->id, $order->element, null, 'reception');
406  if ($ret < 0) {
407  $this->error = $order->error;
408  $this->errors = $order->errors;
409  return $ret;
410  }
411  //Build array of quantity received by product for a purchase order
412  if (is_array($order->linkedObjects) && count($order->linkedObjects) > 0) {
413  foreach ($order->linkedObjects as $type => $shipping_array) {
414  if ($type == 'reception' && is_array($shipping_array) && count($shipping_array) > 0) {
415  foreach ($shipping_array as $shipping) {
416  if (is_array($shipping->lines) && count($shipping->lines) > 0) {
417  foreach ($shipping->lines as $shippingline) {
418  $qtyshipped[$shippingline->fk_product] += $shippingline->qty;
419  }
420  }
421  }
422  }
423  }
424  }
425 
426  //Build array of quantity ordered to be received
427  if (is_array($order->lines) && count($order->lines) > 0) {
428  foreach ($order->lines as $orderline) {
429  // Exclude lines not qualified for shipment, similar code is found into calcAndSetStatusDispatch() for vendors
430  if (empty($conf->global->STOCK_SUPPORTS_SERVICES) && $orderline->product_type > 0) {
431  continue;
432  }
433  $qtyordred[$orderline->fk_product] += $orderline->qty;
434  }
435  }
436  //dol_syslog(var_export($qtyordred,true),LOG_DEBUG);
437  //dol_syslog(var_export($qtyshipped,true),LOG_DEBUG);
438  //Compare array
439  $diff_array = array_diff_assoc($qtyordred, $qtyshipped);
440  if (count($diff_array) == 0) {
441  //No diff => mean everythings is received
442  $ret = $order->setStatut(CommandeFournisseur::STATUS_RECEIVED_COMPLETELY, null, null, 'SUPPLIER_ORDER_CLOSE');
443  if ($ret < 0) {
444  $this->error = $order->error;
445  $this->errors = $order->errors;
446  return $ret;
447  }
448  }
449  }
450  }
451 
452  if ($action == 'TICKET_CREATE') {
453  dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
454  // Auto link contract
455  if (!empty($conf->contract->enabled) && isModEnabled('ticket') && isModEnabled('ficheinter') && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_TICKET_LINK_CONTRACT) && !empty($conf->global->TICKET_PRODUCT_CATEGORY) && !empty($object->fk_soc)) {
456  $societe = new Societe($this->db);
457  $company_ids = (empty($conf->global->WORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS)) ? [$object->fk_soc] : $societe->getParentsForCompany($object->fk_soc, [$object->fk_soc]);
458 
459  $contrat = new Contrat($this->db);
460  $number_contracts_found = 0;
461  foreach ($company_ids as $company_id) {
462  $contrat->socid = $company_id;
463  $list = $contrat->getListOfContracts($option = 'all', $status = [Contrat::STATUS_DRAFT, Contrat::STATUS_VALIDATED], $product_categories = [$conf->global->TICKET_PRODUCT_CATEGORY], $line_status = [ContratLigne::STATUS_INITIAL, ContratLigne::STATUS_OPEN]);
464  if (is_array($list) && !empty($list)) {
465  $number_contracts_found = count($list);
466  if ($number_contracts_found == 1) {
467  foreach ($list as $linked_contract) {
468  $object->setContract($linked_contract->id);
469  }
470  break;
471  } elseif ($number_contracts_found > 1) {
472  foreach ($list as $linked_contract) {
473  $object->setContract($linked_contract->id);
474  // don't set '$contractid' so it is not used when creating an intervention.
475  }
476  if (empty(NOLOGIN)) setEventMessage($langs->trans('TicketManyContractsLinked'), 'warnings');
477  break;
478  }
479  }
480  }
481  if ($number_contracts_found == 0) {
482  if (empty(NOLOGIN)) setEventMessage($langs->trans('TicketNoContractFoundToLink'), 'mesgs');
483  }
484  }
485  // Automatically create intervention
486  if (isModEnabled('ficheinter') && isModEnabled('ticket') && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_TICKET_CREATE_INTERVENTION)) {
487  $fichinter = new Fichinter($this->db);
488  $fichinter->socid = (int) $object->fk_soc;
489  $fichinter->fk_project = $projectid;
490  $fichinter->fk_contrat = (int) $object->fk_contract;
491  $fichinter->author = $user->id;
492  $fichinter->model_pdf = (!empty($conf->global->FICHEINTER_ADDON_PDF)) ? $conf->global->FICHEINTER_ADDON_PDF : 'soleil';
493  $fichinter->origin = $object->element;
494  $fichinter->origin_id = $object->id;
495 
496  // Extrafields
497  $extrafields = new ExtraFields($this->db);
498  $extrafields->fetch_name_optionals_label($fichinter->table_element);
499  $array_options = $extrafields->getOptionalsFromPost($fichinter->table_element);
500  $fichinter->array_options = $array_options;
501 
502  $id = $fichinter->create($user);
503  if ($id <= 0) {
504  setEventMessages($fichinter->error, null, 'errors');
505  }
506  }
507  }
508  return 0;
509  }
510 
521  private function shouldClassify($conf, $totalonlinkedelements, $object_total_ht)
522  {
523  // if the configuration allows unmatching amounts, allow classification anyway
524  if (!empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) {
525  return true;
526  }
527  // if the amount are same, allow classification, else deny
528  return (price2num($totalonlinkedelements, 'MT') == price2num($object_total_ht, 'MT'));
529  }
530 }
Class to manage predefined suppliers products.
const STATUS_RECEIVED_PARTIALLY
Received partially.
const STATUS_RECEIVED_COMPLETELY
Received completely.
const STATUS_ORDERSENT
Order sent, shipment on process.
Class to manage customers orders.
const STATUS_SHIPMENTONPROCESS
Shipment on process.
const STATUS_CLOSED
Closed (Sent, billed or not)
const STATUS_VALIDATED
Validated status.
Class to stock current configuration.
Definition: conf.class.php:34
Class to manage contracts.
Class that all the triggers must extend.
const STATUS_VALIDATED
Validated status.
Class to manage standard extra fields.
Class to manage invoices.
Class to manage interventions.
runTrigger($action, $object, User $user, Translate $langs, Conf $conf)
Function called when a Dolibarrr business event is done.
shouldClassify($conf, $totalonlinkedelements, $object_total_ht)
const STATUS_SIGNED
Signed quote.
const STATUS_BILLED
Billed or processed quote.
Class to manage third parties objects (customers, suppliers, prospects...)
const STATUS_SIGNED
Signed quote.
Class to manage translations.
Class to manage Dolibarr users.
Definition: user.class.php:48
print *****$script_file(".$version.") pid cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
setEventMessage($mesgs, $style='mesgs', $noduplicate=0)
Set event message in dol_events session object.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition: repair.php:123