27 require_once DOL_DOCUMENT_ROOT.
'/core/triggers/dolibarrtriggers.class.php';
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";
49 $this->version = self::VERSION_DOLIBARR;
50 $this->picto =
'technic';
66 if (empty($conf->workflow) || empty($conf->workflow->enabled)) {
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");
84 include_once DOL_DOCUMENT_ROOT.
'/commande/class/commande.class.php';
85 $newobject =
new Commande($this->db);
87 $newobject->context[
'createfrompropal'] =
'createfrompropal';
88 $newobject->context[
'origin'] = $object->element;
89 $newobject->context[
'origin_id'] = $object->id;
91 $ret = $newobject->createFromProposal($object, $user);
93 $this->error = $newobject->error;
94 $this->errors[] = $newobject->error;
97 $object->clearObjectLinkedCache();
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);
111 $newobject->context[
'createfromorder'] =
'createfromorder';
112 $newobject->context[
'origin'] = $object->element;
113 $newobject->context[
'origin_id'] = $object->id;
115 $ret = $newobject->createFromOrder($object, $user);
117 $this->error = $newobject->error;
118 $this->errors[] = $newobject->error;
121 $object->clearObjectLinkedCache();
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) {
136 $totalonlinkedelements += $element->total_ht;
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);
151 if ($action ==
'BILL_VALIDATE') {
152 dol_syslog(
"Trigger '".$this->
name.
"' for action '$action' launched by ".__FILE__.
". id=".$object->id);
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) {
161 $totalonlinkedelements += $element->total_ht;
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);
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) {
180 $totalonlinkedelements += $element->total_ht;
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);
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) {
198 $totalonlinkedelements += $element->total_ht;
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();
217 if ($action ==
'BILL_SUPPLIER_VALIDATE') {
218 dol_syslog(
"Trigger '".$this->
name.
"' for action '$action' launched by ".__FILE__.
". id=".$object->id);
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;
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);
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) {
250 $totalonlinkedelements += $element->total_ht;
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);
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;
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();
291 if ($action ==
'BILL_PAYED') {
292 dol_syslog(
"Trigger '".$this->
name.
"' for action '$action' launched by ".__FILE__.
". id=".$object->id);
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) {
300 $totalonlinkedelements += $element->total_ht;
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);
315 if (($action ==
'SHIPPING_VALIDATE') || ($action ==
'SHIPPING_CLOSED')) {
316 dol_syslog(
"Trigger '".$this->
name.
"' for action '$action' launched by ".__FILE__.
". id=".$object->id);
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'))
324 $qtyshipped = array();
325 $qtyordred = array();
326 require_once DOL_DOCUMENT_ROOT.
'/commande/class/commande.class.php';
330 $ret = $order->fetch($object->origin_id);
332 $this->error = $order->error;
333 $this->errors = $order->errors;
336 $ret = $order->fetchObjectLinked($order->id,
'commande',
null,
'shipping');
338 $this->error = $order->error;
339 $this->errors = $order->errors;
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;
358 if (is_array($order->lines) && count($order->lines) > 0) {
359 foreach ($order->lines as $orderline) {
361 if (empty($conf->global->STOCK_SUPPORTS_SERVICES) && $orderline->product_type > 0) {
364 $qtyordred[$orderline->fk_product] += $orderline->qty;
370 $diff_array = array_diff_assoc($qtyordred, $qtyshipped);
371 if (count($diff_array) == 0) {
375 $this->error = $order->error;
376 $this->errors = $order->errors;
384 if (($action ==
'RECEPTION_VALIDATE') || ($action ==
'RECEPTION_CLOSED')) {
385 dol_syslog(
"Trigger '".$this->
name.
"' for action '$action' launched by ".__FILE__.
". id=".$object->id);
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'))
393 $qtyshipped = array();
394 $qtyordred = array();
395 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.commande.class.php';
399 $ret = $order->fetch($object->origin_id);
401 $this->error = $order->error;
402 $this->errors = $order->errors;
405 $ret = $order->fetchObjectLinked($order->id, $order->element,
null,
'reception');
407 $this->error = $order->error;
408 $this->errors = $order->errors;
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;
427 if (is_array($order->lines) && count($order->lines) > 0) {
428 foreach ($order->lines as $orderline) {
430 if (empty($conf->global->STOCK_SUPPORTS_SERVICES) && $orderline->product_type > 0) {
433 $qtyordred[$orderline->fk_product] += $orderline->qty;
439 $diff_array = array_diff_assoc($qtyordred, $qtyshipped);
440 if (count($diff_array) == 0) {
444 $this->error = $order->error;
445 $this->errors = $order->errors;
452 if ($action ==
'TICKET_CREATE') {
453 dol_syslog(
"Trigger '".$this->
name.
"' for action '$action' launched by ".__FILE__.
". id=".$object->id);
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]);
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);
471 } elseif ($number_contracts_found > 1) {
472 foreach ($list as $linked_contract) {
473 $object->setContract($linked_contract->id);
476 if (empty(NOLOGIN))
setEventMessage($langs->trans(
'TicketManyContractsLinked'),
'warnings');
481 if ($number_contracts_found == 0) {
482 if (empty(NOLOGIN))
setEventMessage($langs->trans(
'TicketNoContractFoundToLink'),
'mesgs');
486 if (
isModEnabled(
'ficheinter') &&
isModEnabled(
'ticket') && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_TICKET_CREATE_INTERVENTION)) {
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;
498 $extrafields->fetch_name_optionals_label($fichinter->table_element);
499 $array_options = $extrafields->getOptionalsFromPost($fichinter->table_element);
500 $fichinter->array_options = $array_options;
502 $id = $fichinter->create($user);
524 if (!empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) {
528 return (
price2num($totalonlinkedelements,
'MT') ==
price2num($object_total_ht,
'MT'));