dolibarr 18.0.6
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
27require_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 } else {
120 if (empty($object->fk_account) && !empty($object->thirdparty->fk_account) && !getDolGlobalInt('BANK_ASK_PAYMENT_BANK_DURING_ORDER')) {
121 $res = $newobject->setBankAccount($object->thirdparty->fk_account, true, $user);
122 if ($ret < 0) {
123 $this->error = $newobject->error;
124 $this->errors[] = $newobject->error;
125 }
126 }
127 }
128
129 $object->clearObjectLinkedCache();
130
131 return $ret;
132 }
133 }
134
135 // Order classify billed proposal
136 if ($action == 'ORDER_CLASSIFY_BILLED') {
137 dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
138 if (isModEnabled("propal") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_ORDER_CLASSIFY_BILLED_PROPAL)) {
139 $object->fetchObjectLinked('', 'propal', $object->id, $object->element);
140 if (!empty($object->linkedObjects)) {
141 $totalonlinkedelements = 0;
142 foreach ($object->linkedObjects['propal'] as $element) {
143 if ($element->statut == Propal::STATUS_SIGNED || $element->statut == Propal::STATUS_BILLED) {
144 $totalonlinkedelements += $element->total_ht;
145 }
146 }
147 dol_syslog("Amount of linked proposals = ".$totalonlinkedelements.", of order = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht));
148 if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
149 foreach ($object->linkedObjects['propal'] as $element) {
150 $ret = $element->classifyBilled($user);
151 }
152 }
153 }
154 return $ret;
155 }
156 }
157
158 // classify billed order & billed propososal
159 if ($action == 'BILL_VALIDATE') {
160 dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
161
162 // First classify billed the order to allow the proposal classify process
163 if (isModEnabled('commande') && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER)) {
164 $object->fetchObjectLinked('', 'commande', $object->id, $object->element);
165 if (!empty($object->linkedObjects)) {
166 $totalonlinkedelements = 0;
167 foreach ($object->linkedObjects['commande'] as $element) {
168 if ($element->statut == Commande::STATUS_VALIDATED || $element->statut == Commande::STATUS_SHIPMENTONPROCESS || $element->statut == Commande::STATUS_CLOSED) {
169 $totalonlinkedelements += $element->total_ht;
170 }
171 }
172 dol_syslog("Amount of linked orders = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht));
173 if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
174 foreach ($object->linkedObjects['commande'] as $element) {
175 $ret = $element->classifyBilled($user);
176 }
177 }
178 }
179 }
180
181 // Second classify billed the proposal.
182 if (isModEnabled("propal") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_INVOICE_CLASSIFY_BILLED_PROPAL)) {
183 $object->fetchObjectLinked('', 'propal', $object->id, $object->element);
184 if (!empty($object->linkedObjects)) {
185 $totalonlinkedelements = 0;
186 foreach ($object->linkedObjects['propal'] as $element) {
187 if ($element->statut == Propal::STATUS_SIGNED || $element->statut == Propal::STATUS_BILLED) {
188 $totalonlinkedelements += $element->total_ht;
189 }
190 }
191 dol_syslog("Amount of linked proposals = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht));
192 if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
193 foreach ($object->linkedObjects['propal'] as $element) {
194 $ret = $element->classifyBilled($user);
195 }
196 }
197 }
198 }
199
200 if (isModEnabled("expedition") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE)) {
201 $object->fetchObjectLinked('', 'shipping', $object->id, $object->element);
202 if (!empty($object->linkedObjects)) {
203 $totalonlinkedelements = 0;
204 foreach ($object->linkedObjects['shipping'] as $element) {
205 if ($element->statut == Expedition::STATUS_VALIDATED) {
206 $totalonlinkedelements += $element->total_ht;
207 }
208 }
209 dol_syslog("Amount of linked shipment = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht), LOG_DEBUG);
210 if ($totalonlinkedelements == $object->total_ht) {
211 foreach ($object->linkedObjects['shipping'] as $element) {
212 $ret = $element->setClosed();
213 if ($ret < 0) {
214 return $ret;
215 }
216 }
217 }
218 }
219 }
220
221 return $ret;
222 }
223
224 // classify billed order & billed proposal
225 if ($action == 'BILL_SUPPLIER_VALIDATE') {
226 dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
227
228 // Firstly, we set to purchase order to "Billed" if WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER is set.
229 // After we will set proposals
230 if ((isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && !empty($conf->global->WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER)) {
231 $object->fetchObjectLinked('', 'order_supplier', $object->id, $object->element);
232 if (!empty($object->linkedObjects)) {
233 $totalonlinkedelements = 0;
234 foreach ($object->linkedObjects['order_supplier'] as $element) {
236 $totalonlinkedelements += $element->total_ht;
237 }
238 }
239 dol_syslog("Amount of linked orders = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht));
240 if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
241 foreach ($object->linkedObjects['order_supplier'] as $element) {
242 $ret = $element->classifyBilled($user);
243 if ($ret < 0) {
244 return $ret;
245 }
246 }
247 }
248 }
249 }
250
251 // Secondly, we set to linked Proposal to "Billed" if WORKFLOW_INVOICE_CLASSIFY_BILLED_SUPPLIER_PROPOSAL is set.
252 if (isModEnabled('supplier_proposal') && !empty($conf->global->WORKFLOW_INVOICE_CLASSIFY_BILLED_SUPPLIER_PROPOSAL)) {
253 $object->fetchObjectLinked('', 'supplier_proposal', $object->id, $object->element);
254 if (!empty($object->linkedObjects)) {
255 $totalonlinkedelements = 0;
256 foreach ($object->linkedObjects['supplier_proposal'] as $element) {
257 if ($element->statut == SupplierProposal::STATUS_SIGNED || $element->statut == SupplierProposal::STATUS_BILLED) {
258 $totalonlinkedelements += $element->total_ht;
259 }
260 }
261 dol_syslog("Amount of linked supplier proposals = ".$totalonlinkedelements.", of supplier invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht));
262 if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
263 foreach ($object->linkedObjects['supplier_proposal'] as $element) {
264 $ret = $element->classifyBilled($user);
265 if ($ret < 0) {
266 return $ret;
267 }
268 }
269 }
270 }
271 }
272
273 // Then set reception to "Billed" if WORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE is set
274 if (isModEnabled("reception") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE)) {
275 $object->fetchObjectLinked('', 'reception', $object->id, $object->element);
276 if (!empty($object->linkedObjects)) {
277 $totalonlinkedelements = 0;
278 foreach ($object->linkedObjects['reception'] as $element) {
279 if ($element->statut == Reception::STATUS_VALIDATED || $element->statut == Reception::STATUS_CLOSED) {
280 $totalonlinkedelements += $element->total_ht;
281 }
282 }
283 dol_syslog("Amount of linked reception = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".((string) $totalonlinkedelements == (string) $object->total_ht), LOG_DEBUG);
284 if ( (string) $totalonlinkedelements == (string) $object->total_ht) {
285 foreach ($object->linkedObjects['reception'] as $element) {
286 $ret = $element->setBilled();
287 if ($ret < 0) {
288 return $ret;
289 }
290 }
291 }
292 }
293 }
294
295 return $ret;
296 }
297
298 // Invoice classify billed order
299 if ($action == 'BILL_PAYED') {
300 dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
301
302 if (isModEnabled('commande') && !empty($conf->global->WORKFLOW_INVOICE_CLASSIFY_BILLED_ORDER)) {
303 $object->fetchObjectLinked('', 'commande', $object->id, $object->element);
304 if (!empty($object->linkedObjects)) {
305 $totalonlinkedelements = 0;
306 foreach ($object->linkedObjects['commande'] as $element) {
307 if ($element->statut == Commande::STATUS_VALIDATED || $element->statut == Commande::STATUS_SHIPMENTONPROCESS || $element->statut == Commande::STATUS_CLOSED) {
308 $totalonlinkedelements += $element->total_ht;
309 }
310 }
311 dol_syslog("Amount of linked orders = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht));
312 if ($this->shouldClassify($conf, $totalonlinkedelements, $object->total_ht)) {
313 foreach ($object->linkedObjects['commande'] as $element) {
314 $ret = $element->classifyBilled($user);
315 }
316 }
317 }
318 return $ret;
319 }
320 }
321
322 // If we validate or close a shipment
323 if (($action == 'SHIPPING_VALIDATE') || ($action == 'SHIPPING_CLOSED')) {
324 dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
325
326 if (isModEnabled('commande') && isModEnabled("expedition") && !empty($conf->workflow->enabled) &&
327 (
328 (!empty($conf->global->WORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING) && ($action == 'SHIPPING_VALIDATE')) ||
329 (!empty($conf->global->WORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING_CLOSED) && ($action == 'SHIPPING_CLOSED'))
330 )
331 ) {
332 $qtyshipped = array();
333 $qtyordred = array();
334 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
335
336 // Find all shipments on order origin
337 $order = new Commande($this->db);
338 $ret = $order->fetch($object->origin_id);
339 if ($ret < 0) {
340 $this->error = $order->error;
341 $this->errors = $order->errors;
342 return $ret;
343 }
344 $ret = $order->fetchObjectLinked($order->id, 'commande', null, 'shipping');
345 if ($ret < 0) {
346 $this->error = $order->error;
347 $this->errors = $order->errors;
348 return $ret;
349 }
350 //Build array of quantity shipped by product for an order
351 if (is_array($order->linkedObjects) && count($order->linkedObjects) > 0) {
352 foreach ($order->linkedObjects as $type => $shipping_array) {
353 if ($type == 'shipping' && is_array($shipping_array) && count($shipping_array) > 0) {
354 foreach ($shipping_array as $shipping) {
355 if (is_array($shipping->lines) && count($shipping->lines) > 0) {
356 foreach ($shipping->lines as $shippingline) {
357 $qtyshipped[$shippingline->fk_product] += $shippingline->qty;
358 }
359 }
360 }
361 }
362 }
363 }
364
365 //Build array of quantity ordered to be shipped
366 if (is_array($order->lines) && count($order->lines) > 0) {
367 foreach ($order->lines as $orderline) {
368 // Exclude lines not qualified for shipment, similar code is found into calcAndSetStatusDispatch() for vendors
369 if (empty($conf->global->STOCK_SUPPORTS_SERVICES) && $orderline->product_type > 0) {
370 continue;
371 }
372 $qtyordred[$orderline->fk_product] += $orderline->qty;
373 }
374 }
375 //dol_syslog(var_export($qtyordred,true),LOG_DEBUG);
376 //dol_syslog(var_export($qtyshipped,true),LOG_DEBUG);
377 //Compare array
378 $diff_array = array_diff_assoc($qtyordred, $qtyshipped);
379 if (count($diff_array) == 0) {
380 //No diff => mean everythings is shipped
381 $ret = $order->setStatut(Commande::STATUS_CLOSED, $object->origin_id, $object->origin, 'ORDER_CLOSE');
382 if ($ret < 0) {
383 $this->error = $order->error;
384 $this->errors = $order->errors;
385 return $ret;
386 }
387 }
388 }
389 }
390
391 // If we validate or close a shipment
392 if (($action == 'RECEPTION_VALIDATE') || ($action == 'RECEPTION_CLOSED')) {
393 dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
394
395 if ((isModEnabled("fournisseur") || isModEnabled("supplier_order")) && isModEnabled("reception") && !empty($conf->workflow->enabled) &&
396 (
397 (!empty($conf->global->WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION) && ($action == 'RECEPTION_VALIDATE')) ||
398 (!empty($conf->global->WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED) && ($action == 'RECEPTION_CLOSED'))
399 )
400 ) {
401 $qtyshipped = array();
402 $qtyordred = array();
403 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
404
405 // Find all reception on purchase order origin
406 $order = new CommandeFournisseur($this->db);
407 $ret = $order->fetch($object->origin_id);
408 if ($ret < 0) {
409 $this->error = $order->error;
410 $this->errors = $order->errors;
411 return $ret;
412 }
413 $ret = $order->fetchObjectLinked($order->id, $order->element, null, 'reception');
414 if ($ret < 0) {
415 $this->error = $order->error;
416 $this->errors = $order->errors;
417 return $ret;
418 }
419 //Build array of quantity received by product for a purchase order
420 if (is_array($order->linkedObjects) && count($order->linkedObjects) > 0) {
421 foreach ($order->linkedObjects as $type => $shipping_array) {
422 if ($type == 'reception' && is_array($shipping_array) && count($shipping_array) > 0) {
423 foreach ($shipping_array as $shipping) {
424 if (is_array($shipping->lines) && count($shipping->lines) > 0) {
425 foreach ($shipping->lines as $shippingline) {
426 $qtyshipped[$shippingline->fk_product] += $shippingline->qty;
427 }
428 }
429 }
430 }
431 }
432 }
433
434 //Build array of quantity ordered to be received
435 if (is_array($order->lines) && count($order->lines) > 0) {
436 foreach ($order->lines as $orderline) {
437 // Exclude lines not qualified for shipment, similar code is found into calcAndSetStatusDispatch() for vendors
438 if (empty($conf->global->STOCK_SUPPORTS_SERVICES) && $orderline->product_type > 0) {
439 continue;
440 }
441 $qtyordred[$orderline->fk_product] += $orderline->qty;
442 }
443 }
444 //dol_syslog(var_export($qtyordred,true),LOG_DEBUG);
445 //dol_syslog(var_export($qtyshipped,true),LOG_DEBUG);
446 //Compare array
447 $diff_array = array_diff_assoc($qtyordred, $qtyshipped);
448 if (count($diff_array) == 0) {
449 //No diff => mean everythings is received
450 $ret = $order->setStatut(CommandeFournisseur::STATUS_RECEIVED_COMPLETELY, null, null, 'SUPPLIER_ORDER_CLOSE');
451 if ($ret < 0) {
452 $this->error = $order->error;
453 $this->errors = $order->errors;
454 return $ret;
455 }
456 }
457 }
458 }
459
460 if ($action == 'TICKET_CREATE') {
461 dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
462 // Auto link ticket to contract
463 if (isModEnabled('contract') && isModEnabled('ticket') && isModEnabled('workflow') && getDolGlobalString('WORKFLOW_TICKET_LINK_CONTRACT') && getDolGlobalString('TICKET_PRODUCT_CATEGORY') && !empty($object->fk_soc)) {
464 $societe = new Societe($this->db);
465 $company_ids = (!getDolGlobalString('WORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS')) ? [$object->fk_soc] : $societe->getParentsForCompany($object->fk_soc, [$object->fk_soc]);
466
467 $contrat = new Contrat($this->db);
468 $number_contracts_found = 0;
469 foreach ($company_ids as $company_id) {
470 $contrat->socid = $company_id;
471 $list = $contrat->getListOfContracts('all', array(Contrat::STATUS_DRAFT, Contrat::STATUS_VALIDATED), array(getDolGlobalString('TICKET_PRODUCT_CATEGORY')), array(ContratLigne::STATUS_INITIAL, ContratLigne::STATUS_OPEN));
472 if (!is_array($list) || empty($list)) {
473 continue;
474 }
475 $number_contracts_found = count($list);
476
477 foreach ($list as $linked_contract) {
478 $object->setContract($linked_contract->id);
479 // don't set '$contractid' so it is not used when creating an intervention.
480 }
481
482 if ($number_contracts_found > 1 && !defined('NOLOGIN')) {
483 setEventMessage($langs->trans('TicketManyContractsLinked'), 'warnings');
484 }
485 }
486 if ($number_contracts_found == 0 && !defined('NOLOGIN')) {
487 setEventMessage($langs->trans('TicketNoContractFoundToLink'), 'mesgs');
488 }
489 }
490 // Automatically create intervention
491 if (isModEnabled('ficheinter') && isModEnabled('ticket') && isModEnabled('workflow') && getDolGlobalString('WORKFLOW_TICKET_CREATE_INTERVENTION')) {
492 $fichinter = new Fichinter($this->db);
493 $fichinter->socid = (int) $object->fk_soc;
494 $fichinter->fk_project = (int) $object->fk_project;
495 $fichinter->fk_contrat = (int) $object->fk_contract;
496 $fichinter->author = $user->id;
497 $fichinter->model_pdf = getDolGlobalString('FICHEINTER_ADDON_PDF', 'soleil');
498 $fichinter->origin = $object->element;
499 $fichinter->origin_id = $object->id;
500
501 // Extrafields
502 $extrafields = new ExtraFields($this->db);
503 $extrafields->fetch_name_optionals_label($fichinter->table_element);
504 $array_options = $extrafields->getOptionalsFromPost($fichinter->table_element);
505 $fichinter->array_options = $array_options;
506
507 $id = $fichinter->create($user);
508 if ($id <= 0) {
509 setEventMessages($fichinter->error, null, 'errors');
510 }
511 }
512 }
513 return 0;
514 }
515
526 private function shouldClassify($conf, $totalonlinkedelements, $object_total_ht)
527 {
528 // if the configuration allows unmatching amounts, allow classification anyway
529 if (!empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) {
530 return true;
531 }
532 // if the amount are same, allow classification, else deny
533 return (price2num($totalonlinkedelements, 'MT') == price2num($object_total_ht, 'MT'));
534 }
535}
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.
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.
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after 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.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
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