shipment.php 36 KB

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