shipment.php 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929
  1. <?php
  2. /* Copyright (C) 2003-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2005-2012 Laurent Destailleur <eldy@users.sourceforge.net>
  4. * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
  5. * Copyright (C) 2012-2015 Juanjo Menent <jmenent@2byte.es>
  6. * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
  7. * Copyright (C) 2018 Philippe Grand <philippe.grand@atoo-net.com>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. */
  22. /**
  23. * \file htdocs/expedition/shipment.php
  24. * \ingroup expedition
  25. * \brief Tab shipments/delivery receipts on the order
  26. */
  27. require '../main.inc.php';
  28. require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
  29. require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
  30. require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
  31. require_once DOL_DOCUMENT_ROOT.'/core/lib/order.lib.php';
  32. require_once DOL_DOCUMENT_ROOT.'/core/lib/sendings.lib.php';
  33. require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
  34. if (! empty($conf->projet->enabled)) {
  35. require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
  36. require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
  37. }
  38. if (! empty($conf->stock->enabled)) require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
  39. if (! empty($conf->propal->enabled)) require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
  40. if (! empty($conf->product->enabled) || ! empty($conf->service->enabled)) require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
  41. // Load translation files required by the page
  42. $langs->loadLangs(array('orders',"companies","bills",'propal','deliveries','stocks',"productbatch",'incoterm'));
  43. $id=GETPOST('id','int'); // id of order
  44. $ref= GETPOST('ref','alpha');
  45. $action=GETPOST('action','alpha');
  46. // Security check
  47. $socid=0;
  48. if (! empty($user->societe_id)) $socid=$user->societe_id;
  49. $result=restrictedArea($user,'commande',$id);
  50. $object = new Commande($db);
  51. $extrafields = new ExtraFields($db);
  52. // fetch optionals attributes and labels
  53. $extralabels = $extrafields->fetch_name_optionals_label($object->table_element);
  54. // Load object
  55. include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once
  56. /*
  57. * Actions
  58. */
  59. $parameters = array('socid' => $socid);
  60. $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
  61. if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
  62. if (empty($reshook))
  63. {
  64. // Categorisation dans projet
  65. if ($action == 'classin')
  66. {
  67. $object = new Commande($db);
  68. $object->fetch($id);
  69. $object->setProject(GETPOST('projectid','int'));
  70. }
  71. if ($action == 'confirm_cloture' && GETPOST('confirm','alpha') == 'yes')
  72. {
  73. $object = new Commande($db);
  74. $object->fetch($id);
  75. $result = $object->cloture($user);
  76. }
  77. // Positionne ref commande client
  78. else if ($action == 'setref_client' && $user->rights->commande->creer) {
  79. $result = $object->set_ref_client($user, GETPOST('ref_client'));
  80. if ($result < 0)
  81. {
  82. setEventMessages($object->error, $object->errors, 'errors');
  83. }
  84. }
  85. if ($action == 'setdatedelivery' && $user->rights->commande->creer)
  86. {
  87. //print "x ".$_POST['liv_month'].", ".$_POST['liv_day'].", ".$_POST['liv_year'];
  88. $datelivraison=dol_mktime(0, 0, 0, GETPOST('liv_month','int'), GETPOST('liv_day','int'),GETPOST('liv_year','int'));
  89. $object = new Commande($db);
  90. $object->fetch($id);
  91. $result=$object->set_date_livraison($user,$datelivraison);
  92. if ($result < 0)
  93. setEventMessages($object->error, $object->errors, 'errors');
  94. }
  95. /*
  96. if ($action == 'setdeliveryaddress' && $user->rights->commande->creer)
  97. {
  98. $object = new Commande($db);
  99. $object->fetch($id);
  100. $object->setDeliveryAddress(GETPOST('delivery_address_id','int'));
  101. if ($result < 0)
  102. setEventMessages($object->error, $object->errors, 'errors');
  103. }
  104. */
  105. if ($action == 'setmode' && $user->rights->commande->creer)
  106. {
  107. $object = new Commande($db);
  108. $object->fetch($id);
  109. $result = $object->setPaymentMethods(GETPOST('mode_reglement_id','int'));
  110. if ($result < 0)
  111. setEventMessages($object->error, $object->errors, 'errors');
  112. }
  113. if ($action == 'setavailability' && $user->rights->commande->creer) {
  114. $object = new Commande($db);
  115. $object->fetch($id);
  116. $result=$object->availability(GETPOST('availability_id'));
  117. if ($result < 0)
  118. setEventMessages($object->error, $object->errors, 'errors');
  119. }
  120. if ($action == 'setdemandreason' && $user->rights->commande->creer) {
  121. $object = new Commande($db);
  122. $object->fetch($id);
  123. $result=$object->demand_reason(GETPOST('demand_reason_id'));
  124. if ($result < 0)
  125. setEventMessages($object->error, $object->errors, 'errors');
  126. }
  127. if ($action == 'setconditions' && $user->rights->commande->creer)
  128. {
  129. $object = new Commande($db);
  130. $object->fetch($id);
  131. $result=$object->setPaymentTerms(GETPOST('cond_reglement_id','int'));
  132. if ($result < 0)
  133. setEventMessages($object->error, $object->errors, 'errors');
  134. }
  135. // Set incoterm
  136. elseif ($action == 'set_incoterms' && !empty($conf->incoterm->enabled))
  137. {
  138. $result = $object->setIncoterms(GETPOST('incoterm_id', 'int'), GETPOST('location_incoterms', 'alpha'));
  139. if ($result < 0) {
  140. setEventMessages($object->error, $object->errors, 'errors');
  141. }
  142. }
  143. // shipping method
  144. if ($action == 'setshippingmethod' && $user->rights->commande->creer) {
  145. $object = new Commande($db);
  146. $object->fetch($id);
  147. $result=$object->setShippingMethod(GETPOST('shipping_method_id', 'int'));
  148. if ($result < 0)
  149. setEventMessages($object->error, $object->errors, 'errors');
  150. }
  151. // warehouse
  152. if ($action == 'setwarehouse' && $user->rights->commande->creer) {
  153. $object = new Commande($db);
  154. $object->fetch($id);
  155. $result = $object->setWarehouse(GETPOST('warehouse_id', 'int'));
  156. if ($result < 0)
  157. setEventMessages($object->error, $object->errors, 'errors');
  158. }
  159. if ($action == 'update_extras')
  160. {
  161. $object->oldcopy = dol_clone($object);
  162. // Fill array 'array_options' with data from update form
  163. $extralabels = $extrafields->fetch_name_optionals_label($object->table_element);
  164. $ret = $extrafields->setOptionalsFromPost($extralabels, $object, GETPOST('attribute', 'none'));
  165. if ($ret < 0) $error++;
  166. if (! $error)
  167. {
  168. // Actions on extra fields
  169. $result = $object->insertExtraFields('SHIPMENT_MODIFY');
  170. if ($result < 0)
  171. {
  172. setEventMessages($object->error, $object->errors, 'errors');
  173. $error++;
  174. }
  175. }
  176. if ($error)
  177. $action = 'edit_extras';
  178. }
  179. if ($action == 'set_thirdparty' && $user->rights->commande->creer)
  180. {
  181. $object->fetch($id);
  182. $object->setValueFrom('fk_soc', $socid, '', '', 'date', '', $user, 'ORDER_MODIFY');
  183. header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $id);
  184. exit();
  185. }
  186. include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
  187. }
  188. /*
  189. * View
  190. */
  191. $form = new Form($db);
  192. $formfile = new FormFile($db);
  193. $formproduct = new FormProduct($db);
  194. if (! empty($conf->projet->enabled)) { $formproject = new FormProjets($db); }
  195. llxHeader('',$langs->trans('OrderCard'),'');
  196. if ($id > 0 || ! empty($ref))
  197. {
  198. $object = new Commande($db);
  199. if ( $object->fetch($id,$ref) > 0)
  200. {
  201. $object->loadExpeditions(1);
  202. $product_static=new Product($db);
  203. $soc = new Societe($db);
  204. $soc->fetch($object->socid);
  205. $author = new User($db);
  206. $author->fetch($object->user_author_id);
  207. $res = $object->fetch_optionals();
  208. $head = commande_prepare_head($object);
  209. dol_fiche_head($head, 'shipping', $langs->trans("CustomerOrder"), -1, 'order');
  210. $formconfirm = '';
  211. // Confirm validation
  212. if ($action == 'cloture')
  213. {
  214. $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$id,$langs->trans("CloseShipment"),$langs->trans("ConfirmCloseShipment"),"confirm_cloture");
  215. }
  216. // Call Hook formConfirm
  217. $parameters = array();
  218. $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  219. if (empty($reshook)) $formconfirm.=$hookmanager->resPrint;
  220. elseif ($reshook > 0) $formconfirm=$hookmanager->resPrint;
  221. // Print form confirm
  222. print $formconfirm;
  223. // Order card
  224. $linkback = '<a href="' . DOL_URL_ROOT . '/commande/list.php?restore_lastsearch_values=1' . (! empty($socid) ? '?socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
  225. $morehtmlref='<div class="refidno">';
  226. // Ref customer
  227. $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->commande->creer, 'string', '', 0, 1);
  228. $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->commande->creer, 'string', '', null, null, '', 1);
  229. // Thirdparty
  230. $morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $soc->getNomUrl(1);
  231. // Project
  232. if (! empty($conf->projet->enabled))
  233. {
  234. $langs->load("projects");
  235. $morehtmlref.='<br>'.$langs->trans('Project') . ' ';
  236. if ($user->rights->commande->creer)
  237. {
  238. if ($action != 'classify')
  239. $morehtmlref.='<a href="' . $_SERVER['PHP_SELF'] . '?action=classify&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : ';
  240. if ($action == 'classify') {
  241. //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
  242. $morehtmlref.='<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
  243. $morehtmlref.='<input type="hidden" name="action" value="classin">';
  244. $morehtmlref.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
  245. $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
  246. $morehtmlref.='<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
  247. $morehtmlref.='</form>';
  248. } else {
  249. $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1);
  250. }
  251. } else {
  252. if (! empty($object->fk_project)) {
  253. $proj = new Project($db);
  254. $proj->fetch($object->fk_project);
  255. $morehtmlref.='<a href="'.DOL_URL_ROOT.'/projet/card.php?id=' . $object->fk_project . '" title="' . $langs->trans('ShowProject') . '">';
  256. $morehtmlref.=$proj->ref;
  257. $morehtmlref.='</a>';
  258. } else {
  259. $morehtmlref.='';
  260. }
  261. }
  262. }
  263. $morehtmlref.='</div>';
  264. dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
  265. print '<div class="fichecenter">';
  266. print '<div class="fichehalfleft">';
  267. print '<div class="underbanner clearboth"></div>';
  268. print '<table class="border" width="100%">';
  269. // Discounts for third party
  270. if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
  271. $filterabsolutediscount = "fk_facture_source IS NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
  272. $filtercreditnote = "fk_facture_source IS NOT NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
  273. } else {
  274. $filterabsolutediscount = "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')";
  275. $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')";
  276. }
  277. print '<tr><td class="titlefield">'.$langs->trans('Discounts').'</td><td colspan="3">';
  278. $absolute_discount=$soc->getAvailableDiscounts('',$filterabsolutediscount);
  279. $absolute_creditnote=$soc->getAvailableDiscounts('',$filtercreditnote);
  280. $absolute_discount=price2num($absolute_discount,'MT');
  281. $absolute_creditnote=price2num($absolute_creditnote,'MT');
  282. $thirdparty = $soc;
  283. $discount_type = 0;
  284. $backtopage = urlencode($_SERVER["PHP_SELF"] . '?id=' . $object->id);
  285. $cannotApplyDiscount = 1;
  286. include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
  287. print '</td></tr>';
  288. // Date
  289. print '<tr><td>'.$langs->trans('Date').'</td>';
  290. print '<td colspan="2">';
  291. print dol_print_date($object->date,'daytext');
  292. if ($object->hasDelay() && empty($object->date_livraison)) {
  293. print ' '.img_picto($langs->trans("Late").' : '.$object->showDelay(), "warning");
  294. }
  295. print '</td>';
  296. print '</tr>';
  297. // Delivery date planned
  298. print '<tr><td height="10">';
  299. print '<table class="nobordernopadding" width="100%"><tr><td>';
  300. print $langs->trans('DateDeliveryPlanned');
  301. print '</td>';
  302. if ($action != 'editdate_livraison') print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editdate_livraison&amp;id='.$object->id.'">'.img_edit($langs->trans('SetDeliveryDate'),1).'</a></td>';
  303. print '</tr></table>';
  304. print '</td><td colspan="2">';
  305. if ($action == 'editdate_livraison')
  306. {
  307. print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
  308. print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
  309. print '<input type="hidden" name="action" value="setdatedelivery">';
  310. print $form->selectDate($object->date_livraison>0?$object->date_livraison:-1, 'liv_', '', '', '', "setdatedelivery");
  311. print '<input type="submit" class="button" value="'.$langs->trans('Modify').'">';
  312. print '</form>';
  313. }
  314. else
  315. {
  316. print dol_print_date($object->date_livraison,'daytext');
  317. if ($object->hasDelay() && ! empty($object->date_livraison)) {
  318. print ' '.img_picto($langs->trans("Late").' : '.$object->showDelay(), "warning");
  319. }
  320. }
  321. print '</td>';
  322. // Note on several rows
  323. //print '<td rowspan="'.$nbrow.'" valign="top">'.$langs->trans('NotePublic').' :<br>';
  324. //print nl2br($object->note_public);
  325. //print '</td>';
  326. print '</tr>';
  327. // Shipping Method
  328. print '<tr><td>';
  329. print '<table width="100%" class="nobordernopadding"><tr><td>';
  330. print $langs->trans('SendingMethod');
  331. print '</td>';
  332. if ($action != 'editshippingmethod' && $user->rights->expedition->creer)
  333. print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editshippingmethod&amp;id='.$object->id.'">'.img_edit($langs->trans('SetShippingMode'),1).'</a></td>';
  334. print '</tr></table>';
  335. print '</td><td colspan="2">';
  336. if ($action == 'editshippingmethod') {
  337. $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, $object->shipping_method_id, 'shipping_method_id', 1);
  338. } else {
  339. $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, $object->shipping_method_id, 'none');
  340. }
  341. print '</td>';
  342. print '</tr>';
  343. // Warehouse
  344. if (! empty($conf->stock->enabled) && ! empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER)) {
  345. require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
  346. $formproduct=new FormProduct($db);
  347. print '<tr><td>';
  348. print '<table width="100%" class="nobordernopadding"><tr><td>';
  349. print $langs->trans('Warehouse');
  350. print '</td>';
  351. if ($action != 'editwarehouse' && $user->rights->commande->creer)
  352. print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editwarehouse&amp;id='.$object->id.'">'.img_edit($langs->trans('SetWarehouse'),1).'</a></td>';
  353. print '</tr></table>';
  354. print '</td><td colspan="2">';
  355. if ($action == 'editwarehouse') {
  356. $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->warehouse_id, 'warehouse_id', 1);
  357. } else {
  358. $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->warehouse_id, 'none');
  359. }
  360. print '</td>';
  361. print '</tr>';
  362. }
  363. // Terms of payment
  364. /*
  365. print '<tr><td height="10">';
  366. print '<table class="nobordernopadding" width="100%"><tr><td>';
  367. print $langs->trans('PaymentConditionsShort');
  368. print '</td>';
  369. if ($action != 'editconditions' && ! empty($object->brouillon)) print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editconditions&amp;id='.$object->id.'">'.img_edit($langs->trans('SetConditions'),1).'</a></td>';
  370. print '</tr></table>';
  371. print '</td><td colspan="2">';
  372. if ($action == 'editconditions')
  373. {
  374. $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id,$object->cond_reglement_id,'cond_reglement_id');
  375. }
  376. else
  377. {
  378. $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id,$object->cond_reglement_id,'none');
  379. }
  380. print '</td></tr>';
  381. // Mode of payment
  382. print '<tr><td>';
  383. print '<table class="nobordernopadding" width="100%"><tr><td>';
  384. print $langs->trans('PaymentMode');
  385. print '</td>';
  386. if ($action != 'editmode' && ! empty($object->brouillon)) print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editmode&amp;id='.$object->id.'">'.img_edit($langs->trans('SetMode'),1).'</a></td>';
  387. print '</tr></table>';
  388. print '</td><td colspan="2">';
  389. if ($action == 'editmode')
  390. {
  391. $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id,$object->mode_reglement_id,'mode_reglement_id');
  392. }
  393. else
  394. {
  395. $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id,$object->mode_reglement_id,'none');
  396. }
  397. print '</td></tr>';*/
  398. // Availability
  399. print '<tr><td height="10">';
  400. print '<table class="nobordernopadding" width="100%"><tr><td>';
  401. print $langs->trans('AvailabilityPeriod');
  402. print '</td>';
  403. if ($action != 'editavailability')
  404. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editavailability&amp;id=' . $object->id . '">' . img_edit($langs->trans('SetAvailability'), 1) . '</a></td>';
  405. print '</tr></table>';
  406. print '</td><td colspan="3">';
  407. if ($action == 'editavailability') {
  408. $form->form_availability($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->availability_id, 'availability_id', 1);
  409. } else {
  410. $form->form_availability($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->availability_id, 'none', 1);
  411. }
  412. print '</td></tr>';
  413. // Source
  414. print '<tr><td height="10">';
  415. print '<table class="nobordernopadding" width="100%"><tr><td>';
  416. print $langs->trans('Source');
  417. print '</td>';
  418. if ($action != 'editdemandreason')
  419. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editdemandreason&amp;id=' . $object->id . '">' . img_edit($langs->trans('SetDemandReason'), 1) . '</a></td>';
  420. print '</tr></table>';
  421. print '</td><td colspan="3">';
  422. if ($action == 'editdemandreason') {
  423. $form->formInputReason($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->demand_reason_id, 'demand_reason_id', 1);
  424. } else {
  425. $form->formInputReason($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->demand_reason_id, 'none');
  426. }
  427. $tmparray=$object->getTotalWeightVolume();
  428. $totalWeight=$tmparray['weight'];
  429. $totalVolume=$tmparray['volume'];
  430. if ($totalWeight || $totalVolume)
  431. {
  432. print '<tr><td>'.$langs->trans("CalculatedWeight").'</td>';
  433. print '<td>';
  434. print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, isset($conf->global->MAIN_WEIGHT_DEFAULT_ROUND)?$conf->global->MAIN_WEIGHT_DEFAULT_ROUND:-1, isset($conf->global->MAIN_WEIGHT_DEFAULT_UNIT)?$conf->global->MAIN_WEIGHT_DEFAULT_UNIT:'no');
  435. print '</td></tr>';
  436. print '<tr><td>'.$langs->trans("CalculatedVolume").'</td>';
  437. print '<td>';
  438. print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND)?$conf->global->MAIN_VOLUME_DEFAULT_ROUND:-1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT)?$conf->global->MAIN_VOLUME_DEFAULT_UNIT:'no');
  439. print '</td></tr>';
  440. }
  441. // TODO How record was recorded OrderMode (llx_c_input_method)
  442. // Incoterms
  443. if (!empty($conf->incoterm->enabled))
  444. {
  445. print '<tr><td>';
  446. print '<table width="100%" class="nobordernopadding"><tr><td>';
  447. print $langs->trans('IncotermLabel');
  448. print '<td><td align="right">';
  449. if ($user->rights->commande->creer) print '<a href="'.$_SERVER['PHP_SELF'].'/expedition/shipment.php?id='.$object->id.'&action=editincoterm">'.img_edit().'</a>';
  450. else print '&nbsp;';
  451. print '</td></tr></table>';
  452. print '</td>';
  453. print '<td colspan="3">';
  454. if ($action != 'editincoterm')
  455. {
  456. print $form->textwithpicto($object->display_incoterms(), $object->libelle_incoterms, 1);
  457. }
  458. else
  459. {
  460. print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms)?$object->location_incoterms:''), $_SERVER['PHP_SELF'].'?id='.$object->id);
  461. }
  462. print '</td></tr>';
  463. }
  464. // Other attributes
  465. $cols = 2;
  466. include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
  467. print '</table>';
  468. print '</div>';
  469. print '<div class="fichehalfright">';
  470. print '<div class="ficheaddleft">';
  471. print '<div class="underbanner clearboth"></div>';
  472. print '<table class="border centpercent">';
  473. if (!empty($conf->multicurrency->enabled) && ($object->multicurrency_code != $conf->currency))
  474. {
  475. // Multicurrency Amount HT
  476. print '<tr><td class="titlefieldmiddle">' . fieldLabel('MulticurrencyAmountHT','multicurrency_total_ht') . '</td>';
  477. print '<td class="nowrap">' . price($object->multicurrency_total_ht, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
  478. print '</tr>';
  479. // Multicurrency Amount VAT
  480. print '<tr><td>' . fieldLabel('MulticurrencyAmountVAT','multicurrency_total_tva') . '</td>';
  481. print '<td class="nowrap">' . price($object->multicurrency_total_tva, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
  482. print '</tr>';
  483. // Multicurrency Amount TTC
  484. print '<tr><td>' . fieldLabel('MulticurrencyAmountTTC','multicurrency_total_ttc') . '</td>';
  485. print '<td class="nowrap">' . price($object->multicurrency_total_ttc, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
  486. print '</tr>';
  487. }
  488. // Total HT
  489. print '<tr><td class="titlefieldmiddle">'.$langs->trans('AmountHT').'</td>';
  490. print '<td>'.price($object->total_ht, 0, '', 1, -1, -1, $conf->currency).'</td>';
  491. print '</tr>';
  492. // Total VAT
  493. print '<tr><td>'.$langs->trans('AmountVAT').'</td><td>'.price($object->total_tva, 0, '', 1, -1, -1, $conf->currency).'</td>';
  494. print '</tr>';
  495. // Amount Local Taxes
  496. if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) // Localtax1
  497. {
  498. print '<tr><td>' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
  499. print '<td>' . price($object->total_localtax1, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
  500. }
  501. if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) // Localtax2 IRPF
  502. {
  503. print '<tr><td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
  504. print '<td>' . price($object->total_localtax2, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
  505. }
  506. // Total TTC
  507. print '<tr><td>'.$langs->trans('AmountTTC').'</td><td>'.price($object->total_ttc, 0, '', 1, -1, -1, $conf->currency).'</td>';
  508. print '</tr>';
  509. print '</table>';
  510. print '</div>';
  511. print '</div>';
  512. print '</div>';
  513. print '<div class="clearboth"></div><br>';
  514. /**
  515. * Lines or orders with quantity shipped and remain to ship
  516. * Note: Qty shipped are already available into $object->expeditions[fk_product]
  517. */
  518. print '<table class="noborder noshadow" width="100%">';
  519. $sql = "SELECT cd.rowid, cd.fk_product, cd.product_type as type, cd.label, cd.description,";
  520. $sql.= " cd.price, cd.tva_tx, cd.subprice,";
  521. $sql.= " cd.qty,";
  522. $sql.= ' cd.date_start,';
  523. $sql.= ' cd.date_end,';
  524. $sql.= ' p.rowid as prodid, p.label as product_label, p.entity, p.ref, p.fk_product_type as product_type, p.description as product_desc';
  525. $sql.= " FROM ".MAIN_DB_PREFIX."commandedet as cd";
  526. $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON cd.fk_product = p.rowid";
  527. $sql.= " WHERE cd.fk_commande = ".$object->id;
  528. $sql.= " ORDER BY cd.rang, cd.rowid";
  529. //print $sql;
  530. dol_syslog("shipment.php", LOG_DEBUG);
  531. $resql = $db->query($sql);
  532. if ($resql)
  533. {
  534. $num = $db->num_rows($resql);
  535. $i = 0;
  536. print '<tr class="liste_titre">';
  537. print '<td>'.$langs->trans("Description").'</td>';
  538. print '<td align="center">'.$langs->trans("QtyOrdered").'</td>';
  539. print '<td align="center">'.$langs->trans("QtyShipped").'</td>';
  540. print '<td align="center">'.$langs->trans("KeepToShip").'</td>';
  541. if (! empty($conf->stock->enabled))
  542. {
  543. print '<td align="center">'.$langs->trans("RealStock").'</td>';
  544. }
  545. else
  546. {
  547. print '<td>&nbsp;</td>';
  548. }
  549. print "</tr>\n";
  550. $toBeShipped=array();
  551. $toBeShippedTotal=0;
  552. while ($i < $num)
  553. {
  554. $objp = $db->fetch_object($resql);
  555. // Show product and description
  556. $type=isset($objp->type)?$objp->type:$objp->product_type;
  557. // Try to enhance type detection using date_start and date_end for free lines where type
  558. // was not saved.
  559. if (! empty($objp->date_start)) $type=1;
  560. if (! empty($objp->date_end)) $type=1;
  561. print '<tr class="oddeven">';
  562. // Product label
  563. if ($objp->fk_product > 0)
  564. {
  565. // Define output language
  566. if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE))
  567. {
  568. $object->fetch_thirdparty();
  569. $prod = new Product($db);
  570. $prod->id = $objp->fk_product;
  571. $prod->entity = $objp->entity;
  572. $prod->getMultiLangs();
  573. $outputlangs = $langs;
  574. $newlang='';
  575. if (empty($newlang) && ! empty($_REQUEST['lang_id'])) $newlang=$_REQUEST['lang_id'];
  576. if (empty($newlang)) $newlang=$object->thirdparty->default_lang;
  577. if (! empty($newlang))
  578. {
  579. $outputlangs = new Translate("",$conf);
  580. $outputlangs->setDefaultLang($newlang);
  581. }
  582. $label = (! empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $objp->product_label;
  583. }
  584. else
  585. $label = (! empty($objp->label)?$objp->label:$objp->product_label);
  586. print '<td>';
  587. print '<a name="'.$objp->rowid.'"></a>'; // ancre pour retourner sur la ligne
  588. // Show product and description
  589. $product_static->type=$type;
  590. $product_static->id=$objp->fk_product;
  591. $product_static->ref=$objp->ref;
  592. $product_static->entity = $objp->entity;
  593. $text=$product_static->getNomUrl(1);
  594. $text.= ' - '.$label;
  595. $description=($conf->global->PRODUIT_DESC_IN_FORM?'':dol_htmlentitiesbr($objp->description)).'<br>';
  596. $description.= $product_static->show_photos('product', $conf->product->multidir_output[$product_static->entity], 1, 1, 0, 0, 0, 80);
  597. print $form->textwithtooltip($text,$description,3,'','',$i);
  598. // Show range
  599. print_date_range($db->jdate($objp->date_start),$db->jdate($objp->date_end));
  600. // Add description in form
  601. if (! empty($conf->global->PRODUIT_DESC_IN_FORM))
  602. {
  603. print ($objp->description && $objp->description!=$objp->product_label)?'<br>'.dol_htmlentitiesbr($objp->description):'';
  604. }
  605. print '</td>';
  606. }
  607. else
  608. {
  609. print "<td>";
  610. if ($type==1) $text = img_object($langs->trans('Service'),'service');
  611. else $text = img_object($langs->trans('Product'),'product');
  612. if (! empty($objp->label)) {
  613. $text.= ' <strong>'.$objp->label.'</strong>';
  614. print $form->textwithtooltip($text,$objp->description,3,'','',$i);
  615. } else {
  616. print $text.' '.nl2br($objp->description);
  617. }
  618. // Show range
  619. print_date_range($db->jdate($objp->date_start),$db->jdate($objp->date_end));
  620. print "</td>\n";
  621. }
  622. // Qty ordered
  623. print '<td align="center">' . $objp->qty . '</td>';
  624. // Qty already shipped
  625. $qtyProdCom=$objp->qty;
  626. print '<td align="center">';
  627. // Nb of sending products for this line of order
  628. $qtyAlreadyShipped = (! empty($object->expeditions[$objp->rowid])?$object->expeditions[$objp->rowid]:0);
  629. print $qtyAlreadyShipped;
  630. print '</td>';
  631. // Qty remains to ship
  632. print '<td align="center">';
  633. if ($type == 0 || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
  634. {
  635. $toBeShipped[$objp->fk_product] = $objp->qty - $qtyAlreadyShipped;
  636. $toBeShippedTotal += $toBeShipped[$objp->fk_product];
  637. print $toBeShipped[$objp->fk_product];
  638. }
  639. else
  640. {
  641. print '0 ('.$langs->trans("Service").')';
  642. }
  643. print '</td>';
  644. if ($objp->fk_product > 0)
  645. {
  646. $product = new Product($db);
  647. $product->fetch($objp->fk_product);
  648. $product->load_stock('warehouseopen');
  649. }
  650. if ($objp->fk_product > 0 && ($type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES)) && ! empty($conf->stock->enabled))
  651. {
  652. print '<td align="center">';
  653. print $product->stock_reel;
  654. if ($product->stock_reel < $toBeShipped[$objp->fk_product])
  655. {
  656. print ' '.img_warning($langs->trans("StockTooLow"));
  657. }
  658. print '</td>';
  659. }
  660. else
  661. {
  662. print '<td>&nbsp;</td>';
  663. }
  664. print "</tr>\n";
  665. // Show subproducts lines
  666. if ($objp->fk_product > 0 && ! empty($conf->global->PRODUIT_SOUSPRODUITS))
  667. {
  668. // Set tree of subproducts in product->sousprods
  669. $product->get_sousproduits_arbo();
  670. //var_dump($product->sousprods);exit;
  671. // Define a new tree with quantiies recalculated
  672. $prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
  673. //var_dump($prods_arbo);
  674. if (count($prods_arbo) > 0)
  675. {
  676. foreach($prods_arbo as $key => $value)
  677. {
  678. $img='';
  679. if ($value['stock'] < $value['stock_alert'])
  680. {
  681. $img=img_warning($langs->trans("StockTooLow"));
  682. }
  683. print '<tr class="oddeven"><td>&nbsp; &nbsp; &nbsp; -> <a href="'.DOL_URL_ROOT."/product/card.php?id=".$value['id'].'">'.$value['fullpath'].'</a> ('.$value['nb'].')</td>';
  684. print '<td align="center"> '.$value['nb_total'].'</td>';
  685. print '<td>&nbsp</td>';
  686. print '<td>&nbsp</td>';
  687. print '<td align="center">'.$value['stock'].' '.$img.'</td></tr>'."\n";
  688. }
  689. }
  690. }
  691. $i++;
  692. }
  693. $db->free($resql);
  694. if (! $num)
  695. {
  696. print '<tr '.$bc[false].'><td colspan="5">'.$langs->trans("NoArticleOfTypeProduct").'<br>';
  697. }
  698. print "</table>";
  699. }
  700. else
  701. {
  702. dol_print_error($db);
  703. }
  704. print '</div>';
  705. /*
  706. * Boutons Actions
  707. */
  708. if (empty($user->societe_id))
  709. {
  710. print '<div class="tabsAction">';
  711. // Bouton expedier sans gestion des stocks
  712. if (empty($conf->stock->enabled) && ($object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED))
  713. {
  714. if ($user->rights->expedition->creer)
  715. {
  716. print '<a class="butAction" href="'.DOL_URL_ROOT.'/expedition/card.php?action=create&amp;origin=commande&amp;object_id='.$id.'">'.$langs->trans("CreateShipment").'</a>';
  717. if ($toBeShippedTotal <= 0)
  718. {
  719. print ' '.img_warning($langs->trans("WarningNoQtyLeftToSend"));
  720. }
  721. }
  722. else
  723. {
  724. print '<a class="butActionRefused" href="#">'.$langs->trans("CreateShipment").'</a>';
  725. }
  726. }
  727. print "</div>";
  728. }
  729. // Bouton expedier avec gestion des stocks
  730. if (! empty($conf->stock->enabled) && $object->statut == Commande::STATUS_DRAFT)
  731. {
  732. print $langs->trans("ValidateOrderFirstBeforeShipment");
  733. }
  734. if (! empty($conf->stock->enabled) && ($object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED))
  735. {
  736. if ($user->rights->expedition->creer)
  737. {
  738. //print load_fiche_titre($langs->trans("CreateShipment"));
  739. print '<div class="tabsAction">';
  740. print '<form method="GET" action="'.DOL_URL_ROOT.'/expedition/card.php">';
  741. print '<input type="hidden" name="action" value="create">';
  742. //print '<input type="hidden" name="id" value="'.$object->id.'">';
  743. print '<input type="hidden" name="shipping_method_id" value="'.$object->shipping_method_id.'">';
  744. print '<input type="hidden" name="origin" value="commande">';
  745. print '<input type="hidden" name="origin_id" value="'.$object->id.'">';
  746. print '<input type="hidden" name="projectid" value="'.$object->fk_project.'">';
  747. //print '<table class="border" width="100%">';
  748. $langs->load("stocks");
  749. //print '<tr>';
  750. if (! empty($conf->stock->enabled))
  751. {
  752. //print '<td>';
  753. print $langs->trans("WarehouseSource");
  754. //print '</td>';
  755. //print '<td>';
  756. print $formproduct->selectWarehouses(! empty($object->warehouse_id)?$object->warehouse_id:-1, 'entrepot_id', '', 1, 0, 0, '', 0, 0, array(), 'minwidth200');
  757. if (count($formproduct->cache_warehouses) <= 0)
  758. {
  759. print ' &nbsp; '.$langs->trans("WarehouseSourceNotDefined").' <a href="'.DOL_URL_ROOT.'/product/stock/card.php?action=create">'.$langs->trans("AddOne").'</a>';
  760. }
  761. //print '</td>';
  762. }
  763. //print '<td align="center">';
  764. print '<input type="submit" class="butAction" named="save" value="'.$langs->trans("CreateShipment").'">';
  765. if ($toBeShippedTotal <= 0)
  766. {
  767. print ' '.img_warning($langs->trans("WarningNoQtyLeftToSend"));
  768. }
  769. //print '</td></tr>';
  770. //print "</table>";
  771. print "</form>\n";
  772. print '</div>';
  773. $somethingshown=1;
  774. }
  775. else
  776. {
  777. print '<div class="tabsAction">';
  778. print '<a class="butActionRefused" href="#">'.$langs->trans("CreateShipment").'</a>';
  779. print '</div>';
  780. }
  781. }
  782. show_list_sending_receive('commande',$object->id);
  783. }
  784. else
  785. {
  786. /* Order not found */
  787. setEventMessages($langs->trans("NonExistentOrder"), null, 'errors');
  788. }
  789. }
  790. // End of page
  791. llxFooter();
  792. $db->close();