dolibarr  13.0.2
mo_production.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2019-2020 Laurent Destailleur <eldy@users.sourceforge.net>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
24 // Load Dolibarr environment
25 require '../main.inc.php';
26 
27 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
28 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
29 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
30 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
31 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
32 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
35 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
36 dol_include_once('/mrp/class/mo.class.php');
37 dol_include_once('/mrp/lib/mrp_mo.lib.php');
38 
39 // Load translation files required by the page
40 $langs->loadLangs(array("mrp", "stocks", "other", "productbatch"));
41 
42 // Get parameters
43 $id = GETPOST('id', 'int');
44 $ref = GETPOST('ref', 'alpha');
45 $action = GETPOST('action', 'aZ09');
46 $confirm = GETPOST('confirm', 'alpha');
47 $cancel = GETPOST('cancel', 'aZ09');
48 $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'mocard'; // To manage different context of search
49 $backtopage = GETPOST('backtopage', 'alpha');
50 //$lineid = GETPOST('lineid', 'int');
51 
52 $collapse = GETPOST('collapse', 'aZ09comma');
53 
54 // Initialize technical objects
55 $object = new Mo($db);
56 $extrafields = new ExtraFields($db);
57 $diroutputmassaction = $conf->mrp->dir_output.'/temp/massgeneration/'.$user->id;
58 $hookmanager->initHooks(array('mocard', 'globalcard')); // Note that conf->hooks_modules contains array
59 
60 // Fetch optionals attributes and labels
61 $extrafields->fetch_name_optionals_label($object->table_element);
62 
63 $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
64 
65 // Initialize array of search criterias
66 $search_all = GETPOST("search_all", 'alpha');
67 $search = array();
68 foreach ($object->fields as $key => $val)
69 {
70  if (GETPOST('search_'.$key, 'alpha')) $search[$key] = GETPOST('search_'.$key, 'alpha');
71 }
72 
73 if (empty($action) && empty($id) && empty($ref)) $action = 'view';
74 
75 // Load object
76 include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once.
77 
78 // Security check - Protection if external user
79 //if ($user->socid > 0) accessforbidden();
80 //if ($user->socid > 0) $socid = $user->socid;
81 $isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
82 $result = restrictedArea($user, 'mrp', $object->id, 'mrp_mo', '', 'fk_soc', 'rowid', $isdraft);
83 
84 $permissionnote = $user->rights->mrp->write; // Used by the include of actions_setnotes.inc.php
85 $permissiondellink = $user->rights->mrp->write; // Used by the include of actions_dellink.inc.php
86 $permissiontoadd = $user->rights->mrp->write; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php
87 $permissiontodelete = $user->rights->mrp->delete || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT);
88 $upload_dir = $conf->mrp->multidir_output[isset($object->entity) ? $object->entity : 1];
89 
90 $permissiontoproduce = $permissiontoadd;
91 
92 
93 /*
94  * Actions
95  */
96 
97 $parameters = array();
98 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
99 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
100 
101 if (empty($reshook))
102 {
103  $error = 0;
104 
105  $backurlforlist = dol_buildpath('/mrp/mo_list.php', 1);
106 
107  if (empty($backtopage) || ($cancel && empty($id))) {
108  //var_dump($backurlforlist);exit;
109  if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) $backtopage = $backurlforlist;
110  else $backtopage = DOL_URL_ROOT.'/mrp/mo_production.php?id='.($id > 0 ? $id : '__ID__');
111  }
112  $triggermodname = 'MRP_MO_MODIFY'; // Name of trigger action code to execute when we modify record
113 
114  // Actions cancel, add, update, delete or clone
115  include DOL_DOCUMENT_ROOT.'/core/actions_addupdatedelete.inc.php';
116 
117  // Actions when linking object each other
118  include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php';
119 
120  // Actions when printing a doc from card
121  include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
122 
123  // Actions to send emails
124  $triggersendname = 'MO_SENTBYMAIL';
125  $autocopy = 'MAIN_MAIL_AUTOCOPY_MO_TO';
126  $trackid = 'mo'.$object->id;
127  include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
128 
129  // Action to move up and down lines of object
130  //include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; // Must be include, not include_once
131 
132  if ($action == 'set_thirdparty' && $permissiontoadd)
133  {
134  $object->setValueFrom('fk_soc', GETPOST('fk_soc', 'int'), '', '', 'date', '', $user, 'MO_MODIFY');
135  }
136  if ($action == 'classin' && $permissiontoadd)
137  {
138  $object->setProject(GETPOST('projectid', 'int'));
139  }
140 
141  if ($action == 'confirm_reopen') {
142  $result = $object->setStatut($object::STATUS_INPROGRESS, 0, '', 'MRP_REOPEN');
143  }
144 
145  if ($action == 'confirm_addconsumeline' && GETPOST('addconsumelinebutton')) {
146  $moline = new MoLine($db);
147 
148  // Line to produce
149  $moline->fk_mo = $object->id;
150  $moline->qty = GETPOST('qtytoadd', 'int'); ;
151  $moline->fk_product = GETPOST('productidtoadd', 'int');
152  $moline->role = 'toconsume';
153  $moline->position = 0;
154 
155  $resultline = $moline->create($user, false); // Never use triggers here
156  if ($resultline <= 0) {
157  $error++;
158  setEventMessages($moline->error, $molines->errors, 'errors');
159  }
160 
161  $action = '';
162  }
163 
164  if (in_array($action, array('confirm_consumeorproduce', 'confirm_consumeandproduceall'))) {
165  $stockmove = new MouvementStock($db);
166 
167  $labelmovement = GETPOST('inventorylabel', 'alphanohtml');
168  $codemovement = GETPOST('inventorycode', 'alphanohtml');
169 
170  $db->begin();
171 
172  // Process line to consume
173  foreach ($object->lines as $line) {
174  if ($line->role == 'toconsume') {
175  $tmpproduct = new Product($db);
176  $tmpproduct->fetch($line->fk_product);
177 
178  $i = 1;
179  while (GETPOSTISSET('qty-'.$line->id.'-'.$i)) {
180  $qtytoprocess = price2num(GETPOST('qty-'.$line->id.'-'.$i));
181 
182  if ($qtytoprocess != 0) {
183  // Check warehouse is set if we should have to
184  if (GETPOSTISSET('idwarehouse-'.$line->id.'-'.$i)) { // If there is a warehouse to set
185  if (!(GETPOST('idwarehouse-'.$line->id.'-'.$i) > 0)) { // If there is no warehouse set.
186  $langs->load("errors");
187  setEventMessages($langs->trans("ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv("Warehouse"), $tmpproduct->ref), null, 'errors');
188  $error++;
189  }
190  if ($tmpproduct->status_batch && (!GETPOST('batch-'.$line->id.'-'.$i))) {
191  $langs->load("errors");
192  setEventMessages($langs->trans("ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv("Batch"), $tmpproduct->ref), null, 'errors');
193  $error++;
194  }
195  }
196 
197  $idstockmove = 0;
198  if (!$error && GETPOST('idwarehouse-'.$line->id.'-'.$i) > 0) {
199  // Record stock movement
200  $id_product_batch = 0;
201  $stockmove->origin = $object;
202  $idstockmove = $stockmove->livraison($user, $line->fk_product, GETPOST('idwarehouse-'.$line->id.'-'.$i), $qtytoprocess, 0, $labelmovement, dol_now(), '', '', GETPOST('batch-'.$line->id.'-'.$i), $id_product_batch, $codemovement);
203  if ($idstockmove < 0) {
204  $error++;
205  setEventMessages($stockmove->error, $stockmove->errors, 'errors');
206  }
207  }
208 
209  if (!$error) {
210  $pos = 0;
211  // Record consumption
212  $moline = new MoLine($db);
213  $moline->fk_mo = $object->id;
214  $moline->position = $pos;
215  $moline->fk_product = $line->fk_product;
216  $moline->fk_warehouse = GETPOST('idwarehouse-'.$line->id.'-'.$i);
217  $moline->qty = $qtytoprocess;
218  $moline->batch = GETPOST('batch-'.$line->id.'-'.$i);
219  $moline->role = 'consumed';
220  $moline->fk_mrp_production = $line->id;
221  $moline->fk_stock_movement = $idstockmove;
222  $moline->fk_user_creat = $user->id;
223 
224  $resultmoline = $moline->create($user);
225  if ($resultmoline <= 0) {
226  $error++;
227  setEventMessages($moline->error, $moline->errors, 'errors');
228  }
229 
230  $pos++;
231  }
232  }
233 
234  $i++;
235  }
236  }
237  }
238 
239  // Process line to produce
240  foreach ($object->lines as $line) {
241  if ($line->role == 'toproduce') {
242  $tmpproduct = new Product($db);
243  $tmpproduct->fetch($line->fk_product);
244 
245  $i = 1;
246  while (GETPOSTISSET('qtytoproduce-'.$line->id.'-'.$i)) {
247  $qtytoprocess = price2num(GETPOST('qtytoproduce-'.$line->id.'-'.$i));
248 
249  if ($qtytoprocess != 0) {
250  // Check warehouse is set if we should have to
251  if (GETPOSTISSET('idwarehousetoproduce-'.$line->id.'-'.$i)) { // If there is a warehouse to set
252  if (!(GETPOST('idwarehousetoproduce-'.$line->id.'-'.$i) > 0)) { // If there is no warehouse set.
253  $langs->load("errors");
254  setEventMessages($langs->trans("ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv("Warehouse"), $tmpproduct->ref), null, 'errors');
255  $error++;
256  }
257  if (!empty($conf->productbatch->enabled) && $tmpproduct->status_batch && (!GETPOST('batchtoproduce-'.$line->id.'-'.$i))) {
258  $langs->load("errors");
259  setEventMessages($langs->trans("ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv("Batch"), $tmpproduct->ref), null, 'errors');
260  $error++;
261  }
262  }
263 
264  $idstockmove = 0;
265  if (!$error && GETPOST('idwarehousetoproduce-'.$line->id.'-'.$i) > 0) {
266  // Record stock movement
267  $id_product_batch = 0;
268  $stockmove->origin = $object;
269  $idstockmove = $stockmove->reception($user, $line->fk_product, GETPOST('idwarehousetoproduce-'.$line->id.'-'.$i), $qtytoprocess, 0, $labelmovement, '', '', GETPOST('batchtoproduce-'.$line->id.'-'.$i), dol_now(), $id_product_batch, $codemovement);
270  if ($idstockmove < 0) {
271  $error++;
272  setEventMessages($stockmove->error, $stockmove->errors, 'errors');
273  }
274  }
275 
276  if (!$error) {
277  $pos = 0;
278  // Record production
279  $moline = new MoLine($db);
280  $moline->fk_mo = $object->id;
281  $moline->position = $pos;
282  $moline->fk_product = $line->fk_product;
283  $moline->fk_warehouse = GETPOST('idwarehousetoproduce-'.$line->id.'-'.$i);
284  $moline->qty = $qtytoprocess;
285  $moline->batch = GETPOST('batchtoproduce-'.$line->id.'-'.$i);
286  $moline->role = 'produced';
287  $moline->fk_mrp_production = $line->id;
288  $moline->fk_stock_movement = $idstockmove;
289  $moline->fk_user_creat = $user->id;
290 
291  $resultmoline = $moline->create($user);
292  if ($resultmoline <= 0) {
293  $error++;
294  setEventMessages($moline->error, $moline->errors, 'errors');
295  }
296 
297  $pos++;
298  }
299  }
300 
301  $i++;
302  }
303  }
304  }
305 
306  if (!$error) {
307  $consumptioncomplete = true;
308  $productioncomplete = true;
309 
310  if (GETPOST('autoclose', 'int')) {
311  foreach ($object->lines as $line) {
312  if ($line->role == 'toconsume') {
313  $arrayoflines = $object->fetchLinesLinked('consumed', $line->id);
314  $alreadyconsumed = 0;
315  foreach ($arrayoflines as $line2) {
316  $alreadyconsumed += $line2['qty'];
317  }
318 
319  if ($alreadyconsumed < $line->qty) {
320  $consumptioncomplete = false;
321  }
322  }
323  if ($line->role == 'toproduce') {
324  $arrayoflines = $object->fetchLinesLinked('produced', $line->id);
325  $alreadyproduced = 0;
326  foreach ($arrayoflines as $line2) {
327  $alreadyproduced += $line2['qty'];
328  }
329 
330  if ($alreadyproduced < $line->qty) {
331  $productioncomplete = false;
332  }
333  }
334  }
335  } else {
336  $consumptioncomplete = false;
337  $productioncomplete = false;
338  }
339 
340  // Update status of MO
341  dol_syslog("consumptioncomplete = ".$consumptioncomplete." productioncomplete = ".$productioncomplete);
342  //var_dump("consumptioncomplete = ".$consumptioncomplete." productioncomplete = ".$productioncomplete);
343  if ($consumptioncomplete && $productioncomplete) {
344  $result = $object->setStatut($object::STATUS_PRODUCED, 0, '', 'MRP_MO_PRODUCED');
345  } else {
346  $result = $object->setStatut($object::STATUS_INPROGRESS, 0, '', 'MRP_MO_PRODUCED');
347  }
348  if ($result <= 0) {
349  $error++;
350  setEventMessages($object->error, $object->errors, 'errors');
351  }
352  }
353 
354  if ($error) {
355  $action = str_replace('confirm_', '', $action);
356  $db->rollback();
357  } else {
358  $db->commit();
359 
360  // Redirect to avoid to action done a second time if we make a back from browser
361  header("Location: ".$_SERVER["PHP_SELF"].'?id='.$object->id);
362  exit;
363  }
364  }
365 
366  // Action close produced
367  if ($action == 'confirm_produced' && $confirm == 'yes' && $permissiontoadd)
368  {
369  $result = $object->setStatut($object::STATUS_PRODUCED, 0, '', 'MRP_MO_PRODUCED');
370  if ($result >= 0)
371  {
372  // Define output language
373  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
374  {
375  $outputlangs = $langs;
376  $newlang = '';
377  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09');
378  if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
379  if (!empty($newlang)) {
380  $outputlangs = new Translate("", $conf);
381  $outputlangs->setDefaultLang($newlang);
382  }
383  $model = $object->model_pdf;
384  $ret = $object->fetch($id); // Reload to get new records
385 
386  $object->generateDocument($model, $outputlangs, 0, 0, 0);
387  }
388  } else {
389  setEventMessages($object->error, $object->errors, 'errors');
390  }
391  }
392 }
393 
394 
395 
396 /*
397  * View
398  */
399 
400 $form = new Form($db);
401 $formproject = new FormProjets($db);
402 $formproduct = new FormProduct($db);
403 $tmpwarehouse = new Entrepot($db);
404 $tmpbatch = new Productlot($db);
405 
406 $help_url = 'EN:Module_Manufacturing_Orders|FR:Module_Ordres_de_Fabrication';
407 llxHeader('', $langs->trans('Mo'), $help_url, '', 0, 0, array('/mrp/js/lib_dispatch.js.php'));
408 
409 // Part to show record
410 if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create')))
411 {
412  $res = $object->fetch_thirdparty();
413  $res = $object->fetch_optionals();
414 
415  $head = moPrepareHead($object);
416 
417  print dol_get_fiche_head($head, 'production', $langs->trans("ManufacturingOrder"), -1, $object->picto);
418 
419  $formconfirm = '';
420 
421  // Confirmation to delete
422  if ($action == 'delete')
423  {
424  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteMo'), $langs->trans('ConfirmDeleteMo'), 'confirm_delete', '', 0, 1);
425  }
426  // Confirmation to delete line
427  if ($action == 'deleteline')
428  {
429  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1);
430  }
431  // Clone confirmation
432  if ($action == 'clone') {
433  // Create an array for form
434  $formquestion = array();
435  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneMo', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
436  }
437 
438  // Confirmation of validation
439  if ($action == 'validate')
440  {
441  // We check that object has a temporary ref
442  $ref = substr($object->ref, 1, 4);
443  if ($ref == 'PROV') {
444  $object->fetch_product();
445  $numref = $object->getNextNumRef($object->fk_product);
446  } else {
447  $numref = $object->ref;
448  }
449 
450  $text = $langs->trans('ConfirmValidateMo', $numref);
451  /*if (! empty($conf->notification->enabled))
452  {
453  require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
454  $notify = new Notify($db);
455  $text .= '<br>';
456  $text .= $notify->confirmMessage('BOM_VALIDATE', $object->socid, $object);
457  }*/
458 
459  $formquestion = array();
460  if (!empty($conf->mrp->enabled))
461  {
462  $langs->load("mrp");
463  require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
464  $formproduct = new FormProduct($db);
465  $forcecombo = 0;
466  if ($conf->browser->name == 'ie') $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
467  $formquestion = array(
468  // 'text' => $langs->trans("ConfirmClone"),
469  // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
470  // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
471  );
472  }
473 
474  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('Validate'), $text, 'confirm_validate', $formquestion, 0, 1, 220);
475  }
476 
477  // Call Hook formConfirm
478  $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
479  $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
480  if (empty($reshook)) $formconfirm .= $hookmanager->resPrint;
481  elseif ($reshook > 0) $formconfirm = $hookmanager->resPrint;
482 
483  // Print form confirm
484  print $formconfirm;
485 
486 
487  // Object card
488  // ------------------------------------------------------------
489  $linkback = '<a href="'.dol_buildpath('/mrp/mo_list.php', 1).'?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
490 
491  $morehtmlref = '<div class="refidno">';
492  /*
493  // Ref bis
494  $morehtmlref.=$form->editfieldkey("RefBis", 'ref_client', $object->ref_client, $object, $user->rights->mrp->creer, 'string', '', 0, 1);
495  $morehtmlref.=$form->editfieldval("RefBis", 'ref_client', $object->ref_client, $object, $user->rights->mrp->creer, 'string', '', null, null, '', 1);*/
496  // Thirdparty
497  $morehtmlref .= $langs->trans('ThirdParty').' : '.(is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : '');
498  // Project
499  if (!empty($conf->projet->enabled))
500  {
501  $langs->load("projects");
502  $morehtmlref .= '<br>'.$langs->trans('Project').' ';
503  if ($permissiontoadd)
504  {
505  if ($action != 'classify')
506  $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&amp;id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> : ';
507  if ($action == 'classify') {
508  //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->fk_soc, $object->fk_project, 'projectid', 0, 0, 1, 1);
509  $morehtmlref .= '<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
510  $morehtmlref .= '<input type="hidden" name="action" value="classin">';
511  $morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">';
512  $morehtmlref .= $formproject->select_projects($object->fk_soc, $object->fk_project, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1);
513  $morehtmlref .= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
514  $morehtmlref .= '</form>';
515  } else {
516  $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_soc, $object->fk_project, 'none', 0, 0, 0, 1);
517  }
518  } else {
519  if (!empty($object->fk_project)) {
520  $proj = new Project($db);
521  $proj->fetch($object->fk_project);
522  $morehtmlref .= $proj->getNomUrl();
523  } else {
524  $morehtmlref .= '';
525  }
526  }
527  }
528  $morehtmlref .= '</div>';
529 
530 
531  dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
532 
533 
534  print '<div class="fichecenter">';
535  print '<div class="fichehalfleft">';
536  print '<div class="underbanner clearboth"></div>';
537  print '<table class="border centpercent tableforfield">'."\n";
538 
539  // Common attributes
540  $keyforbreak = 'fk_warehouse';
541  unset($object->fields['fk_project']);
542  unset($object->fields['fk_soc']);
543  include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php';
544 
545  // Other attributes
546  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
547 
548  print '</table>';
549  print '</div>';
550  print '</div>';
551 
552  print '<div class="clearboth"></div>';
553 
555 
556 
557  if (!in_array($action, array('consumeorproduce', 'consumeandproduceall')))
558  {
559  print '<div class="tabsAction">';
560 
561  $parameters = array();
562  // Note that $action and $object may be modified by hook
563  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action);
564  if (empty($reshook)) {
565  // Validate
566  if ($object->status == $object::STATUS_DRAFT)
567  {
568  if ($permissiontoadd)
569  {
570  if (empty($object->table_element_line) || (is_array($object->lines) && count($object->lines) > 0))
571  {
572  print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=validate">'.$langs->trans("Validate").'</a>';
573  } else {
574  $langs->load("errors");
575  print '<a class="butActionRefused" href="" title="'.$langs->trans("ErrorAddAtLeastOneLineFirst").'">'.$langs->trans("Validate").'</a>';
576  }
577  }
578  }
579 
580  // Consume or produce
581  if ($object->status == Mo::STATUS_VALIDATED || $object->status == Mo::STATUS_INPROGRESS) {
582  if ($permissiontoproduce) {
583  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=consumeorproduce">'.$langs->trans('ConsumeOrProduce').'</a>';
584  } else {
585  print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotEnoughPermissions").'">'.$langs->trans('ConsumeOrProduce').'</a>';
586  }
587  } elseif ($object->status == Mo::STATUS_DRAFT) {
588  print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("ValidateBefore").'">'.$langs->trans('ConsumeOrProduce').'</a>';
589  }
590 
591  // ConsumeAndProduceAll
592  if ($object->status == Mo::STATUS_VALIDATED || $object->status == Mo::STATUS_INPROGRESS) {
593  if ($permissiontoproduce) {
594  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=consumeandproduceall">'.$langs->trans('ConsumeAndProduceAll').'</a>';
595  } else {
596  print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotEnoughPermissions").'">'.$langs->trans('ConsumeAndProduceAll').'</a>';
597  }
598  } elseif ($object->status == Mo::STATUS_DRAFT) {
599  print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("ValidateBefore").'">'.$langs->trans('ConsumeAndProduceAll').'</a>';
600  }
601 
602  // Cancel - Reopen
603  if ($permissiontoadd)
604  {
605  if ($object->status == $object::STATUS_VALIDATED || $object->status == $object::STATUS_INPROGRESS)
606  {
607  $arrayproduced = $object->fetchLinesLinked('produced', 0);
608  $nbProduced = 0;
609  foreach ($arrayproduced as $lineproduced) {
610  $nbProduced += $lineproduced['qty'];
611  }
612  if ($nbProduced > 0) { // If production has started, we can close it
613  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=confirm_produced&confirm=yes">'.$langs->trans("Close").'</a>'."\n";
614  } else {
615  print '<a class="butActionRefused" href="#" title="'.$langs->trans("GoOnTabProductionToProduceFirst", $langs->transnoentitiesnoconv("Production")).'">'.$langs->trans("Close").'</a>'."\n";
616  }
617 
618  print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=confirm_close&confirm=yes">'.$langs->trans("Cancel").'</a>'."\n";
619  }
620 
621  if ($object->status == $object::STATUS_CANCELED)
622  {
623  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=confirm_reopen&confirm=yes">'.$langs->trans("Re-Open").'</a>'."\n";
624  }
625 
626  if ($object->status == $object::STATUS_PRODUCED) {
627  if ($permissiontoproduce) {
628  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=confirm_reopen">'.$langs->trans('ReOpen').'</a>';
629  } else {
630  print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotEnoughPermissions").'">'.$langs->trans('ReOpen').'</a>';
631  }
632  }
633  }
634  }
635 
636  print '</div>';
637  }
638 
639  if (in_array($action, array('consumeorproduce', 'consumeandproduceall', 'addconsumeline')))
640  {
641  print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
642  print '<input type="hidden" name="token" value="'.newToken().'">';
643  print '<input type="hidden" name="action" value="confirm_'.$action.'">';
644  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
645  print '<input type="hidden" name="id" value="'.$id.'">';
646  // Note: closing form is add end of page
647 
648  if (in_array($action, array('consumeorproduce', 'consumeandproduceall'))) {
649  $defaultstockmovementlabel = GETPOST('inventorylabel', 'alphanohtml') ? GETPOST('inventorylabel', 'alphanohtml') : $langs->trans("ProductionForRef", $object->ref);
650  //$defaultstockmovementcode = GETPOST('inventorycode', 'alphanohtml') ? GETPOST('inventorycode', 'alphanohtml') : $object->ref.'_'.dol_print_date(dol_now(), 'dayhourlog');
651  $defaultstockmovementcode = GETPOST('inventorycode', 'alphanohtml') ? GETPOST('inventorycode', 'alphanohtml') : $langs->trans("ProductionForRef", $object->ref);
652 
653  print '<div class="center'.(in_array($action, array('consumeorproduce', 'consumeandproduceall')) ? ' formconsumeproduce' : '').'">';
654  print '<span class="opacitymedium hideonsmartphone">'.$langs->trans("ConfirmProductionDesc", $langs->transnoentitiesnoconv("Confirm")).'<br></span>';
655  print '<span class="fieldrequired">'.$langs->trans("InventoryCode").':</span> <input type="text" class="maxwidth200" name="inventorycode" value="'.$defaultstockmovementcode.'"> &nbsp; ';
656  print '<span class="clearbothonsmartphone"></span>';
657  print $langs->trans("MovementLabel").': <input type="text" class="minwidth300" name="inventorylabel" value="'.$defaultstockmovementlabel.'"><br><br>';
658  print '<input type="checkbox" id="autoclose" name="autoclose" value="1"'.(GETPOSTISSET('inventorylabel') ? (GETPOST('autoclose') ? ' checked="checked"' : '') : ' checked="checked"').'> <label for="autoclose">'.$langs->trans("AutoCloseMO").'</label><br>';
659  print '<input class="button" type="submit" value="'.$langs->trans("Confirm").'" name="confirm">';
660  print ' &nbsp; ';
661  print '<input class="button button-cancel" type="submit" value="'.$langs->trans("Cancel").'" name="cancel">';
662  print '<br><br>';
663  print '</div>';
664 
665  print '<br>';
666  }
667  }
668 
669 
670  /*
671  * Lines
672  */
673  $collapse = 1;
674 
675  if (!empty($object->table_element_line))
676  {
677  // Show object lines
678  $object->fetchLines();
679 
680  print '<div class="fichecenter">';
681  print '<div class="fichehalfleft">';
682  print '<div class="clearboth"></div>';
683 
684  $newlinetext = '';
685  if ($action != 'consumeorproduce' && $action != 'consumeandproduceall') {
686  $newlinetext = '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=addconsumeline">'.$langs->trans("AddNewConsumeLines").'</a>';
687  }
688  print load_fiche_titre($langs->trans('Consumption'), '', '', 0, '', '', $newlinetext);
689 
690  print '<div class="div-table-responsive-no-min">';
691  print '<table class="noborder noshadow centpercent nobottom">';
692 
693  print '<tr class="liste_titre">';
694  print '<td>'.$langs->trans("Product").'</td>';
695  print '<td class="right">'.$langs->trans("Qty").'</td>';
696  print '<td class="right">'.$langs->trans("QtyAlreadyConsumed").'</td>';
697  print '<td>';
698  if ($collapse || in_array($action, array('consumeorproduce', 'consumeandproduceall'))) print $langs->trans("Warehouse");
699  print '</td>';
700  if ($conf->productbatch->enabled) {
701  print '<td>';
702  if ($collapse || in_array($action, array('consumeorproduce', 'consumeandproduceall'))) print $langs->trans("Batch");
703  print '</td>';
704  }
705  print '</tr>';
706 
707  if ($action == 'addconsumeline') {
708  print '<!-- Add line to consume -->'."\n";
709  print '<tr class="liste_titre">';
710  print '<td>';
711  print $form->select_produits('', 'productidtoadd', '', 0, 0, -1, 2, '', 0, array(), 0, '1', 0, 'maxwidth300');
712  print '</td>';
713  print '<td class="right"><input type="text" name="qtytoadd" value="1" class="width50 right"></td>';
714  print '<td class="right"></td>';
715  print '<td>';
716  print '<input type="submit" class="button buttongen" name="addconsumelinebutton" value="'.$langs->trans("Add").'">';
717  print '</td>';
718  if ($conf->productbatch->enabled) {
719  print '<td></td>';
720  }
721  print '</tr>';
722  }
723 
724  // Lines to consume
725 
726  if (!empty($object->lines))
727  {
728  $nblinetoconsume = 0;
729  foreach ($object->lines as $line) {
730  if ($line->role == 'toconsume') {
731  $nblinetoconsume++;
732  }
733  }
734 
735  $nblinetoconsumecursor = 0;
736  foreach ($object->lines as $line) {
737  if ($line->role == 'toconsume') {
738  $nblinetoconsumecursor++;
739 
740  $tmpproduct = new Product($db);
741  $tmpproduct->fetch($line->fk_product);
742 
743  $arrayoflines = $object->fetchLinesLinked('consumed', $line->id);
744  $alreadyconsumed = 0;
745  foreach ($arrayoflines as $line2) {
746  $alreadyconsumed += $line2['qty'];
747  }
748 
749  print '<tr>';
750  print '<td>'.$tmpproduct->getNomUrl(1);
751  print '<br><span class="opacitymedium small">'.$tmpproduct->label.'</span>';
752  print '</td>';
753  print '<td class="right nowraponall">';
754  $help = '';
755  if ($line->qty_frozen) $help .= ($help ? '<br>' : '').'<strong>'.$langs->trans("QuantityFrozen").'</strong>: '.yn(1).' ('.$langs->trans("QuantityConsumedInvariable").')';
756  if ($line->disable_stock_change) $help .= ($help ? '<br>' : '').'<strong>'.$langs->trans("DisableStockChange").'</strong>: '.yn(1).' ('.(($tmpproduct->type == Product::TYPE_SERVICE && empty($conf->global->STOCK_SUPPORTS_SERVICES)) ? $langs->trans("NoStockChangeOnServices") : $langs->trans("DisableStockChangeHelp")).')';
757  if ($help) {
758  print $form->textwithpicto($line->qty, $help, -1);
759  } else {
760  print $line->qty;
761  }
762  print '</td>';
763  print '<td class="right">';
764  if ($alreadyconsumed) {
765  print '<script>';
766  print 'jQuery(document).ready(function() {
767  jQuery("#expandtoproduce'.$line->id.'").click(function() {
768  console.log("Expand mrp_production line '.$line->id.'");
769  jQuery(".expanddetail'.$line->id.'").toggle();';
770  if ($nblinetoconsume == $nblinetoconsumecursor) { // If it is the last line
771  print 'if (jQuery("#tablelines").hasClass("nobottom")) { jQuery("#tablelines").removeClass("nobottom"); } else { jQuery("#tablelines").addClass("nobottom"); }';
772  }
773  print '
774  });
775  });';
776  print '</script>';
777  if (empty($conf->use_javascript_ajax)) print '<a href="'.$_SERVER["PHP_SELF"].'?collapse='.$collapse.','.$line->id.'">';
778  print img_picto($langs->trans("ShowDetails"), "chevron-down", 'id="expandtoproduce'.$line->id.'"');
779  if (empty($conf->use_javascript_ajax)) print '</a>';
780  } else {
781  if ($nblinetoconsume == $nblinetoconsumecursor) { // If it is the last line
782  print '<script>jQuery("#tablelines").removeClass("nobottom");</script>';
783  }
784  }
785  print ' '.$alreadyconsumed;
786  print '</td>';
787  print '<td>'; // Warehouse
788  print '</td>';
789  if ($conf->productbatch->enabled) {
790  print '<td></td>'; // Lot
791  }
792  print '</tr>';
793 
794  // Show detailed of already consumed with js code to collapse
795  foreach ($arrayoflines as $line2) {
796  print '<tr class="expanddetail'.$line->id.' hideobject opacitylow">';
797  print '<td>';
798  print dol_print_date($line2['date'], 'dayhour');
799  print '</td>';
800  print '<td></td>';
801  print '<td class="right">'.$line2['qty'].'</td>';
802  print '<td class="tdoverflowmax150">';
803  if ($line2['fk_warehouse'] > 0) {
804  $result = $tmpwarehouse->fetch($line2['fk_warehouse']);
805  if ($result > 0) print $tmpwarehouse->getNomUrl(1);
806  }
807  print '</td>';
808  // Lot Batch
809  print '<td>';
810  if ($line2['batch'] != '') {
811  $tmpbatch->fetch(0, $line2['fk_product'], $line2['batch']);
812  print $tmpbatch->getNomUrl(1);
813  }
814  print '</td>';
815  print '</tr>';
816  }
817 
818  if (in_array($action, array('consumeorproduce', 'consumeandproduceall'))) {
819  $i = 1;
820  print '<!-- Enter line to consume -->'."\n";
821  print '<tr>';
822  print '<td><span class="opacitymedium">'.$langs->trans("ToConsume").'</span></td>';
823  $preselected = (GETPOSTISSET('qty-'.$line->id.'-'.$i) ? GETPOST('qty-'.$line->id.'-'.$i) : max(0, $line->qty - $alreadyconsumed));
824  if ($action == 'consumeorproduce' && !GETPOSTISSET('qty-'.$line->id.'-'.$i)) $preselected = 0;
825  print '<td class="right"><input type="text" class="width50 right" name="qty-'.$line->id.'-'.$i.'" value="'.$preselected.'"></td>';
826  print '<td></td>';
827  print '<td>';
828  if ($tmpproduct->type == Product::TYPE_PRODUCT || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
829  if (empty($line->disable_stock_change)) {
830  $preselected = (GETPOSTISSET('idwarehouse-'.$line->id.'-'.$i) ? GETPOST('idwarehouse-'.$line->id.'-'.$i) : ($tmpproduct->fk_default_warehouse > 0 ? $tmpproduct->fk_default_warehouse : 'ifone'));
831  print $formproduct->selectWarehouses($preselected, 'idwarehouse-'.$line->id.'-'.$i, '', 1, 0, $line->fk_product, '', 1, 0, null, 'maxwidth300');
832  } else {
833  print '<span class="opacitymedium">'.$langs->trans("DisableStockChange").'</span>';
834  }
835  } else {
836  print '<span class="opacitymedium">'.$langs->trans("NoStockChangeOnServices").'</span>';
837  }
838  // Lot / Batch
839  print '</td>';
840  if ($conf->productbatch->enabled) {
841  print '<td>';
842  if ($tmpproduct->status_batch) {
843  $preselected = (GETPOSTISSET('batch-'.$line->id.'-'.$i) ? GETPOST('batch-'.$line->id.'-'.$i) : '');
844  print '<input type="text" class="width50" name="batch-'.$line->id.'-'.$i.'" value="'.$preselected.'">';
845  }
846  print '</td>';
847  }
848  print '</tr>';
849  }
850  }
851  }
852  }
853 
854  print '</table>';
855  print '</div>';
856 
857  // Lines to produce
858 
859  print '</div>';
860  print '<div class="fichehalfright">';
861  print '<div class="clearboth"></div>';
862 
863  print load_fiche_titre($langs->trans('Production'), '', '');
864 
865  print '<div class="div-table-responsive-no-min">';
866  print '<table id="tablelinestoproduce" class="noborder noshadow nobottom centpercent">';
867 
868  print '<tr class="liste_titre">';
869  print '<td>'.$langs->trans("Product").'</td>';
870  print '<td class="right">'.$langs->trans("Qty").'</td>';
871  print '<td class="right">'.$langs->trans("QtyAlreadyProduced").'</td>';
872  print '<td>';
873  if ($collapse || in_array($action, array('consumeorproduce', 'consumeandproduceall'))) print $langs->trans("Warehouse");
874  print '</td>';
875  if ($conf->productbatch->enabled) {
876  print '<td>';
877  if ($collapse || in_array($action, array('consumeorproduce', 'consumeandproduceall'))) print $langs->trans("Batch");
878  print '</td>';
879  print '<td></td>';
880  }
881  print '</tr>';
882 
883  if (!empty($object->lines))
884  {
885  $nblinetoproduce = 0;
886  foreach ($object->lines as $line) {
887  if ($line->role == 'toproduce') {
888  $nblinetoproduce++;
889  }
890  }
891 
892  $nblinetoproducecursor = 0;
893  foreach ($object->lines as $line) {
894  if ($line->role == 'toproduce') {
895  $i = 1;
896 
897  $nblinetoproducecursor++;
898 
899  $tmpproduct = new Product($db);
900  $tmpproduct->fetch($line->fk_product);
901 
902  $arrayoflines = $object->fetchLinesLinked('produced', $line->id);
903  $alreadyproduced = 0;
904  foreach ($arrayoflines as $line2) {
905  $alreadyproduced += $line2['qty'];
906  }
907 
908  $suffix = '_'.$line->id;
909  print '<!-- Line to dispatch '.$suffix.' -->'."\n";
910  // hidden fields for js function
911  print '<input id="qty_ordered'.$suffix.'" type="hidden" value="'.$line->qty.'">';
912  print '<input id="qty_dispatched'.$suffix.'" type="hidden" value="'.$alreadyproduced.'">';
913 
914  print '<tr>';
915  print '<td>'.$tmpproduct->getNomUrl(1);
916  print '<br><span class="opacitymedium small">'.$tmpproduct->label.'</span>';
917  print '</td>';
918  print '<td class="right">'.$line->qty.'</td>';
919  print '<td class="right nowraponall">';
920  if ($alreadyproduced) {
921  print '<script>';
922  print 'jQuery(document).ready(function() {
923  jQuery("#expandtoproduce'.$line->id.'").click(function() {
924  console.log("Expand mrp_production line '.$line->id.'");
925  jQuery(".expanddetailtoproduce'.$line->id.'").toggle();';
926  if ($nblinetoproduce == $nblinetoproducecursor) {
927  print 'if (jQuery("#tablelinestoproduce").hasClass("nobottom")) { jQuery("#tablelinestoproduce").removeClass("nobottom"); } else { jQuery("#tablelinestoproduce").addClass("nobottom"); }';
928  }
929  print '
930  });
931  });';
932  print '</script>';
933  if (empty($conf->use_javascript_ajax)) print '<a href="'.$_SERVER["PHP_SELF"].'?collapse='.$collapse.','.$line->id.'">';
934  print img_picto($langs->trans("ShowDetails"), "chevron-down", 'id="expandtoproduce'.$line->id.'"');
935  if (empty($conf->use_javascript_ajax)) print '</a>';
936  }
937  print ' '.$alreadyproduced;
938  print '</td>';
939  print '<td>'; // Warehouse
940  print '</td>';
941  if ($conf->productbatch->enabled) {
942  print '<td></td>'; // Lot
943  print '<td></td>';
944  }
945  print '</tr>';
946 
947  // Show detailed of already consumed with js code to collapse
948  foreach ($arrayoflines as $line2) {
949  print '<tr class="expanddetailtoproduce'.$line->id.' hideobject opacitylow">';
950  print '<td>';
951  print dol_print_date($line2['date'], 'dayhour');
952  print '</td>';
953  print '<td></td>';
954  print '<td class="right">'.$line2['qty'].'</td>';
955  print '<td class="tdoverflowmax150">';
956  if ($line2['fk_warehouse'] > 0) {
957  $result = $tmpwarehouse->fetch($line2['fk_warehouse']);
958  if ($result > 0) print $tmpwarehouse->getNomUrl(1);
959  }
960  print '</td>';
961  if ($conf->productbatch->enabled) {
962  print '<td>';
963  if ($line2['batch'] != '') {
964  $tmpbatch->fetch(0, $line2['fk_product'], $line2['batch']);
965  print $tmpbatch->getNomUrl(1);
966  }
967  print '</td>';
968  print '<td></td>';
969  }
970  print '</tr>';
971  }
972 
973  if (in_array($action, array('consumeorproduce', 'consumeandproduceall'))) {
974  print '<!-- Enter line to produce -->'."\n";
975  print '<tr name="batch_'.$line->id.'_'.$i.'">';
976  print '<td><span class="opacitymedium">'.$langs->trans("ToProduce").'</span></td>';
977  $preselected = (GETPOSTISSET('qtytoproduce-'.$line->id.'-'.$i) ? GETPOST('qtytoproduce-'.$line->id.'-'.$i) : max(0, $line->qty - $alreadyproduced));
978  if ($action == 'consumeorproduce' && !GETPOSTISSET('qtytoproduce-'.$line->id.'-'.$i)) $preselected = 0;
979  print '<td class="right"><input type="text" class="width50 right" id="qtytoproduce-'.$line->id.'-'.$i.'" name="qtytoproduce-'.$line->id.'-'.$i.'" value="'.$preselected.'"></td>';
980  print '<td></td>';
981  print '<td>';
982  if ($tmpproduct->type == Product::TYPE_PRODUCT || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
983  $preselected = (GETPOSTISSET('idwarehousetoproduce-'.$line->id.'-'.$i) ? GETPOST('idwarehousetoproduce-'.$line->id.'-'.$i) : ($object->fk_warehouse > 0 ? $object->fk_warehouse : 'ifone'));
984  print $formproduct->selectWarehouses($preselected, 'idwarehousetoproduce-'.$line->id.'-'.$i, '', 1, 0, $line->fk_product, '', 1, 0, null, 'maxwidth300 csswarehouse_'.$line->id.'_'.$i);
985  } else {
986  print '<span class="opacitymedium">'.$langs->trans("NoStockChangeOnServices").'</span>';
987  }
988  print '</td>';
989  if ($conf->productbatch->enabled) {
990  print '<td>';
991  if ($tmpproduct->status_batch) {
992  $preselected = (GETPOSTISSET('batchtoproduce-'.$line->id.'-'.$i) ? GETPOST('batchtoproduce-'.$line->id.'-'.$i) : '');
993  print '<input type="text" class="width50" name="batchtoproduce-'.$line->id.'-'.$i.'" value="'.$preselected.'">';
994  }
995  print '</td>';
996  print '<td>';
997  if ($tmpproduct->status_batch) {
998  $type = 'batch';
999  print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine('.$line->id.', \''.$type.'\', \'qtymissing\')"');
1000  }
1001  print '</td>';
1002  }
1003  print '</tr>';
1004  }
1005  }
1006  }
1007  }
1008 
1009  print '</table>';
1010  print '</div>';
1011 
1012  print '</div>';
1013  print '</div>';
1014  }
1015 
1016  if (in_array($action, array('consumeorproduce', 'consumeandproduceall', 'addconsumeline')))
1017  {
1018  print "</form>\n";
1019  }
1020 }
1021 
1022 // End of page
1023 llxFooter();
1024 $db->close();
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname= '')
Make an include_once using default root and alternate root if it fails.
GETPOST($paramname, $check= 'alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
Class to manage stock movements.
img_edit($titlealt= 'default', $float=0, $other= '')
Show logo editer/modifier fiche.
Class with list of lots and properties.
yn($yesno, $case=1, $color=0)
Return yes or no in current language.
Class to manage products or services.
dol_now($mode= 'auto')
Return date for now.
Class for Mo.
Definition: mo.class.php:34
const TYPE_SERVICE
Service.
const TYPE_PRODUCT
Regular product.
moPrepareHead($object)
Prepare array of tabs for Mo.
Definition: mrp_mo.lib.php:30
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
Class MoLine.
Definition: mo.class.php:1364
Class with static methods for building HTML components related to products Only components common to ...
llxHeader()
Empty header.
Definition: wrapper.php:45
Class to manage standard extra fields.
setEventMessages($mesg, $mesgs, $style= 'mesgs', $messagekey= '')
Set event messages in dol_events session object.
Class to manage generation of HTML components Only common components must be here.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname.
Class to manage projects.
load_fiche_titre($titre, $morehtmlright= '', $picto= 'generic', $pictoisfullpath=0, $id= '', $morecssontable= '', $morehtmlcenter= '')
Load a title with picto.
price2num($amount, $rounding= '', $option=0)
Function that return a number with universal decimal format (decimal separator is &#39;...
Class to manage building of HTML components.
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt= '', $morecss= '', $marginleftonlyshort=2)
Show picto whatever it&#39;s its name (generic function)
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
restrictedArea($user, $features, $objectid=0, $tableandshare= '', $feature2= '', $dbt_keyfield= 'fk_soc', $dbt_select= 'rowid', $isdraft=0)
Check permissions of a user to show a page and an object.
Class to manage translations.
print $_SERVER["PHP_SELF"]
Edit parameters.
dol_get_fiche_head($links=array(), $active= '', $title= '', $notab=0, $picto= '', $pictoisfullpath=0, $morehtmlright= '', $morecss= '', $limittoshow=0, $moretabssuffix= '')
Show tabs of a record.
print
Draft customers invoices.
Definition: index.php:89
dol_print_date($time, $format= '', $tzoutput= 'auto', $outputlangs= '', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_banner_tab($object, $paramid, $morehtml= '', $shownav=1, $fieldid= 'rowid', $fieldref= 'ref', $morehtmlref= '', $moreparam= '', $nodbprefix=0, $morehtmlleft= '', $morehtmlstatus= '', $onlybanner=0, $morehtmlright= '')
Show tab footer of a card.
llxFooter()
Empty footer.
Definition: wrapper.php:59
if(!defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN'
Draft customers invoices.
Class to manage warehouses.