dolibarr  9.0.0
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  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
26 require_once DOL_DOCUMENT_ROOT.'/core/triggers/dolibarrtriggers.class.php';
27 
28 
34 {
38  public $picto = 'technic';
39 
40  public $family = 'core';
41  public $description = "Triggers of this module allows to manage workflows";
42 
47  public $version = self::VERSION_DOLIBARR;
48 
60  public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf)
61  {
62  if (empty($conf->workflow->enabled)) return 0; // Module not active, we do nothing
63 
64  // Proposals to order
65  if ($action == 'PROPAL_CLOSE_SIGNED')
66  {
67  dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
68  if (! empty($conf->commande->enabled) && ! empty($conf->global->WORKFLOW_PROPAL_AUTOCREATE_ORDER))
69  {
70  include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
71  $newobject = new Commande($this->db);
72 
73  $newobject->context['createfrompropal'] = 'createfrompropal';
74  $newobject->context['origin'] = $object->element;
75  $newobject->context['origin_id'] = $object->id;
76 
77  $ret=$newobject->createFromProposal($object, $user);
78  if ($ret < 0) { $this->error=$newobject->error; $this->errors[]=$newobject->error; }
79  return $ret;
80  }
81  }
82 
83  // Order to invoice
84  if ($action == 'ORDER_CLOSE')
85  {
86  dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
87  if (! empty($conf->facture->enabled) && ! empty($conf->global->WORKFLOW_ORDER_AUTOCREATE_INVOICE))
88  {
89  include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
90  $newobject = new Facture($this->db);
91 
92  $newobject->context['createfromorder'] = 'createfromorder';
93  $newobject->context['origin'] = $object->element;
94  $newobject->context['origin_id'] = $object->id;
95 
96  $ret=$newobject->createFromOrder($object, $user);
97  if ($ret < 0) { $this->error=$newobject->error; $this->errors[]=$newobject->error; }
98  return $ret;
99  }
100  }
101 
102  // Order classify billed proposal
103  if ($action == 'ORDER_CLASSIFY_BILLED')
104  {
105  dol_syslog( "Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id );
106  if (! empty($conf->propal->enabled) && ! empty($conf->workflow->enabled) && ! empty($conf->global->WORKFLOW_ORDER_CLASSIFY_BILLED_PROPAL))
107  {
108  $object->fetchObjectLinked('','propal',$object->id,$object->element);
109  if (! empty($object->linkedObjects))
110  {
111  $totalonlinkedelements=0;
112  foreach($object->linkedObjects['propal'] as $element)
113  {
114  if ($element->statut == Propal::STATUS_SIGNED || $element->statut == Propal::STATUS_BILLED) $totalonlinkedelements += $element->total_ht;
115  }
116  dol_syslog( "Amount of linked proposals = ".$totalonlinkedelements.", of order = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) );
117  if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) )
118  {
119  foreach($object->linkedObjects['propal'] as $element)
120  {
121  $ret=$element->classifyBilled($user);
122  }
123  }
124  }
125  return $ret;
126  }
127  }
128 
129  // classify billed order & billed propososal
130  if ($action == 'BILL_VALIDATE')
131  {
132  dol_syslog( "Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id );
133 
134  // First classify billed the order to allow the proposal classify process
135  if (! empty($conf->commande->enabled) && ! empty($conf->workflow->enabled) && ! empty($conf->global->WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER))
136  {
137  $object->fetchObjectLinked('','commande',$object->id,$object->element);
138  if (! empty($object->linkedObjects))
139  {
140  $totalonlinkedelements=0;
141  foreach($object->linkedObjects['commande'] as $element)
142  {
143  if ($element->statut == Commande::STATUS_VALIDATED || $element->statut == Commande::STATUS_SHIPMENTONPROCESS || $element->statut == Commande::STATUS_CLOSED) $totalonlinkedelements += $element->total_ht;
144  }
145  dol_syslog( "Amount of linked orders = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) );
146  if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) )
147  {
148  foreach($object->linkedObjects['commande'] as $element)
149  {
150  $ret=$element->classifyBilled($user);
151  }
152  }
153  }
154  return $ret;
155  }
156 
157  // Second classify billed the proposal.
158  if (! empty($conf->propal->enabled) && ! empty($conf->workflow->enabled) && ! empty($conf->global->WORKFLOW_INVOICE_CLASSIFY_BILLED_PROPAL))
159  {
160  $object->fetchObjectLinked('','propal',$object->id,$object->element);
161  if (! empty($object->linkedObjects))
162  {
163  $totalonlinkedelements=0;
164  foreach($object->linkedObjects['propal'] as $element)
165  {
166  if ($element->statut == Propal::STATUS_SIGNED || $element->statut == Propal::STATUS_BILLED) $totalonlinkedelements += $element->total_ht;
167  }
168  dol_syslog( "Amount of linked proposals = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) );
169  if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) )
170  {
171  foreach($object->linkedObjects['propal'] as $element)
172  {
173  $ret=$element->classifyBilled($user);
174  }
175  }
176  }
177  return $ret;
178  }
179  }
180 
181  // classify billed order & billed propososal
182  if ($action == 'BILL_SUPPLIER_VALIDATE')
183  {
184  dol_syslog( "Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id );
185 
186  // First classify billed the order to allow the proposal classify process
187  if (! empty($conf->fournisseur->enabled) && ! empty($conf->global->WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER))
188  {
189  $object->fetchObjectLinked('','order_supplier',$object->id,$object->element);
190  if (! empty($object->linkedObjects))
191  {
192  $totalonlinkedelements=0;
193  foreach($object->linkedObjects['order_supplier'] as $element)
194  {
195  if ($element->statut == CommandeFournisseur::STATUS_ACCEPTED || $element->statut == CommandeFournisseur::STATUS_ORDERSENT || $element->statut == CommandeFournisseur::STATUS_RECEIVED_PARTIALLY || $element->statut == CommandeFournisseur::STATUS_RECEIVED_COMPLETELY) $totalonlinkedelements += $element->total_ht;
196  }
197  dol_syslog( "Amount of linked orders = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) );
198  if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) )
199  {
200  foreach($object->linkedObjects['order_supplier'] as $element)
201  {
202  $ret=$element->classifyBilled($user);
203  }
204  }
205  }
206  return $ret;
207  }
208 
209  // Second classify billed the proposal.
210  if (! empty($conf->supplier_proposal->enabled) && ! empty($conf->global->WORKFLOW_INVOICE_CLASSIFY_BILLED_SUPPLIER_PROPOSAL))
211  {
212  $object->fetchObjectLinked('','supplier_proposal',$object->id,$object->element);
213  if (! empty($object->linkedObjects))
214  {
215  $totalonlinkedelements=0;
216  foreach($object->linkedObjects['supplier_proposal'] as $element)
217  {
218  if ($element->statut == SupplierProposal::STATUS_SIGNED || $element->statut == SupplierProposal::STATUS_BILLED) $totalonlinkedelements += $element->total_ht;
219  }
220  dol_syslog( "Amount of linked supplier proposals = ".$totalonlinkedelements.", of supplier invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) );
221  if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) )
222  {
223  foreach($object->linkedObjects['supplier_proposal'] as $element)
224  {
225  $ret=$element->classifyBilled($user);
226  }
227  }
228  }
229  return $ret;
230  }
231  }
232 
233  // Invoice classify billed order
234  if ($action == 'BILL_PAYED')
235  {
236  dol_syslog( "Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id );
237 
238  if (! empty($conf->commande->enabled) && ! empty($conf->global->WORKFLOW_INVOICE_CLASSIFY_BILLED_ORDER))
239  {
240  $object->fetchObjectLinked('','commande',$object->id,$object->element);
241  if (! empty($object->linkedObjects))
242  {
243  $totalonlinkedelements=0;
244  foreach($object->linkedObjects['commande'] as $element)
245  {
246  if ($element->statut == Commande::STATUS_VALIDATED || $element->statut == Commande::STATUS_SHIPMENTONPROCESS || $element->statut == Commande::STATUS_CLOSED) $totalonlinkedelements += $element->total_ht;
247  }
248  dol_syslog( "Amount of linked orders = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) );
249  if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) )
250  {
251  foreach($object->linkedObjects['commande'] as $element)
252  {
253  $ret=$element->classifyBilled($user);
254  }
255  }
256  }
257  return $ret;
258  }
259  }
260 
261  if ($action=='SHIPPING_VALIDATE')
262  {
263  dol_syslog( "Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id );
264 
265  if (! empty($conf->commande->enabled) && ! empty($conf->expedition->enabled) && ! empty($conf->workflow->enabled) && ! empty($conf->global->WORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING))
266  {
267  $qtyshipped=array();
268  $qtyordred=array();
269  require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
270 
271  //find all shippement on order origin
272  $order = new Commande($this->db);
273  $ret=$order->fetch($object->origin_id);
274  if ($ret<0) {
275  $this->error=$order->error; $this->errors=$order->errors;
276  return $ret;
277  }
278  $ret=$order->fetchObjectLinked($order->id,'commande',null,'shipping');
279  if ($ret<0) {
280  $this->error=$order->error; $this->errors=$order->errors;
281  return $ret;
282  }
283  //Build array of quantity shipped by product for an order
284  if (is_array($order->linkedObjects) && count($order->linkedObjects)>0) {
285  foreach($order->linkedObjects as $type=>$shipping_array) {
286  if ($type=='shipping' && is_array($shipping_array) && count($shipping_array)>0) {
287  foreach ($shipping_array as $shipping) {
288  if (is_array($shipping->lines) && count($shipping->lines)>0) {
289  foreach($shipping->lines as $shippingline) {
290  $qtyshipped[$shippingline->fk_product]+=$shippingline->qty;
291  }
292  }
293  }
294  }
295  }
296  }
297 
298  //Build array of quantity ordered by product
299  if (is_array($order->lines) && count($order->lines)>0) {
300  foreach($order->lines as $orderline) {
301  $qtyordred[$orderline->fk_product]+=$orderline->qty;
302  }
303  }
304  //dol_syslog(var_export($qtyordred,true),LOG_DEBUG);
305  //dol_syslog(var_export($qtyshipped,true),LOG_DEBUG);
306  //Compare array
307  $diff_array=array_diff_assoc($qtyordred,$qtyshipped);
308  if (count($diff_array)==0) {
309  //No diff => mean everythings is shipped
310  $ret=$object->setStatut(Commande::STATUS_CLOSED, $object->origin_id, $object->origin);
311  if ($ret<0) {
312  $this->error=$object->error; $this->errors=$object->errors;
313  return $ret;
314  }
315  }
316  }
317  }
318 
319  return 0;
320  }
321 }
Class to stock current configuration.
Definition: conf.class.php:33
const STATUS_CLOSED
Closed (Sent, billed or not)
const STATUS_RECEIVED_COMPLETELY
Received completely.
runTrigger($action, $object, User $user, Translate $langs, Conf $conf)
Function called when a Dolibarrr business event is done.
Class to manage Dolibarr users.
Definition: user.class.php:41
const STATUS_SHIPMENTONPROCESS
Shipment on process.
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition: repair.php:103
const STATUS_SIGNED
Signed quote.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='')
Write log message into outputs.
const STATUS_BILLED
Billed or processed quote.
const STATUS_SIGNED
Signed quote.
const STATUS_RECEIVED_PARTIALLY
Received partially.
Class to manage customers orders.
Class to manage translations.
Class that all the triggers must extend.
const STATUS_VALIDATED
Validated status.
const STATUS_ORDERSENT
Order sent, shipment on process.
Class to manage invoices.