shipment.php 36 KB

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