27if (!defined(
'NOREQUIRESOC')) {
28 define(
'NOREQUIRESOC',
'1');
30if (!defined(
'NOCSRFCHECK')) {
31 define(
'NOCSRFCHECK', 1);
33if (!defined(
'NOTOKENRENEWAL')) {
34 define(
'NOTOKENRENEWAL', 1);
36if (!defined(
'NOLOGIN')) {
39if (!defined(
'NOREQUIREMENU')) {
40 define(
'NOREQUIREMENU', 1);
42if (!defined(
'NOREQUIREHTML')) {
43 define(
'NOREQUIREHTML', 1);
45if (!defined(
'NOREQUIREAJAX')) {
46 define(
'NOREQUIREAJAX',
'1');
49session_cache_limiter(
'public');
51require_once
'../../main.inc.php';
57$langs->loadLangs(array(
"productbatch"));
62header(
'Cache-Control: max-age=10800, public, must-revalidate');
74function addDispatchLine(index,
type, mode, lotnumber) {
75 mode = mode ||
'qtymissing'
76 lotnumber = lotnumber ||
''
78 console.log(
"fourn/js/lib_dispatch.js.php addDispatchLine Split line type="+
type+
" index="+index+
" mode="+mode);
80 var $row0 = $(
"tr[name='"+
type+
'_0_'+index+
"']");
81 var $dpopt = $row0.find(
'.hasDatepicker').first().datepicker(
'option',
'all');
82 var $row = $row0.clone(
true);
83 var nbrTrs = $(
"tr[name^='"+
type+
"_'][name$='_"+index+
"']").length;
84 var qtyOrdered = parseFloat($(
"#qty_ordered_0_"+index).val());
86 var qty = parseFloat($(
"#qty_"+(nbrTrs - 1)+
"_"+index).val());
91 console.log(
"fourn/js/lib_dispatch.js.php addDispatchLine Split line nbrTrs="+nbrTrs+
" qtyOrdered="+qtyOrdered+
" qty="+qty);
95 if (mode ===
'lessone') {
96 qtyDispatched = parseFloat($(
"#qty_dispatched_0_" + index).val()) + 1;
99 qtyDispatched = parseFloat($(
"#qty_dispatched_0_" + index).val()) + qty;
101 if (lotnumber ===
'' && qtyDispatched == qtyOrdered && qtyDispatched > 1) {
102 qtyDispatched = parseFloat($(
"#qty_dispatched_0_" + index).val()) + 1;
106 console.log(
"qtyDispatched=" + qtyDispatched +
" qtyOrdered=" + qtyOrdered+
" qty=" + qty);
108 if (qty <= 1 && lotnumber ===
'') {
109 window.alert(
"Remain quantity to dispatch is too low to be split");
111 var oldlineqty = qtyDispatched;
112 var newlineqty = qtyOrdered - qtyDispatched;
113 if (lotnumber !==
'') {
115 }
else if (newlineqty <= 0) {
116 newlineqty = qty - 1;
118 $(
"#qty_"+(nbrTrs - 1)+
"_"+index).val(oldlineqty);
122 $row.html($row.html().replace(/_0_/g,
"_" + nbrTrs +
"_"));
127 $row.find(
'.hasDatepicker').each((i, dp) => {
129 .removeClass(
'hasDatepicker');
130 $(dp).next(
'img.ui-datepicker-trigger').remove();
131 $(dp).datepicker($dpopt);
136 $row.find(
"select[name='" +
'entrepot_' + nbrTrs +
'_' + index +
"']").select2();
138 let $prevRow = $(
"tr[name^='" +
type +
"_'][name$='_" + index +
"']:last")
139 let $prevEntr = Number($prevRow.find("select[
name='" + 'entrepot_' + (nbrTrs-1) + '_' + index + "']").val())
140 $row.find("select[
name='" + 'entrepot_' + nbrTrs + '_' + index + "']").val($prevEntr)
143 $row.find("input[
name^='qty']").val('');
145 $row.attr('
name',
type + '_' + nbrTrs + '_' + index);
147 $("tr[
name^='" +
type + "_'][name$='_" + index + "']:last").after($row);
150 $("
#s2id_entrepot_" + nbrTrs + '_' + index).detach(); // old way to find duplicated select2 component
151 $(".csswarehouse_" + nbrTrs + "_" + index + ":first-child").parent("span.selection").parent(".select2").detach();
153 /* Suffix of lines are: _ trs.length _ index */
154 $("#qty_"+nbrTrs+"_"+index).focus();
155 $("#qty_dispatched_0_"+index).val(oldlineqty);
157 //hide all buttons then show only the last one
158 $("tr[name^='" + type + "_'][name$='_" + index + "'] .splitbutton").hide();
159 $("tr[name^='" + type + "_'][name$='_" + index + "']:last .splitbutton").show();
161 $("#reset_" + (nbrTrs) + "_" + index).click(function (event) {
162 event.preventDefault();
163 id = $(this).attr("id");
164 id = id.split("reset_");
166 idlast = $("tr[name^='" + type + "_'][name$='_" + index + "']:last .qtydispatchinput").attr("id");
167 if (idlast == $("#qty_" + idrow).attr("id")) {
168 console.log("Remove trigger for tr name = " + type + "_" + idrow);
169 $('tr[name="' + type + '_' + idrow + '"').remove();
170 $("tr[name^='" + type + "_'][name$='_" + index + "']:last .splitbutton").show();
172 console.log("fourn/js/lib_dispatch.js.php Reset trigger for id = qty_" + idrow);
173 $("#qty_" + idrow).val("");
177 if (mode === 'lessone')
179 qty = 1; // keep 1 in old line
180 $("#qty_"+(nbrTrs-1)+"_"+index).val(qty);
182 $("#qty_"+nbrTrs+"_"+index).val(newlineqty);
183 // Store arbitrary data for dispatch qty input field change event
184 $("#qty_" + (nbrTrs - 1) + "_" + index).data('qty', qty);
185 $("#qty_" + (nbrTrs - 1) + "_" + index).data('type', type);
186 $("#qty_" + (nbrTrs - 1) + "_" + index).data('index', index);
187 // Update dispatched qty when value dispatch qty input field changed
188 //$("#qty_" + (nbrTrs - 1) + "_" + index).change(this.onChangeDispatchLineQty);
190 $("tr[name^='" + type + "_'][name$='_" + index + "']:last").data("remove", "remove");
191 $("#lot_number_" + (nbrTrs) + "_" + index).val(lotnumber)
192 $("#idline_" + (nbrTrs) + "_" + index).val("-1")
193 $("#qty_" + (nbrTrs) + "_" + index).data('expected', "0");
194 $("#lot_number_" + (nbrTrs) + "_" + index).removeAttr("disabled");
195 //set focus on lot of new line (if it exists)
196 if ($("#lot_number_" + (nbrTrs) + "_" + index).length) {
197 $("#lot_number_" + (nbrTrs) + "_" + index).focus().select();
199 $("#qty_" + (nbrTrs) + "_" + index).focus().select();
213function addDispatchLinesFromSerialList(index, type) {
214 console.log("fourn/js/lib_dispatch.js.php addDispatchLinesFromSerialList type="+type+" index="+index);
216 var $dialog = jQuery("#dialogforpopup");
217 var html = '<textarea id="seriallist" class="centpercent" rows="10" placeholder=<?php echo "'".dol_escape_js(dol_escape_htmltag($langs->transnoentitiesnoconv("EnterOneSerialNumberPerLine")))."'" ; ?>></textarea>';
218 html += '<div id="seriallistmessage" class="opacitymedium paddingtop"></div>';
221 // Return the list of non empty trimmed lines
222 var getSerialList = function() {
223 return jQuery("#seriallist").val().split(/\r\n|\r|\n/).map(function(s) { return s.trim(); }).filter(function(s) { return s !== ''; });
226 jQuery("#seriallist").on("input", function() {
227 jQuery("#seriallistmessage").removeClass("error").text(<?php echo "'".dol_escape_js($langs->transnoentitiesnoconv("NbOfSerialNumbersDetected", "%s"))."'" ; ?>.replace('%s', getSerialList().length));
231 title: <?php echo "'".dol_escape_js($langs->transnoentitiesnoconv("EnterMultipleSerialNumbers"))."'" ; ?>,
237 text: <?php echo "'".dol_escape_js($langs->transnoentitiesnoconv("Apply"))."'" ; ?>,
239 var serials = getSerialList();
240 if (serials.length == 0) {
243 // Cheap early check of duplicates inside the list. Uniqueness in stock is still checked by MouvementStock.
245 for (var n = 0; n < serials.length; n++) {
246 if (seen[serials[n]]) {
247 jQuery("#seriallistmessage").addClass("error").text(<?php echo "'".dol_escape_js($langs->transnoentitiesnoconv("ErrorDuplicateSerialNumberInList", "%s"))."'" ; ?>.replace('%s', serials[n]));
250 seen[serials[n]] = true;
253 var nbrTrs = $("tr[name^='"+type+"_'][name$='_"+index+"']").length;
254 var $lastlot = $("#lot_number_"+(nbrTrs - 1)+"_"+index);
256 // Reuse the last line if it is still empty (not a saved line and no lot/serial entered yet)
257 if (!$lastlot.prop('disabled') && $lastlot.val().trim() === '') {
258 $lastlot.val(serials[0]);
259 $("#qty_"+(nbrTrs - 1)+"_"+index).val(1);
262 for (; k < serials.length; k++) {
263 addDispatchLine(index, type, 'qtymissing', serials[k]);
266 jQuery(this).dialog("close");
270 text: <?php echo "'".dol_escape_js($langs->transnoentitiesnoconv("Cancel"))."'" ; ?>,
272 jQuery(this).dialog("close");
277 jQuery("#seriallist").focus();
289function onChangeDispatchLineQty(element) {
290 var type = $(element).data('type'),
291 qty = parseFloat($(element).data('expected')),
292 changedQty, nbrTrs, dispatchingQty, qtyOrdered, qtyDispatched;
293 id = $(element).attr("id");
297 if (index >= 0 && type && qty >= 0) {
298 nbrTrs = $("tr[name^='" + type + "_'][name$='_" + index + "']").length;
299 qtyChanged = parseFloat($(element).val()) - qty; // qty changed
300 qtyDispatching = parseFloat($(element).val()); // qty currently being dispatched
301 qtyOrdered = parseFloat($("#qty_ordered_0_" + index).val()); // qty ordered
302 qtyDispatched = parseFloat($("#qty_dispatched_0_" + index).val()); // qty already dispatched
304 console.log("onChangeDispatchLineQty qtyChanged: " + qtyChanged + " qtyDispatching: " + qtyDispatching + " qtyOrdered: " + qtyOrdered + " qtyDispatched: " + qtyDispatched);
306 if ((qtyChanged) <= (qtyOrdered - (qtyDispatched + qtyDispatching))) {
307 $("#qty_dispatched_0_" + index).val(qtyDispatched + qtyChanged);
309 /*console.log("eee");
310 $(element).val($(element).data('expected'));*/
312 $(element).data('expected', $(element).val());
316$(document).ready(function () {
317 $(document).on('keydown', '.inputlotnumber', function (e) {
318 if (e.key === 'Enter' || e.keyCode === 13 || e.which === 13) {
321 var $input = $(this);
322 var $tr = $input.closest('tr');
323 var trName = $tr.attr('name');
328 var parts = trName.split('_');
329 if (parts.length < 3) {
334 var rowIdx = parseInt(parts[1], 10);
335 var prodIdx = parseInt(parts[2], 10);
337 var $rows = $("tr[name^='" + type + "_'][name$='_" + prodIdx + "']");
338 var nbrTrs = $rows.length;
340 // If user is on the last row of this product line
341 if (rowIdx === nbrTrs - 1) {
342 var qty = parseFloat($("#qty_" + rowIdx + "_" + prodIdx).val());
344 addDispatchLine(prodIdx, type);
346 // Last line for this product reached, try focusing next product line if available
347 var nextProdIdx = prodIdx + 1;
348 var $nextLot = $("#lot_number_0_" + nextProdIdx);
349 if ($nextLot.length && !$nextLot.prop('disabled')) {
350 $nextLot.focus().select();
354 // Move focus to next row's lot input if it exists
355 var $nextRowLot = $("#lot_number_" + (rowIdx + 1) + "_" + prodIdx);
356 if ($nextRowLot.length) {
357 $nextRowLot.focus().select();
$propal type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
if(!defined( 'NOREQUIREMENU')) if(!empty(GETPOST('seteventmessages', 'alpha'))) if(!function_exists("llxHeader")) top_httphead($contenttype='text/html', $forcenocache=0)
Show HTTP header.
$conf db name
Only used if Module[ID]Name translation string is not found.