1<?php 2/* Copyright (C) 2010-2012 Regis Houssin <regis.houssin@inodbox.com> 3 * Copyright (C) 2010-2014 Laurent Destailleur <eldy@users.sourceforge.net> 4 * Copyright (C) 2012-2013 Christophe Battarel <christophe.battarel@altairis.fr> 5 * Copyright (C) 2012 Cédric Salvador <csalvador@gpcsolutions.fr> 6 * Copyright (C) 2014 Florian Henry <florian.henry@open-concept.pro> 7 * Copyright (C) 2014 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr> 8 * Copyright (C) 2015-2016 Marcos García <marcosgdf@gmail.com> 9 * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr> 10 * Copyright (C) 2018 Ferran Marcet <fmarcet@2byte.es> 11 * Copyright (C) 2019 Nicolas ZABOURI <info@inovea-conseil.com> 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 3 of the License, or 16 * (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program. If not, see <https://www.gnu.org/licenses/>. 25 * 26 * Need to have following variables defined: 27 * $object (invoice, order, ...) 28 * $conf 29 * $langs 30 * $dateSelector 31 * $forceall (0 by default, 1 for supplier invoices/orders) 32 * $senderissupplier (0 by default, 1 or 2 for supplier invoices/orders) 33 * $inputalsopricewithtax (0 by default, 1 to also show column with unit price including tax) 34 */ 35 36// Protection to avoid direct call of template 37if (empty($object) || !is_object($object)) { 38 print "Error: this template page cannot be called directly as an URL"; 39 exit; 40} 41$usemargins = 0; 42if (!empty($conf->margin->enabled) && !empty($object->element) && in_array($object->element, array('facture', 'facturerec', 'propal', 'commande'))) 43{ 44 $usemargins = 1; 45} 46if (!isset($dateSelector)) global $dateSelector; // Take global var only if not already defined into function calling (for example formAddObjectLine) 47global $forceall, $forcetoshowtitlelines, $senderissupplier, $inputalsopricewithtax; 48if (!isset($dateSelector)) $dateSelector = 1; // For backward compatibility 49elseif (empty($dateSelector)) $dateSelector = 0; 50if (empty($forceall)) $forceall = 0; 51if (empty($senderissupplier)) $senderissupplier = 0; 52if (empty($inputalsopricewithtax)) $inputalsopricewithtax = 0; 53// Define colspan for the button 'Add' 54$colspan = 3; // Columns: total ht + col edit + col delete 55if (!empty($conf->multicurrency->enabled) && $this->multicurrency_code != $conf->currency) $colspan++; //Add column for Total (currency) if required 56if (in_array($object->element, array('propal', 'commande', 'order', 'facture', 'facturerec', 'invoice', 'supplier_proposal', 'order_supplier', 'invoice_supplier'))) $colspan++; // With this, there is a column move button 57//print $object->element; 58// Lines for extrafield 59$objectline = null; 60if (!empty($extrafields)) 61{ 62 if ($this->table_element_line == 'commandedet') { 63 $objectline = new OrderLine($this->db); 64 } elseif ($this->table_element_line == 'propaldet') { 65 $objectline = new PropaleLigne($this->db); 66 } elseif ($this->table_element_line == 'supplier_proposaldet') { 67 $objectline = new SupplierProposalLine($this->db); 68 } elseif ($this->table_element_line == 'facturedet') { 69 $objectline = new FactureLigne($this->db); 70 } elseif ($this->table_element_line == 'contratdet') { 71 $objectline = new ContratLigne($this->db); 72 } elseif ($this->table_element_line == 'commande_fournisseurdet') { 73 $objectline = new CommandeFournisseurLigne($this->db); 74 } elseif ($this->table_element_line == 'facture_fourn_det') { 75 $objectline = new SupplierInvoiceLine($this->db); 76 } elseif ($this->table_element_line == 'facturedet_rec') { 77 $objectline = new FactureLigneRec($this->db); 78 } 79} 80print "<!-- BEGIN PHP TEMPLATE objectline_create.tpl.php -->\n"; 81$nolinesbefore = (count($this->lines) == 0 || $forcetoshowtitlelines); 82if ($nolinesbefore) { 83 ?> 84 <tr class="liste_titre<?php echo (($nolinesbefore || $object->element == 'contrat') ? '' : ' liste_titre_add_') ?> nodrag nodrop"> 85 <?php if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) { ?> 86 <td class="linecolnum center"></td> 87 <?php } ?> 88 <td class="linecoldescription minwidth500imp"> 89 <div id="add"></div><span class="hideonsmartphone"><?php echo $langs->trans('AddNewLine'); ?></span> 90 </td> 91 <?php 92 if ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier') // We must have same test in printObjectLines 93 { 94 ?> 95 <td class="linecolrefsupplier"><span id="title_fourn_ref"><?php echo $langs->trans('SupplierRef'); ?></span></td> 96 <?php 97 } 98 ?> 99 <td class="linecolvat right"><span id="title_vat"><?php echo $langs->trans('VAT'); ?></span></td> 100 <td class="linecoluht right"><span id="title_up_ht"><?php echo $langs->trans('PriceUHT'); ?></span></td> 101 <?php if (!empty($conf->multicurrency->enabled) && $this->multicurrency_code != $conf->currency) { ?> 102 <td class="linecoluht_currency right"><span id="title_up_ht_currency"><?php echo $langs->trans('PriceUHTCurrency'); ?></span></td> 103 <?php } ?> 104 <?php if (!empty($inputalsopricewithtax)) { ?> 105 <td class="linecoluttc right"><span id="title_up_ttc"><?php echo $langs->trans('PriceUTTC'); ?></span></td> 106 <?php } ?> 107 <td class="linecolqty right"><?php echo $langs->trans('Qty'); ?></td> 108 <?php 109 if (!empty($conf->global->PRODUCT_USE_UNITS)) 110 { 111 print '<td class="linecoluseunit left">'; 112 print '<span id="title_units">'; 113 print $langs->trans('Unit'); 114 print '</span></td>'; 115 } 116 ?> 117 <td class="linecoldiscount right"><?php echo $langs->trans('ReductionShort'); ?></td> 118 <?php 119 // Fields for situation invoice 120 if ($this->situation_cycle_ref) { 121 print '<td class="linecolcycleref right">'.$langs->trans('Progress').'</td>'; 122 print '<td class="linecolcycleref2 right"></td>'; 123 } 124 if (!empty($usemargins)) 125 { 126 if (empty($user->rights->margins->creer)) { 127 $colspan++; 128 } else { 129 print '<td class="margininfos linecolmargin1 right">'; 130 if ($conf->global->MARGIN_TYPE == "1") 131 echo $langs->trans('BuyingPrice'); 132 else echo $langs->trans('CostPrice'); 133 echo '</td>'; 134 if (!empty($conf->global->DISPLAY_MARGIN_RATES)) echo '<td class="margininfos linecolmargin2 right"><span class="np_marginRate">'.$langs->trans('MarginRate').'</span></td>'; 135 if (!empty($conf->global->DISPLAY_MARK_RATES)) echo '<td class="margininfos linecolmargin2 right"><span class="np_markRate">'.$langs->trans('MarkRate').'</span></td>'; 136 } 137 } 138 ?> 139 <td class="linecoledit" colspan="<?php echo $colspan; ?>"> </td> 140 </tr> 141 <?php 142} 143?> 144<tr class="pair nodrag nodrop nohoverpair<?php echo ($nolinesbefore || $object->element == 'contrat') ? '' : ' liste_titre_create'; ?>"> 145 <?php 146 $coldisplay = 0; 147 // Adds a line numbering column 148 if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) { 149 $coldisplay++; 150 echo '<td class="nobottom linecolnum center"></td>'; 151 } 152 $coldisplay++; 153 ?> 154 <td class="nobottom linecoldescription minwidth500imp"> 155 156 <?php 157 $freelines = false; 158 if (empty($conf->global->MAIN_DISABLE_FREE_LINES)) 159 { 160 $freelines = true; 161 $forceall = 1; // We always force all type for free lines (module product or service means we use predefined product or service) 162 if ($object->element == 'contrat') 163 { 164 if (empty($conf->product->enabled) && empty($conf->service->enabled) && empty($conf->global->CONTRACT_SUPPORT_PRODUCTS)) $forceall = -1; // With contract, by default, no choice at all, except if CONTRACT_SUPPORT_PRODUCTS is set 165 elseif (empty($conf->global->CONTRACT_SUPPORT_PRODUCTS)) $forceall = 3; 166 } 167 // Free line 168 echo '<span class="prod_entry_mode_free">'; 169 // Show radio free line 170 if ($forceall >= 0 && (!empty($conf->product->enabled) || !empty($conf->service->enabled))) 171 { 172 echo '<label for="prod_entry_mode_free">'; 173 echo '<input type="radio" class="prod_entry_mode_free" name="prod_entry_mode" id="prod_entry_mode_free" value="free"'; 174 //echo (GETPOST('prod_entry_mode')=='free' ? ' checked' : ((empty($forceall) && (empty($conf->product->enabled) || empty($conf->service->enabled)))?' checked':'') ); 175 echo ((GETPOST('prod_entry_mode', 'alpha') == 'free' || !empty($conf->global->MAIN_FREE_PRODUCT_CHECKED_BY_DEFAULT)) ? ' checked' : ''); 176 echo '> '; 177 // Show type selector 178 echo $langs->trans("FreeLineOfType"); 179 echo '</label>'; 180 echo ' '; 181 } else { 182 echo '<input type="hidden" id="prod_entry_mode_free" name="prod_entry_mode" value="free">'; 183 // Show type selector 184 if ($forceall >= 0) 185 { 186 if (empty($conf->product->enabled) || empty($conf->service->enabled)) echo $langs->trans("Type"); 187 else echo $langs->trans("FreeLineOfType"); 188 echo ' '; 189 } 190 } 191 echo $form->select_type_of_lines(GETPOSTISSET("type") ? GETPOST("type", 'alpha', 2) : -1, 'type', 1, 1, $forceall); 192 echo '</span>'; 193 } 194 // Predefined product/service 195 if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) 196 { 197 if ($forceall >= 0 && $freelines) echo '<br>'; 198 echo '<span class="prod_entry_mode_predef">'; 199 echo '<label for="prod_entry_mode_predef">'; 200 echo '<input type="radio" class="prod_entry_mode_predef" name="prod_entry_mode" id="prod_entry_mode_predef" value="predef"'.(GETPOST('prod_entry_mode') == 'predef' ? ' checked' : '').'> '; 201 if (empty($senderissupplier)) 202 { 203 if (!empty($conf->product->enabled) && empty($conf->service->enabled)) echo $langs->trans('PredefinedProductsToSell'); 204 elseif ((empty($conf->product->enabled) && !empty($conf->service->enabled)) || ($object->element == 'contrat' && empty($conf->global->CONTRACT_SUPPORT_PRODUCTS))) echo $langs->trans('PredefinedServicesToSell'); 205 else echo $langs->trans('PredefinedProductsAndServicesToSell'); 206 } else { 207 if (!empty($conf->product->enabled) && empty($conf->service->enabled)) echo $langs->trans('PredefinedProductsToPurchase'); 208 elseif (empty($conf->product->enabled) && !empty($conf->service->enabled)) echo $langs->trans('PredefinedServicesToPurchase'); 209 else echo $langs->trans('PredefinedProductsAndServicesToPurchase'); 210 } 211 echo '</label>'; 212 echo ' '; 213 $filtertype = ''; 214 if (!empty($object->element) && $object->element == 'contrat' && empty($conf->global->CONTRACT_SUPPORT_PRODUCTS)) $filtertype = '1'; 215 if (empty($senderissupplier)) 216 { 217 $statustoshow = 1; 218 if (!empty($conf->global->ENTREPOT_EXTRA_STATUS)) { 219 // hide products in closed warehouse, but show products for internal transfer 220 $form->select_produits(GETPOST('idprod'), 'idprod', $filtertype, $conf->product->limit_size, $buyer->price_level, $statustoshow, 2, '', 1, array(), $buyer->id, '1', 0, 'maxwidth500', 0, 'warehouseopen,warehouseinternal', GETPOST('combinations', 'array')); 221 } else { 222 $form->select_produits(GETPOST('idprod'), 'idprod', $filtertype, $conf->product->limit_size, $buyer->price_level, $statustoshow, 2, '', 1, array(), $buyer->id, '1', 0, 'maxwidth500', 0, '', GETPOST('combinations', 'array')); 223 } 224 if (!empty($conf->global->MAIN_AUTO_OPEN_SELECT2_ON_FOCUS_FOR_CUSTOMER_PRODUCTS)) 225 { 226 ?> 227 <script> 228 $(document).ready(function(){ 229 // On first focus on a select2 combo, auto open the menu (this allow to use the keyboard only) 230 $(document).on('focus', '.select2-selection.select2-selection--single', function (e) { 231 console.log('focus on a select2'); 232 if ($(this).attr('aria-labelledby') == 'select2-idprod-container') 233 { 234 console.log('open combo'); 235 $('#idprod').select2('open'); 236 } 237 }); 238 }); 239 </script> 240 <?php 241 } 242 } else { 243 // $senderissupplier=2 is the same as 1 but disables test on minimum qty, disable autofill qty with minimum and autofill unit price 244 if ($senderissupplier != 2) 245 { 246 $ajaxoptions = array( 247 'update' => array('qty'=>'qty', 'remise_percent' => 'discount', 'idprod' => 'idprod'), // html id tags that will be edited with each ajax json response key 248 'option_disabled' => 'idthatdoesnotexists', // html id to disable once select is done 249 'warning' => $langs->trans("NoPriceDefinedForThisSupplier") // translation of an error saved into var 'warning' (for example shown we select a disabled option into combo) 250 ); 251 $alsoproductwithnosupplierprice = 0; 252 } else { 253 $ajaxoptions = array( 254 'update' => array('remise_percent' => 'discount', 'price_ht' => 'up') // html id tags that will be edited with each ajax json response key 255 ); 256 $alsoproductwithnosupplierprice = 1; 257 } 258 $form->select_produits_fournisseurs($object->socid, GETPOST('idprodfournprice'), 'idprodfournprice', '', '', $ajaxoptions, 1, $alsoproductwithnosupplierprice, 'maxwidth500'); 259 if (!empty($conf->global->MAIN_AUTO_OPEN_SELECT2_ON_FOCUS_FOR_SUPPLIER_PRODUCTS)) 260 { 261 ?> 262 <script> 263 $(document).ready(function(){ 264 // On first focus on a select2 combo, auto open the menu (this allow to use the keyboard only) 265 $(document).on('focus', '.select2-selection.select2-selection--single', function (e) { 266 //console.log('focus on a select2'); 267 if ($(this).attr('aria-labelledby') == 'select2-idprodfournprice-container') 268 { 269 $('#idprodfournprice').select2('open'); 270 } 271 }); 272 }); 273 </script> 274 <?php 275 } 276 } 277 echo '<input type="hidden" name="pbq" id="pbq" value="">'; 278 echo '</span>'; 279 } 280 if (is_object($hookmanager) && empty($senderissupplier)) 281 { 282 $parameters = array('fk_parent_line'=>GETPOST('fk_parent_line', 'int')); 283 $reshook = $hookmanager->executeHooks('formCreateProductOptions', $parameters, $object, $action); 284 if (!empty($hookmanager->resPrint)) { 285 print $hookmanager->resPrint; 286 } 287 } 288 if (is_object($hookmanager) && !empty($senderissupplier)) 289 { 290 $parameters = array('htmlname'=>'addproduct'); 291 $reshook = $hookmanager->executeHooks('formCreateProductSupplierOptions', $parameters, $object, $action); 292 if (!empty($hookmanager->resPrint)) { 293 print $hookmanager->resPrint; 294 } 295 } 296 if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { 297 if (!empty($conf->variants->enabled)) { 298 echo '<div id="attributes_box"></div>'; 299 } 300 echo '<br>'; 301 } 302 // Editor wysiwyg 303 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; 304 $nbrows = ROWS_2; 305 $enabled = (!empty($conf->global->FCKEDITOR_ENABLE_DETAILS) ? $conf->global->FCKEDITOR_ENABLE_DETAILS : 0); 306 if (!empty($conf->global->MAIN_INPUT_DESC_HEIGHT)) $nbrows = $conf->global->MAIN_INPUT_DESC_HEIGHT; 307 $toolbarname = 'dolibarr_details'; 308 if (!empty($conf->global->FCKEDITOR_ENABLE_DETAILS_FULL)) $toolbarname = 'dolibarr_notes'; 309 $doleditor = new DolEditor('dp_desc', GETPOST('dp_desc', 'restricthtml'), '', (empty($conf->global->MAIN_DOLEDITOR_HEIGHT) ? 100 : $conf->global->MAIN_DOLEDITOR_HEIGHT), $toolbarname, '', false, true, $enabled, $nbrows, '98%'); 310 $doleditor->Create(); 311 // Show autofill date for recurring invoices 312 if (!empty($conf->service->enabled) && $object->element == 'facturerec') 313 { 314 echo '<div class="divlinefordates"><br>'; 315 echo $langs->trans('AutoFillDateFrom').' '; 316 echo $form->selectyesno('date_start_fill', $line->date_start_fill, 1); 317 echo ' - '; 318 echo $langs->trans('AutoFillDateTo').' '; 319 echo $form->selectyesno('date_end_fill', $line->date_end_fill, 1); 320 echo '</div>'; 321 } 322 echo '</td>'; 323 if ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier') // We must have same test in printObjectLines 324 { 325 $coldisplay++; 326 ?> 327 <td class="nobottom linecolresupplier"><input id="fourn_ref" name="fourn_ref" class="flat minwidth50 maxwidth150" value="<?php echo (GETPOSTISSET("fourn_ref") ? GETPOST("fourn_ref", 'alpha', 2) : ''); ?>"></td> 328 <?php } 329 print '<td class="nobottom linecolvat right">'; 330 $coldisplay++; 331 if ($seller->tva_assuj == "0") echo '<input type="hidden" name="tva_tx" id="tva_tx" value="0">'.vatrate(0, true); 332 else echo $form->load_tva('tva_tx', (GETPOSTISSET("tva_tx") ? GETPOST("tva_tx", 'alpha', 2) : -1), $seller, $buyer, 0, 0, '', false, 1); 333 ?> 334 </td> 335 336 <td class="nobottom linecoluht right"><?php $coldisplay++; ?> 337 <input type="text" size="5" name="price_ht" id="price_ht" class="flat right" value="<?php echo (GETPOSTISSET("price_ht") ? GETPOST("price_ht", 'alpha', 2) : ''); ?>"> 338 </td> 339 340 <?php 341 if (!empty($conf->multicurrency->enabled) && $this->multicurrency_code != $conf->currency) { 342 $coldisplay++; 343 ?> 344 <td class="nobottom linecoluht_currency right"> 345 <input type="text" size="5" name="multicurrency_price_ht" id="multicurrency_price_ht" class="flat right" value="<?php echo (GETPOSTISSET("multicurrency_price_ht") ? GETPOST("multicurrency_price_ht", 'alpha', 2) : ''); ?>"> 346 </td> 347 <?php 348 } 349 if (!empty($inputalsopricewithtax)) { 350 $coldisplay++; 351 ?> 352 <td class="nobottom linecoluttc right"> 353 <input type="text" size="5" name="price_ttc" id="price_ttc" class="flat" value="<?php echo (GETPOSTISSET("price_ttc") ? GETPOST("price_ttc", 'alpha', 2) : ''); ?>"> 354 </td> 355 <?php 356 } 357 $coldisplay++; 358 ?> 359 <td class="nobottom linecolqty right"><input type="text" size="2" name="qty" id="qty" class="flat right" value="<?php echo (GETPOSTISSET("qty") ? GETPOST("qty", 'alpha', 2) : 1); ?>"> 360 </td> 361 <?php 362 if (!empty($conf->global->PRODUCT_USE_UNITS)) { 363 $coldisplay++; 364 print '<td class="nobottom linecoluseunit left">'; 365 print $form->selectUnits(empty($line->fk_unit) ? $conf->global->PRODUCT_USE_UNITS : $line->fk_unit, "units"); 366 print '</td>'; 367 } 368 $remise_percent = $buyer->remise_percent; 369 if ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier') { 370 $remise_percent = $seller->remise_supplier_percent; 371 } 372 $coldisplay++; 373 ?> 374 <td class="nobottom nowrap linecoldiscount right"><input type="text" size="1" name="remise_percent" id="remise_percent" class="flat right" value="<?php echo (GETPOSTISSET("remise_percent") ? GETPOST("remise_percent", 'alpha', 2) : $remise_percent); ?>"><span class="hideonsmartphone">%</span></td> 375 <?php 376 if ($this->situation_cycle_ref) { 377 $coldisplay++; 378 print '<td class="nobottom nowrap right"><input class="falt right" type="text" size="1" value="0" name="progress">%</td>'; 379 $coldisplay++; 380 print '<td></td>'; 381 } 382 if (!empty($usemargins)) { 383 if (!empty($user->rights->margins->creer)) { 384 $coldisplay++; 385 ?> 386 <td class="nobottom margininfos linecolmargin right"> 387 <!-- For predef product --> 388 <?php if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { ?> 389 <select id="fournprice_predef" name="fournprice_predef" class="flat minwidth75imp maxwidth150" style="display: none;"></select> 390 <?php } ?> 391 <!-- For free product --> 392 <input type="text" id="buying_price" name="buying_price" class="flat maxwidth75 maxwidth150 right" value="<?php echo (GETPOSTISSET("buying_price") ? GETPOST("buying_price", 'alpha', 2) : ''); ?>"> 393 </td> 394 <?php 395 if (!empty($conf->global->DISPLAY_MARGIN_RATES)) 396 { 397 echo '<td class="nobottom nowrap margininfos right"><input class="flat right" type="text" size="2" id="np_marginRate" name="np_marginRate" value="'.(GETPOSTISSET("np_marginRate") ? GETPOST("np_marginRate", 'alpha', 2) : '').'"><span class="np_marginRate hideonsmartphone">%</span></td>'; 398 $coldisplay++; 399 } 400 if (!empty($conf->global->DISPLAY_MARK_RATES)) 401 { 402 echo '<td class="nobottom nowrap margininfos right"><input class="flat right" type="text" size="2" id="np_markRate" name="np_markRate" value="'.(GETPOSTISSET("np_markRate") ? GETPOST("np_markRate", 'alpha', 2) : '').'"><span class="np_markRate hideonsmartphone">%</span></td>'; 403 $coldisplay++; 404 } 405 } 406 } 407 $coldisplay += $colspan; 408 ?> 409 <td class="nobottom linecoledit center valignmiddle" colspan="<?php echo $colspan; ?>"> 410 <input type="submit" class="button" value="<?php echo $langs->trans('Add'); ?>" name="addline" id="addline"> 411 </td> 412</tr> 413 414<?php 415if (is_object($objectline)) { 416 print $objectline->showOptionals($extrafields, 'edit', array('colspan'=>$coldisplay), '', '', 1); 417} 418 419if ((!empty($conf->service->enabled) || ($object->element == 'contrat')) && $dateSelector && GETPOST('type') != '0') // We show date field if required 420{ 421 print '<tr id="trlinefordates" class="oddeven">'."\n"; 422 if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) { 423 print '<td></td>'; 424 } 425 print '<td colspan="'.($coldisplay - (empty($conf->global->MAIN_VIEW_LINE_NUMBER) ? 0 : 1)).'">'; 426 $date_start = dol_mktime(GETPOST('date_starthour'), GETPOST('date_startmin'), 0, GETPOST('date_startmonth'), GETPOST('date_startday'), GETPOST('date_startyear')); 427 $date_end = dol_mktime(GETPOST('date_starthour'), GETPOST('date_startmin'), 0, GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear')); 428 429 $prefillDates = false; 430 431 if (!empty($conf->global->MAIN_FILL_SERVICE_DATES_FROM_LAST_SERVICE_LINE) && !empty($object->lines)) 432 { 433 for ($i = count($object->lines) - 1; $i >= 0; $i--) 434 { 435 $lastline = $object->lines[$i]; 436 437 if ($lastline->product_type == Product::TYPE_SERVICE && (!empty($lastline->date_start) || !empty($lastline->date_end))) 438 { 439 $date_start_prefill = $lastline->date_start; 440 $date_end_prefill = $lastline->date_end; 441 442 $prefillDates = true; 443 break; 444 } 445 } 446 } 447 448 449 if (!empty($object->element) && $object->element == 'contrat') 450 { 451 print $langs->trans("DateStartPlanned").' '; 452 print $form->selectDate($date_start, "date_start", $usehm, $usehm, 1, "addproduct"); 453 print ' '.$langs->trans("DateEndPlanned").' '; 454 print $form->selectDate($date_end, "date_end", $usehm, $usehm, 1, "addproduct"); 455 } else { 456 print $langs->trans('ServiceLimitedDuration').' '.$langs->trans('From').' '; 457 print $form->selectDate($date_start, 'date_start', empty($conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE) ? 0 : 1, empty($conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE) ? 0 : 1, 1, "addproduct", 1, 0); 458 print ' '.$langs->trans('to').' '; 459 print $form->selectDate($date_end, 'date_end', empty($conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE) ? 0 : 1, empty($conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE) ? 0 : 1, 1, "addproduct", 1, 0); 460 }; 461 462 if ($prefillDates) 463 { 464 echo ' <span class="small"><a href="#" id="prefill_service_dates">'.$langs->trans('FillWithLastServiceDates').'</a></span>'; 465 } 466 467 print '<script>'; 468 469 if ($prefillDates) 470 { 471 ?> 472 function prefill_service_dates() 473 { 474 $('#date_start').val("<?php echo dol_escape_js(dol_print_date($date_start_prefill, '%d/%m/%Y')); ?>").trigger('change'); 475 $('#date_end').val("<?php echo dol_escape_js(dol_print_date($date_end_prefill, '%d/%m/%Y')); ?>").trigger('change'); 476 477 return false; // Prevent default link behaviour (which is go to href URL) 478 } 479 480 $(document).ready(function() 481 { 482 $('#prefill_service_dates').click(prefill_service_dates); 483 }); 484 485 <?php 486 } 487 488 if (!$date_start) { 489 if (isset($conf->global->MAIN_DEFAULT_DATE_START_HOUR)) { 490 print 'jQuery("#date_starthour").val("'.$conf->global->MAIN_DEFAULT_DATE_START_HOUR.'");'; 491 } 492 if (isset($conf->global->MAIN_DEFAULT_DATE_START_MIN)) { 493 print 'jQuery("#date_startmin").val("'.$conf->global->MAIN_DEFAULT_DATE_START_MIN.'");'; 494 } 495 } 496 if (!$date_end) { 497 if (isset($conf->global->MAIN_DEFAULT_DATE_END_HOUR)) { 498 print 'jQuery("#date_endhour").val("'.$conf->global->MAIN_DEFAULT_DATE_END_HOUR.'");'; 499 } 500 if (isset($conf->global->MAIN_DEFAULT_DATE_END_MIN)) { 501 print 'jQuery("#date_endmin").val("'.$conf->global->MAIN_DEFAULT_DATE_END_MIN.'");'; 502 } 503 } 504 print '</script>'; 505 print '</td>'; 506 print '</tr>'."\n"; 507} 508 509 510print "<script>\n"; 511if (!empty($usemargins) && $user->rights->margins->creer) 512{ 513 ?> 514 /* Some js test when we click on button "Add" */ 515 jQuery(document).ready(function() { 516 <?php 517 if (!empty($conf->global->DISPLAY_MARGIN_RATES)) { ?> 518 $("input[name='np_marginRate']:first").blur(function(e) { 519 return checkFreeLine(e, "np_marginRate"); 520 }); 521 <?php 522 } 523 if (!empty($conf->global->DISPLAY_MARK_RATES)) { ?> 524 $("input[name='np_markRate']:first").blur(function(e) { 525 return checkFreeLine(e, "np_markRate"); 526 }); 527 <?php 528 } 529 ?> 530 }); 531 532 /* TODO This does not work for number with thousand separator that is , */ 533 function checkFreeLine(e, npRate) 534 { 535 var buying_price = $("input[name='buying_price']:first"); 536 var remise = $("input[name='remise_percent']:first"); 537 538 var rate = $("input[name='"+npRate+"']:first"); 539 if (rate.val() == '') 540 return true; 541 542 if (! $.isNumeric(rate.val().replace(',','.'))) 543 { 544 alert('<?php echo dol_escape_js($langs->trans("rateMustBeNumeric")); ?>'); 545 e.stopPropagation(); 546 setTimeout(function () { rate.focus() }, 50); 547 return false; 548 } 549 if (npRate == "np_markRate" && rate.val() >= 100) 550 { 551 alert('<?php echo dol_escape_js($langs->trans("markRateShouldBeLesserThan100")); ?>'); 552 e.stopPropagation(); 553 setTimeout(function () { rate.focus() }, 50); 554 return false; 555 } 556 557 var price = 0; 558 remisejs=price2numjs(remise.val()); 559 560 if (remisejs != 100) // If a discount not 100 or no discount 561 { 562 if (remisejs == '') remisejs=0; 563 564 bpjs=price2numjs(buying_price.val()); 565 ratejs=price2numjs(rate.val()); 566 567 if (npRate == "np_marginRate") 568 price = ((bpjs * (1 + ratejs / 100)) / (1 - remisejs / 100)); 569 else if (npRate == "np_markRate") 570 price = ((bpjs / (1 - ratejs / 100)) / (1 - remisejs / 100)); 571 } 572 573 $("input[name='price_ht']:first").val(price); // TODO Must use a function like php price to have here a formated value 574 575 return true; 576 } 577 578 <?php 579} 580?> 581 582 /* JQuery for product free or predefined select */ 583 jQuery(document).ready(function() { 584 jQuery("#price_ht").keyup(function(event) { 585 // console.log(event.which); // discard event tag and arrows 586 if (event.which != 9 && (event.which < 37 ||event.which > 40) && jQuery("#price_ht").val() != '') { 587 jQuery("#price_ttc").val(''); 588 jQuery("#multicurrency_subprice").val(''); 589 } 590 }); 591 jQuery("#price_ttc").keyup(function(event) { 592 // console.log(event.which); // discard event tag and arrows 593 if (event.which != 9 && (event.which < 37 || event.which > 40) && jQuery("#price_ttc").val() != '') { 594 jQuery("#price_ht").val(''); 595 jQuery("#multicurrency_subprice").val(''); 596 } 597 }); 598 jQuery("#multicurrency_subprice").keyup(function(event) { 599 // console.log(event.which); // discard event tag and arrows 600 if (event.which != 9 && (event.which < 37 || event.which > 40) && jQuery("#price_ttc").val() != '') { 601 jQuery("#price_ht").val(''); 602 jQuery("#price_ttc").val(''); 603 } 604 }); 605 606 $("#prod_entry_mode_free").on( "click", function() { 607 setforfree(); 608 }); 609 $("#select_type").change(function() 610 { 611 setforfree(); 612 if (jQuery('#select_type').val() >= 0) 613 { 614 /* focus work on a standard textarea but not if field was replaced with CKEDITOR */ 615 jQuery('#dp_desc').focus(); 616 /* focus if CKEDITOR */ 617 if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined") 618 { 619 var editor = CKEDITOR.instances['dp_desc']; 620 if (editor) { editor.focus(); } 621 } 622 } 623 console.log("Hide/show date according to product type"); 624 if (jQuery('#select_type').val() == '0') 625 { 626 jQuery('#trlinefordates').hide(); 627 jQuery('.divlinefordates').hide(); 628 } 629 else 630 { 631 jQuery('#trlinefordates').show(); 632 jQuery('.divlinefordates').show(); 633 } 634 }); 635 636 $("#prod_entry_mode_predef").on( "click", function() { 637 console.log("click prod_entry_mode_predef"); 638 setforpredef(); 639 jQuery('#trlinefordates').show(); 640 }); 641 642 <?php 643 if (!$freelines) { ?> 644 $("#prod_entry_mode_predef").click(); 645 <?php 646 } 647 ?> 648 649 /* When changing predefined product, we reload list of supplier prices required for margin combo */ 650 $("#idprod, #idprodfournprice").change(function() 651 { 652 console.log("Call method change() after change on #idprod or #idprodfournprice (senderissupplier=<?php echo $senderissupplier; ?>). this.val = "+$(this).val()); 653 654 setforpredef(); // TODO Keep vat combo visible and set it to first entry into list that match result of get_default_tva 655 656 jQuery('#trlinefordates').show(); 657 658 <?php 659 if (empty($conf->global->MAIN_DISABLE_EDIT_PREDEF_PRICEHT) && empty($senderissupplier)) 660 { 661 ?> 662 var pbq = parseInt($('option:selected', this).attr('data-pbq')); /* If product was selected with a HTML select */ 663 if (isNaN(pbq)) { pbq = jQuery('#idprod').attr('data-pbq'); } /* If product was selected with a HTML input with autocomplete */ 664 //console.log(pbq); 665 666 if ((jQuery('#idprod').val() > 0 || jQuery('#idprodfournprice').val()) && ! isNaN(pbq) && pbq > 0) 667 { 668 console.log("We are in a price per qty context, we do not call ajax/product, init of fields is done few lines later"); 669 } else { 670 <?php if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) { ?> 671 if (isNaN(pbq)) { console.log("We use experimental option PRODUIT_CUSTOMER_PRICES_BY_QTY or PRODUIT_CUSTOMER_PRICES_BY_QTY but we could not get the id of pbq from product combo list, so load of price may be 0 if product has differet prices"); } 672 <?php } ?> 673 // Get the HT price for the product and display it 674 console.log("Load unit price without tax and set it into #price_ht for product id="+$(this).val()+" socid=<?php print $object->socid; ?>"); 675 $.post('<?php echo DOL_URL_ROOT; ?>/product/ajax/products.php?action=fetch', 676 { 'id': $(this).val(), 'socid': <?php print $object->socid; ?> }, 677 function(data) { 678 console.log("Load unit price end, we got value "+data.price_ht); 679 jQuery("#price_ht").val(data.price_ht); 680 }, 681 'json' 682 ); 683 } 684 <?php 685 } 686 687 if (!empty($usemargins) && $user->rights->margins->creer) 688 { 689 $langs->load('stocks'); 690 ?> 691 692 /* Code for margin */ 693 $("#fournprice_predef").find("option").remove(); 694 $("#fournprice_predef").hide(); 695 $("#buying_price").val("").show(); 696 697 /* Call post to load content of combo list fournprice_predef */ 698 var token = '<?php echo currentToken(); ?>'; // For AJAX Call we use old 'token' and not 'newtoken' 699 $.post('<?php echo DOL_URL_ROOT; ?>/fourn/ajax/getSupplierPrices.php?bestpricefirst=1', { 'idprod': $(this).val(), 'token': token }, function(data) { 700 if (data && data.length > 0) 701 { 702 var options = ''; var defaultkey = ''; var defaultprice = ''; var bestpricefound = 0; 703 704 var bestpriceid = 0; var bestpricevalue = 0; 705 var pmppriceid = 0; var pmppricevalue = 0; 706 var costpriceid = 0; var costpricevalue = 0; 707 708 /* setup of margin calculation */ 709 var defaultbuyprice = '<?php 710 if (isset($conf->global->MARGIN_TYPE)) 711 { 712 if ($conf->global->MARGIN_TYPE == '1') print 'bestsupplierprice'; 713 if ($conf->global->MARGIN_TYPE == 'pmp') print 'pmp'; 714 if ($conf->global->MARGIN_TYPE == 'costprice') print 'costprice'; 715 } ?>'; 716 console.log("we will set the field for margin. defaultbuyprice="+defaultbuyprice); 717 718 var i = 0; 719 $(data).each(function() { 720 /* Warning: Lines must be processed in order: best supplier price, then pmpprice line then costprice */ 721 if (this.id != 'pmpprice' && this.id != 'costprice') 722 { 723 i++; 724 this.price = parseFloat(this.price); // to fix when this.price >0 725 // If margin is calculated on best supplier price, we set it by defaut (but only if value is not 0) 726 //console.log("id="+this.id+"-price="+this.price+"-"+(this.price > 0)); 727 if (bestpricefound == 0 && this.price > 0) { defaultkey = this.id; defaultprice = this.price; bestpriceid = this.id; bestpricevalue = this.price; bestpricefound=1; } // bestpricefound is used to take the first price > 0 728 } 729 if (this.id == 'pmpprice') 730 { 731 // If margin is calculated on PMP, we set it by defaut (but only if value is not 0) 732 console.log("id="+this.id+"-price="+this.price); 733 if ('pmp' == defaultbuyprice || 'costprice' == defaultbuyprice) 734 { 735 if (this.price > 0) { 736 defaultkey = this.id; defaultprice = this.price; pmppriceid = this.id; pmppricevalue = this.price; 737 //console.log("pmppricevalue="+pmppricevalue); 738 } 739 } 740 } 741 if (this.id == 'costprice') 742 { 743 // If margin is calculated on Cost price, we set it by defaut (but only if value is not 0) 744 console.log("id="+this.id+"-price="+this.price+"-pmppricevalue="+pmppricevalue); 745 if ('costprice' == defaultbuyprice) 746 { 747 if (this.price > 0) { defaultkey = this.id; defaultprice = this.price; costpriceid = this.id; costpricevalue = this.price; } 748 else if (pmppricevalue > 0) { defaultkey = 'pmpprice'; defaultprice = pmppricevalue; } 749 } 750 } 751 options += '<option value="'+this.id+'" price="'+this.price+'">'+this.label+'</option>'; 752 }); 753 options += '<option value="inputprice" price="'+defaultprice+'"><?php echo $langs->trans("InputPrice"); ?></option>'; 754 755 console.log("finally selected defaultkey="+defaultkey+" defaultprice for buying price="+defaultprice); 756 757 $("#fournprice_predef").html(options).show(); 758 if (defaultkey != '') 759 { 760 $("#fournprice_predef").val(defaultkey); 761 } 762 763 /* At loading, no product are yet selected, so we hide field of buying_price */ 764 $("#buying_price").hide(); 765 766 /* Define default price at loading */ 767 var defaultprice = $("#fournprice_predef").find('option:selected').attr("price"); 768 $("#buying_price").val(defaultprice); 769 770 $("#fournprice_predef").change(function() { 771 console.log("change on fournprice_predef"); 772 /* Hide field buying_price according to choice into list (if 'inputprice' or not) */ 773 var linevalue=$(this).find('option:selected').val(); 774 var pricevalue = $(this).find('option:selected').attr("price"); 775 if (linevalue != 'inputprice' && linevalue != 'pmpprice') { 776 $("#buying_price").val(pricevalue).hide(); /* We set value then hide field */ 777 } 778 if (linevalue == 'inputprice') { 779 $('#buying_price').show(); 780 } 781 if (linevalue == 'pmpprice') { 782 $("#buying_price").val(pricevalue); 783 $('#buying_price').hide(); 784 } 785 }); 786 } 787 }, 788 'json'); 789 790 <?php 791 } 792 ?> 793 794 /* To process customer price per quantity (CUSTOMER_PRICE_PER_QTY works only if combo product is not an ajax after x key pressed) */ 795 var pbq = parseInt($('option:selected', this).attr('data-pbq')); // When select is done from HTML select 796 if (isNaN(pbq)) { pbq = jQuery('#idprod').attr('data-pbq'); } // When select is done from HTML input with autocomplete 797 var pbqup = parseFloat($('option:selected', this).attr('data-pbqup')); 798 if (isNaN(pbqup)) { pbqup = jQuery('#idprod').attr('data-pbqup'); } 799 var pbqbase = $('option:selected', this).attr('data-pbqbase'); 800 if (isNaN(pbqbase)) { pbqbase = jQuery('#idprod').attr('data-pbqbase'); } 801 var pbqqty = parseFloat($('option:selected', this).attr('data-pbqqty')); 802 if (isNaN(pbqqty)) { pbqqty = jQuery('#idprod').attr('data-pbqqty'); } 803 var pbqpercent = parseFloat($('option:selected', this).attr('data-pbqpercent')); 804 if (isNaN(pbqpercent)) { pbqpercent = jQuery('#idprod').attr('data-pbqpercent'); } 805 806 if ((jQuery('#idprod').val() > 0 || jQuery('#idprodfournprice').val()) && ! isNaN(pbq) && pbq > 0) 807 { 808 var pbqupht = pbqup; /* TODO support of price per qty TTC not yet available */ 809 810 console.log("We choose a price by quanty price_by_qty id = "+pbq+" price_by_qty upht = "+pbqupht+" price_by_qty qty = "+pbqqty+" price_by_qty percent = "+pbqpercent); 811 jQuery("#pbq").val(pbq); 812 jQuery("#price_ht").val(pbqupht); 813 if (jQuery("#qty").val() < pbqqty) 814 { 815 jQuery("#qty").val(pbqqty); 816 } 817 if (jQuery("#remise_percent").val() < pbqpercent) 818 { 819 jQuery("#remise_percent").val(pbqpercent); 820 } 821 } 822 else 823 { 824 jQuery("#pbq").val(''); 825 } 826 827 /* To set focus */ 828 if (jQuery('#idprod').val() > 0 || jQuery('#idprodfournprice').val() > 0) 829 { 830 /* focus work on a standard textarea but not if field was replaced with CKEDITOR */ 831 jQuery('#dp_desc').focus(); 832 /* focus if CKEDITOR */ 833 if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined") 834 { 835 var editor = CKEDITOR.instances['dp_desc']; 836 if (editor) { editor.focus(); } 837 } 838 } 839 }); 840 841 <?php if (GETPOST('prod_entry_mode') == 'predef') { // When we submit with a predef product and it fails we must start with predef ?> 842 setforpredef(); 843 <?php } ?> 844 }); 845 846 /* Function to set fields from choice */ 847 function setforfree() { 848 console.log("Call setforfree. We show most fields"); 849 jQuery("#idprodfournprice").val('0'); // Set cursor on not selected product 850 jQuery("#prod_entry_mode_free").prop('checked',true).change(); 851 jQuery("#prod_entry_mode_predef").prop('checked',false).change(); 852 jQuery("#search_idprod, #idprod, #search_idprodfournprice, #buying_price").val(''); 853 jQuery("#price_ht, #multicurrency_price_ht, #price_ttc, #price_ttc, #fourn_ref, #tva_tx, #buying_price, #title_fourn_ref, #title_vat, #title_up_ht, #title_up_ht_currency, #title_up_ttc, #title_up_ttc_currency").show(); 854 jQuery("#np_marginRate, #np_markRate, .np_marginRate, .np_markRate, #units, #title_units").show(); 855 jQuery("#fournprice_predef").hide(); 856 } 857 function setforpredef() { 858 console.log("Call setforpredef. We hide some fields and show dates"); 859 jQuery("#select_type").val(-1); 860 jQuery("#prod_entry_mode_free").prop('checked',false).change(); 861 jQuery("#prod_entry_mode_predef").prop('checked',true).change(); 862 <?php if (empty($conf->global->MAIN_DISABLE_EDIT_PREDEF_PRICEHT)) { ?> 863 jQuery("#price_ht").val('').show(); 864 jQuery("#multicurrency_price_ht").val('').show(); 865 jQuery("#title_up_ht, #title_up_ht_currency").show(); 866 <?php } else { ?> 867 jQuery("#price_ht").val('').hide(); 868 jQuery("#multicurrency_price_ht").val('').hide(); 869 jQuery("#title_up_ht, #title_up_ht_currency").hide(); 870 <?php } ?> 871 jQuery("#price_ttc, #fourn_ref, #tva_tx, #title_fourn_ref, #title_vat, #title_up_ttc, #title_up_ttc_currency").hide(); 872 jQuery("#np_marginRate, #np_markRate, .np_marginRate, .np_markRate, #units, #title_units").hide(); 873 jQuery("#buying_price").show(); 874 jQuery('#trlinefordates, .divlinefordates').show(); 875 } 876 877<?php 878 879print '</script>'; 880 881print "<!-- END PHP TEMPLATE objectline_create.tpl.php -->\n"; 882