dolibarr  7.0.0-beta
interface_20_modWorkflow_WorkflowManager.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2010 Regis Houssin <regis.houssin@capnetworks.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 {
35  public $picto = 'technic';
36  public $family = 'core';
37  public $description = "Triggers of this module allows to manage workflows";
38  public $version = self::VERSION_DOLIBARR;
39 
51  public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf)
52  {
53  if (empty($conf->workflow->enabled)) return 0; // Module not active, we do nothing
54 
55  // Proposals to order
56  if ($action == 'PROPAL_CLOSE_SIGNED')
57  {
58  dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
59  if (! empty($conf->commande->enabled) && ! empty($conf->global->WORKFLOW_PROPAL_AUTOCREATE_ORDER))
60  {
61  include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
62  $newobject = new Commande($this->db);
63 
64  $newobject->context['createfrompropal'] = 'createfrompropal';
65  $newobject->context['origin'] = $object->element;
66  $newobject->context['origin_id'] = $object->id;
67 
68  $ret=$newobject->createFromProposal($object, $user);
69  if ($ret < 0) { $this->error=$newobject->error; $this->errors[]=$newobject->error; }
70  return $ret;
71  }
72  }
73 
74  // Order to invoice
75  if ($action == 'ORDER_CLOSE')
76  {
77  dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
78  if (! empty($conf->facture->enabled) && ! empty($conf->global->WORKFLOW_ORDER_AUTOCREATE_INVOICE))
79  {
80  include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
81  $newobject = new Facture($this->db);
82 
83  $newobject->context['createfromorder'] = 'createfromorder';
84  $newobject->context['origin'] = $object->element;
85  $newobject->context['origin_id'] = $object->id;
86 
87  $ret=$newobject->createFromOrder($object, $user);
88  if ($ret < 0) { $this->error=$newobject->error; $this->errors[]=$newobject->error; }
89  return $ret;
90  }
91  }
92 
93  // Order classify billed proposal
94  if ($action == 'ORDER_CLASSIFY_BILLED')
95  {
96  dol_syslog( "Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id );
97  if (! empty($conf->propal->enabled) && ! empty($conf->global->WORKFLOW_ORDER_CLASSIFY_BILLED_PROPAL))
98  {
99  $object->fetchObjectLinked('','propal',$object->id,$object->element);
100  if (! empty($object->linkedObjects))
101  {
102  $totalonlinkedelements=0;
103  foreach($object->linkedObjects['propal'] as $element)
104  {
105  if ($element->statut == Propal::STATUS_SIGNED || $element->statut == Propal::STATUS_BILLED) $totalonlinkedelements += $element->total_ht;
106  }
107  dol_syslog( "Amount of linked proposals = ".$totalonlinkedelements.", of order = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) );
108  if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) )
109  {
110  foreach($object->linkedObjects['propal'] as $element)
111  {
112  $ret=$element->classifyBilled($user);
113  }
114  }
115  }
116  return $ret;
117  }
118  }
119 
120  // classify billed order & billed propososal
121  if ($action == 'BILL_VALIDATE')
122  {
123  dol_syslog( "Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id );
124 
125  // First classify billed the order to allow the proposal classify process
126  if (! empty($conf->commande->enabled) && ! empty($conf->global->WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER))
127  {
128  $object->fetchObjectLinked('','commande',$object->id,$object->element);
129  if (! empty($object->linkedObjects))
130  {
131  $totalonlinkedelements=0;
132  foreach($object->linkedObjects['commande'] as $element)
133  {
134  if ($element->statut == Commande::STATUS_VALIDATED || $element->statut == Commande::STATUS_SHIPMENTONPROCESS || $element->statut == Commande::STATUS_CLOSED) $totalonlinkedelements += $element->total_ht;
135  }
136  dol_syslog( "Amount of linked orders = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) );
137  if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) )
138  {
139  foreach($object->linkedObjects['commande'] as $element)
140  {
141  $ret=$element->classifyBilled($user);
142  }
143  }
144  }
145  return $ret;
146  }
147 
148  // Second classify billed the proposal.
149  if (! empty($conf->propal->enabled) && ! empty($conf->global->WORKFLOW_INVOICE_CLASSIFY_BILLED_PROPAL))
150  {
151  $object->fetchObjectLinked('','propal',$object->id,$object->element);
152  if (! empty($object->linkedObjects))
153  {
154  $totalonlinkedelements=0;
155  foreach($object->linkedObjects['propal'] as $element)
156  {
157  if ($element->statut == Propal::STATUS_SIGNED || $element->statut == Propal::STATUS_BILLED) $totalonlinkedelements += $element->total_ht;
158  }
159  dol_syslog( "Amount of linked proposals = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) );
160  if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) )
161  {
162  foreach($object->linkedObjects['propal'] as $element)
163  {
164  $ret=$element->classifyBilled($user);
165  }
166  }
167  }
168  return $ret;
169  }
170  }
171 
172  // classify billed order & billed propososal
173  if ($action == 'BILL_SUPPLIER_VALIDATE')
174  {
175  dol_syslog( "Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id );
176 
177  // First classify billed the order to allow the proposal classify process
178  if (! empty($conf->fournisseur->commande->enabled) && ! empty($conf->global->WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER))
179  {
180  $object->fetchObjectLinked('','order_supplier',$object->id,$object->element);
181  if (! empty($object->linkedObjects))
182  {
183  $totalonlinkedelements=0;
184  foreach($object->linkedObjects['order_supplier'] as $element)
185  {
186  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;
187  }
188  dol_syslog( "Amount of linked orders = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) );
189  if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) )
190  {
191  foreach($object->linkedObjects['order_supplier'] as $element)
192  {
193  $ret=$element->classifyBilled($user);
194  }
195  }
196  }
197  return $ret;
198  }
199 
200  // Second classify billed the proposal.
201  if (! empty($conf->supplier_proposal->enabled) && ! empty($conf->global->WORKFLOW_INVOICE_CLASSIFY_BILLED_SUPPLIER_PROPOSAL))
202  {
203  $object->fetchObjectLinked('','supplier_proposal',$object->id,$object->element);
204  if (! empty($object->linkedObjects))
205  {
206  $totalonlinkedelements=0;
207  foreach($object->linkedObjects['supplier_proposal'] as $element)
208  {
209  if ($element->statut == SupplierProposal::STATUS_SIGNED || $element->statut == SupplierProposal::STATUS_BILLED) $totalonlinkedelements += $element->total_ht;
210  }
211  dol_syslog( "Amount of linked supplier proposals = ".$totalonlinkedelements.", of supplier invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) );
212  if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) )
213  {
214  foreach($object->linkedObjects['supplier_proposal'] as $element)
215  {
216  $ret=$element->classifyBilled($user);
217  }
218  }
219  }
220  return $ret;
221  }
222  }
223 
224  // Invoice classify billed order
225  if ($action == 'BILL_PAYED')
226  {
227  dol_syslog( "Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id );
228 
229  if (! empty($conf->commande->enabled) && ! empty($conf->global->WORKFLOW_INVOICE_CLASSIFY_BILLED_ORDER))
230  {
231  $object->fetchObjectLinked('','commande',$object->id,$object->element);
232  if (! empty($object->linkedObjects))
233  {
234  $totalonlinkedelements=0;
235  foreach($object->linkedObjects['commande'] as $element)
236  {
237  if ($element->statut == Commande::STATUS_VALIDATED || $element->statut == Commande::STATUS_SHIPMENTONPROCESS || $element->statut == Commande::STATUS_CLOSED) $totalonlinkedelements += $element->total_ht;
238  }
239  dol_syslog( "Amount of linked orders = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht) );
240  if ( ($totalonlinkedelements == $object->total_ht) || (! empty($conf->global->WORKFLOW_CLASSIFY_IF_AMOUNTS_ARE_DIFFERENTS)) )
241  {
242  foreach($object->linkedObjects['commande'] as $element)
243  {
244  $ret=$element->classifyBilled($user);
245  }
246  }
247  }
248  return $ret;
249  }
250  }
251 
252  if ($action=='SHIPPING_VALIDATE')
253  {
254  dol_syslog( "Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id );
255 
256  if (! empty($conf->commande->enabled) && ! empty($conf->expedition->enabled) && ! empty($conf->global->WORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING))
257  {
258  $qtyshipped=array();
259  $qtyordred=array();
260  require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
261 
262  //find all shippement on order origin
263  $order = new Commande($this->db);
264  $ret=$order->fetch($object->origin_id);
265  if ($ret<0) {
266  $this->error=$order->error; $this->errors=$order->errors;
267  return $ret;
268  }
269  $ret=$order->fetchObjectLinked($order->id,'commande',null,'shipping');
270  if ($ret<0) {
271  $this->error=$order->error; $this->errors=$order->errors;
272  return $ret;
273  }
274  //Build array of quantity shipped by product for an order
275  if (is_array($order->linkedObjects) && count($order->linkedObjects)>0) {
276  foreach($order->linkedObjects as $type=>$shipping_array) {
277  if ($type=='shipping' && is_array($shipping_array) && count($shipping_array)>0) {
278  foreach ($shipping_array as $shipping) {
279  if (is_array($shipping->lines) && count($shipping->lines)>0) {
280  foreach($shipping->lines as $shippingline) {
281  $qtyshipped[$shippingline->fk_product]+=$shippingline->qty;
282  }
283  }
284  }
285  }
286  }
287  }
288 
289  //Build array of quantity ordered by product
290  if (is_array($order->lines) && count($order->lines)>0) {
291  foreach($order->lines as $orderline) {
292  $qtyordred[$orderline->fk_product]+=$orderline->qty;
293  }
294  }
295  //dol_syslog(var_export($qtyordred,true),LOG_DEBUG);
296  //dol_syslog(var_export($qtyshipped,true),LOG_DEBUG);
297  //Compare array
298  $diff_array=array_diff_assoc($qtyordred,$qtyshipped);
299  if (count($diff_array)==0) {
300  //No diff => mean everythings is shipped
301  $ret=$object->setStatut(Commande::STATUS_CLOSED, $object->origin_id, $object->origin);
302  if ($ret<0) {
303  $this->error=$object->error; $this->errors=$object->errors;
304  return $ret;
305  }
306  }
307  }
308  }
309 
310  return 0;
311  }
312 
313 }
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:39
const STATUS_SHIPMENTONPROCESS
Shipment on process.
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.
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition: repair.php:104
const STATUS_VALIDATED
Validated status.
const STATUS_ORDERSENT
Order sent, shipment on process.
Class to manage invoices.