2020-03-22 12:31:27 +01:00
< ? php
2015-12-18 18:00:31 +01:00
// Copyright (C) 2014 Cedric GROSS <c.gross@kreiz-it.fr>
2017-09-26 12:32:50 +02:00
// Copyright (C) 2017 Francis Appels <francis.appels@z-application.com>
2015-12-18 18:00:31 +01:00
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
2019-09-23 21:55:30 +02:00
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// or see https://www.gnu.org/
2015-12-18 18:00:31 +01:00
2020-03-22 12:31:27 +01:00
/**
2020-03-22 17:06:59 +01:00
* \file htdocs / fourn / js / lib_dispatch . js . php
2020-03-22 12:31:27 +01:00
* \brief File that include javascript functions used for dispatching qty / stock / lot
*/
2021-02-25 23:21:30 +01:00
if ( ! defined ( 'NOREQUIRESOC' )) {
define ( 'NOREQUIRESOC' , '1' );
}
if ( ! defined ( 'NOCSRFCHECK' )) {
define ( 'NOCSRFCHECK' , 1 );
}
if ( ! defined ( 'NOTOKENRENEWAL' )) {
define ( 'NOTOKENRENEWAL' , 1 );
}
if ( ! defined ( 'NOLOGIN' )) {
define ( 'NOLOGIN' , 1 );
}
if ( ! defined ( 'NOREQUIREMENU' )) {
define ( 'NOREQUIREMENU' , 1 );
}
if ( ! defined ( 'NOREQUIREHTML' )) {
define ( 'NOREQUIREHTML' , 1 );
}
if ( ! defined ( 'NOREQUIREAJAX' )) {
define ( 'NOREQUIREAJAX' , '1' );
}
2015-12-18 18:00:31 +01:00
2020-03-22 12:31:27 +01:00
session_cache_limiter ( 'public' );
require_once '../../main.inc.php' ;
// Define javascript type
top_httphead ( 'text/javascript; charset=UTF-8' );
// Important: Following code is to avoid page request by browser and PHP CPU at each Dolibarr page access.
2021-02-25 23:21:30 +01:00
if ( empty ( $dolibarr_nocache )) {
header ( 'Cache-Control: max-age=10800, public, must-revalidate' );
} else {
header ( 'Cache-Control: no-cache' );
}
2020-03-22 12:31:27 +01:00
?>
2015-12-18 18:00:31 +01:00
/**
* addDispatchLine
2020-03-22 12:31:27 +01:00
* Adds new table row for dispatching to multiple stock locations or multiple lot / serial
2018-07-26 18:22:16 +02:00
*
2017-09-26 12:32:50 +02:00
* @ param index int index of product line . 0 = first product line
2015-12-18 18:00:31 +01:00
* @ param type string type of dispatch ( batch = batch dispatch , dispatch = non batch dispatch )
2017-06-27 13:57:41 +02:00
* @ param mode string 'qtymissing' will create new line with qty missing , 'lessone' will keep 1 in old line and the rest in new one
2015-12-18 18:00:31 +01:00
*/
2018-07-26 18:22:16 +02:00
function addDispatchLine ( index , type , mode )
2015-12-18 18:00:31 +01:00
{
2017-06-27 13:57:41 +02:00
mode = mode || 'qtymissing'
2018-07-26 18:22:16 +02:00
2020-03-22 12:31:27 +01:00
console . log ( " fourn/js/lib_dispatch.js.php Split line type= " + type + " index= " + index + " mode= " + mode );
2021-07-19 14:06:56 +02:00
var $row0 = $ ( " tr[name=' " + type + '_0_' + index + " '] " );
var $dpopt = $row0 . find ( '.hasDatepicker' ) . first () . datepicker ( 'option' , 'all' ); // get current datepicker options to apply the same to the cloned datepickers
var $row = $row0 . clone ( true ); // clone first batch line to jQuery object
2020-03-22 17:06:59 +01:00
var nbrTrs = $ ( " tr[name^=' " + type + " _'][name $ ='_ " + index + " '] " ) . length ; // position of line for batch
var qtyOrdered = parseFloat ( $ ( " #qty_ordered_0_ " + index ) . val ()); // Qty ordered is same for all rows
var qty = parseFloat ( $ ( " #qty_ " + ( nbrTrs - 1 ) + " _ " + index ) . val ());
var qtyDispatched ;
2018-07-26 18:22:16 +02:00
if ( mode === 'lessone' )
2015-12-18 18:00:31 +01:00
{
2017-09-26 12:32:50 +02:00
qtyDispatched = parseFloat ( $ ( " #qty_dispatched_0_ " + index ) . val ()) + 1 ;
2015-12-18 18:00:31 +01:00
}
else
{
2017-09-26 12:32:50 +02:00
qtyDispatched = parseFloat ( $ ( " #qty_dispatched_0_ " + index ) . val ()) + qty ;
2020-03-22 12:31:27 +01:00
// If user did not reduced the qty to dispatch on old line, we keep only 1 on old line and the rest on new line
if ( qtyDispatched == qtyOrdered && qtyDispatched > 1 ) {
qtyDispatched = parseFloat ( $ ( " #qty_dispatched_0_ " + index ) . val ()) + 1 ;
mode = 'lessone' ;
}
2015-12-18 18:00:31 +01:00
}
2020-03-22 12:31:27 +01:00
console . log ( " qtyDispatched= " + qtyDispatched + " qtyOrdered= " + qtyOrdered );
2018-07-26 18:22:16 +02:00
2020-03-22 12:31:27 +01:00
if ( qtyOrdered <= 1 ) {
window . alert ( " Quantity can't be split " );
2021-02-27 00:31:29 +01:00
} else if ( qtyDispatched < qtyOrdered ) {
2015-12-18 18:00:31 +01:00
//replace tr suffix nbr
$row . html ( $row . html () . replace ( / _0_ / g , " _ " + nbrTrs + " _ " ));
2021-07-19 14:06:56 +02:00
// jquery's deep clone is incompatible with date pickers (the clone shares data with the original)
// so we destroy and rebuild the new date pickers
setTimeout (() => {
$row . find ( '.hasDatepicker' ) . each (( i , dp ) => {
$ ( dp ) . removeData ()
. removeClass ( 'hasDatepicker' );
$ ( dp ) . next ( 'img.ui-datepicker-trigger' ) . remove ();
$ ( dp ) . datepicker ( $dpopt );
});
}, 0 );
2015-12-18 18:00:31 +01:00
//create new select2 to avoid duplicate id of cloned one
$row . find ( " select[name=' " + 'entrepot_' + nbrTrs + '_' + index + " '] " ) . select2 ();
// TODO find solution to copy selected option to new select
// TODO find solution to keep new tr's after page refresh
//clear value
$row . find ( " input[name^='qty'] " ) . val ( '' );
//change name of new row
$row . attr ( 'name' , type + '_' + nbrTrs + '_' + index );
//insert new row before last row
$ ( " tr[name^=' " + type + " _'][name $ ='_ " + index + " ']:last " ) . after ( $row );
2018-07-26 18:22:16 +02:00
2015-12-18 18:00:31 +01:00
//remove cloned select2 with duplicate id.
2018-06-16 17:18:17 +02:00
$ ( " #s2id_entrepot_ " + nbrTrs + '_' + index ) . detach (); // old way to find duplicated select2 component
2018-06-16 17:25:16 +02:00
$ ( " .csswarehouse_ " + nbrTrs + " _ " + index + " :first-child " ) . parent ( " span.selection " ) . parent ( " .select2 " ) . detach ();
2018-07-26 18:22:16 +02:00
2015-12-18 18:00:31 +01:00
/* Suffix of lines are: _ trs.length _ index */
$ ( " #qty_ " + nbrTrs + " _ " + index ) . focus ();
2017-09-26 12:32:50 +02:00
$ ( " #qty_dispatched_0_ " + index ) . val ( qtyDispatched );
2018-07-26 18:22:16 +02:00
2017-06-27 13:57:41 +02:00
//hide all buttons then show only the last one
$ ( " tr[name^=' " + type + " _'][name $ ='_ " + index + " '] .splitbutton " ) . hide ();
$ ( " tr[name^=' " + type + " _'][name $ ='_ " + index + " ']:last .splitbutton " ) . show ();
2018-07-26 18:22:16 +02:00
2017-06-27 13:57:41 +02:00
if ( mode === 'lessone' )
2015-12-18 18:00:31 +01:00
{
2017-09-26 15:44:40 +02:00
qty = 1 ; // keep 1 in old line
$ ( " #qty_ " + ( nbrTrs - 1 ) + " _ " + index ) . val ( qty );
2017-06-27 13:57:41 +02:00
}
2017-09-26 15:44:40 +02:00
$ ( " #qty_ " + nbrTrs + " _ " + index ) . val ( qtyOrdered - qtyDispatched );
// Store arbitrary data for dispatch qty input field change event
$ ( " #qty_ " + ( nbrTrs - 1 ) + " _ " + index ) . data ( 'qty' , qty );
$ ( " #qty_ " + ( nbrTrs - 1 ) + " _ " + index ) . data ( 'type' , type );
$ ( " #qty_ " + ( nbrTrs - 1 ) + " _ " + index ) . data ( 'index' , index );
// Update dispatched qty when value dispatch qty input field changed
$ ( " #qty_ " + ( nbrTrs - 1 ) + " _ " + index ) . change ( this . onChangeDispatchLineQty );
2017-06-27 13:57:41 +02:00
//set focus on lot of new line (if it exists)
$ ( " #lot_number_ " + ( nbrTrs ) + " _ " + index ) . focus ();
2015-12-18 18:00:31 +01:00
}
2017-09-26 12:32:50 +02:00
}
/**
* onChangeDispatchLineQty
2018-07-26 18:22:16 +02:00
*
* Change event handler for dispatch qty input field ,
2017-09-26 15:44:40 +02:00
* recalculate qty dispatched when qty input has changed .
2020-03-22 17:06:59 +01:00
* If qty is more than qty ordered reset input qty to max qty to dispatch .
2018-07-26 18:22:16 +02:00
*
2017-09-26 12:32:50 +02:00
* element requires arbitrary data qty ( value before change ), type ( type of dispatch ) and index ( index of product line )
*/
function onChangeDispatchLineQty () {
var index = $ ( this ) . data ( 'index' ),
type = $ ( this ) . data ( 'type' ),
qty = parseFloat ( $ ( this ) . data ( 'qty' )),
changedQty , nbrTrs , dispatchingQty , qtyOrdered , qtyDispatched ;
if ( index >= 0 && type && qty >= 0 ) {
nbrTrs = $ ( " tr[name^=' " + type + " _'][name $ ='_ " + index + " '] " ) . length ;
qtyChanged = parseFloat ( $ ( this ) . val ()) - qty ; // qty changed
qtyDispatching = parseFloat ( $ ( " #qty_ " + ( nbrTrs - 1 ) + " _ " + index ) . val ()); // qty currently being dispatched
qtyOrdered = parseFloat ( $ ( " #qty_ordered_0_ " + index ) . val ()); // qty ordered
qtyDispatched = parseFloat ( $ ( " #qty_dispatched_0_ " + index ) . val ()); // qty already dispatched
2017-09-26 15:44:40 +02:00
console . log ( " onChangeDispatchLineQty qtyChanged: " + qtyChanged + " qtyDispatching: " + qtyDispatching + " qtyOrdered: " + qtyOrdered + " qtyDispatched: " + qtyDispatched );
2017-09-26 12:32:50 +02:00
if (( qtyChanged ) <= ( qtyOrdered - ( qtyDispatched + qtyDispatching ))) {
$ ( " #qty_dispatched_0_ " + index ) . val ( qtyDispatched + qtyChanged );
} else {
$ ( this ) . val ( $ ( this ) . data ( 'qty' ));
}
$ ( this ) . data ( 'qty' , $ ( this ) . val ());
}
2018-07-26 18:22:16 +02:00
}