mirror of
https://github.com/Dolibarr/dolibarr.git
synced 2025-02-20 13:46:52 +01:00
NEW Can switch product batch management to no management. (#21691)
* NEW : When an user unset the batch management of products, transformation of each batch stock mouvement in global stock mouvement * FIX : Alert on deserialize product * FIX : Correction of the trad * Fixing style errors. * FIX : PR returns * FIX : using llx_product_batch table * FIX : langs * Fixing style errors. * FIX : $value must be an absolute value * FIX : init $inventorycode before while loop * Fixing style errors. * FIX : "Yes (unique serial number required)" choice must not be available on product edit if its current status batch is "Yes (lot required)" * Fixing style errors. * FIX : Just display a message when we change from batch to serial * Fixing style errors. * Update card.php * Update card.php * Update product.class.php * Update product.class.php --------- Co-authored-by: Adrien Raze <adrien.raze@atm-consulting.fr> Co-authored-by: stickler-ci <support@stickler-ci.com> Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
This commit is contained in:
parent
5d6cf7cd51
commit
f46482a72a
|
|
@ -432,3 +432,5 @@ ConfirmEditExtrafield = Select the extrafield you want modify
|
|||
ConfirmEditExtrafieldQuestion = Are you sure you want to modify this extrafield?
|
||||
ModifyValueExtrafields = Modify value of an extrafield
|
||||
OrProductsWithCategories=Or products with tags/categories
|
||||
WarningTransferBatchStockMouvToGlobal = If you want to deserialize this product, all its serialized stock will be transformed into global stock
|
||||
WarningConvertFromBatchToSerial=If you currently have a quantity higher or equal to 2 for the product, switching to this choice means you will still have a product with different objects of the same batch (while you want a unique serial number). The duplicate will remain until an inventory or a manual stock movement to fix this is done.
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ qtyToTranferLotIsNotEnough=You don't have enough stock, for this lot number, fro
|
|||
ShowWarehouse=Show warehouse
|
||||
MovementCorrectStock=Stock correction for product %s
|
||||
MovementTransferStock=Stock transfer of product %s into another warehouse
|
||||
BatchStockMouvementAddInGlobal=Batch stock move into global stock (product doesn't use batch anymore)
|
||||
InventoryCodeShort=Inv./Mov. code
|
||||
NoPendingReceptionOnSupplierOrder=No pending reception due to open purchase order
|
||||
ThisSerialAlreadyExistWithDifferentDate=This lot/serial number (<strong>%s</strong>) already exists but with different eatby or sellby date (found <strong>%s</strong> but you enter <strong>%s</strong>).
|
||||
|
|
@ -322,6 +323,8 @@ BatchNotFound=Lot / serial not found for this product
|
|||
StockEntryDate=Date of <br>entry in stock
|
||||
StockMovementWillBeRecorded=Stock movement will be recorded
|
||||
StockMovementNotYetRecorded=Stock movement will not be affected by this step
|
||||
|
||||
|
||||
WarningThisWIllAlsoDeleteStock=Warning, this will also destroy all quantities in stock in the warehouse
|
||||
ValidateInventory=Inventory validation
|
||||
IncludeSubWarehouse=Include sub-warehouse ?
|
||||
|
|
@ -331,3 +334,4 @@ ConfirmDeleteBatch=Are you sure you want to delete lot/serial ?
|
|||
WarehouseUsage=Warehouse usage
|
||||
InternalWarehouse=Internal warehouse
|
||||
ExternalWarehouse=External warehouse
|
||||
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ qtyToTranferLotIsNotEnough=Vous n'avez pas assez de stock, pour ce numéro de lo
|
|||
ShowWarehouse=Afficher entrepôt
|
||||
MovementCorrectStock=Correction du stock pour le produit %s
|
||||
MovementTransferStock=Transfert de stock du produit %s dans un autre entrepôt
|
||||
BatchStockMouvementAddInGlobal=Batch stock move into global stock (product doesn't use batch anymore)
|
||||
InventoryCodeShort=Code Inv./Mouv.
|
||||
NoPendingReceptionOnSupplierOrder=Pas de réception en attente consécutive à des commandes fournisseurs
|
||||
ThisSerialAlreadyExistWithDifferentDate=Ce lot/numéro de série (<strong>%s</strong>) existe déjà mais avec des dates de consommation ou péremption différente (trouvé <strong>%s</strong> mais vous avez entré <strong>%s</strong>).
|
||||
|
|
|
|||
|
|
@ -1944,7 +1944,45 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
|
|||
if ($object->isProduct() || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
|
||||
print '<tr><td>'.$langs->trans("ManageLotSerial").'</td><td>';
|
||||
$statutarray = array('0' => $langs->trans("ProductStatusNotOnBatch"), '1' => $langs->trans("ProductStatusOnBatch"), '2' => $langs->trans("ProductStatusOnSerial"));
|
||||
print $form->selectarray('status_batch', $statutarray, (GETPOSTISSET('status_batch') ? GETPOST('status_batch') : $object->status_batch));
|
||||
|
||||
print $form->selectarray('status_batch', $statutarray, GETPOSTISSET('status_batch') ? GETPOST('status_batch') : $object->status_batch);
|
||||
|
||||
print '<span id="statusBatchWarning" class="warning" style="display: none;">';
|
||||
print img_warning().' '.$langs->trans("WarningConvertFromBatchToSerial").'</span>';
|
||||
|
||||
print '<span id="statusBatchMouvToGlobal" class="warning" style="display: none;">';
|
||||
print img_warning().' '.$langs->trans("WarningTransferBatchStockMouvToGlobal").'</span>';
|
||||
|
||||
if ($object->status_batch) {
|
||||
// Display message to make user know that all batch will be move into global stock
|
||||
print '<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
console.log($("#statusBatchWarning"))
|
||||
$("#status_batch").on("change", function() {
|
||||
if ($("#status_batch")[0].value == 0){
|
||||
$("#statusBatchMouvToGlobal").show()
|
||||
} else {
|
||||
$("#statusBatchMouvToGlobal").hide()
|
||||
}
|
||||
})
|
||||
})</script>';
|
||||
|
||||
// Display message to explain that if the product currently have a quantity higher or equal to 2, switching to this choice means we will still have a product with different objects of the same batch (while we want a unique serial number)
|
||||
if ($object->status_batch == 1) {
|
||||
print '<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
console.log($("#statusBatchWarning"))
|
||||
$("#status_batch").on("change", function() {
|
||||
if ($("#status_batch")[0].value == 2){
|
||||
$("#statusBatchWarning").show()
|
||||
} else {
|
||||
$("#statusBatchWarning").hide()
|
||||
}
|
||||
})
|
||||
})</script>';
|
||||
}
|
||||
}
|
||||
|
||||
print '</td></tr>';
|
||||
if (!empty($object->status_batch) || !empty($conf->use_javascript_ajax)) {
|
||||
$langs->load("admin");
|
||||
|
|
|
|||
|
|
@ -1296,6 +1296,42 @@ class Product extends CommonObject
|
|||
}
|
||||
}
|
||||
|
||||
if (!$this->hasbatch() && $this->oldcopy->hasbatch()) {
|
||||
// Selection of all product stock mouvements that contains batchs
|
||||
$sql = 'SELECT pb.qty, pb.fk_entrepot, pb.batch FROM '.MAIN_DB_PREFIX.'product_batch as pb';
|
||||
$sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'product_stock as ps ON (ps.rowid = batch.fk_product_stock)';
|
||||
$sql.= ' WHERE ps.fk_product = '.(int) $this->id;
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
$inventorycode = dol_print_date(dol_now(), '%Y%m%d%H%M%S');
|
||||
|
||||
while ($obj = $this->db->fetch_object($resql)) {
|
||||
$value = $obj->qty;
|
||||
$fk_entrepot = $obj->fk_entrepot;
|
||||
$price = 0;
|
||||
$dlc = '';
|
||||
$dluo = '';
|
||||
$batch = $obj->batch;
|
||||
|
||||
// To know how to revert stockMouvement (add or remove)
|
||||
$addOremove = $value > 0 ? 1 : 0; // 1 if remove, 0 if add
|
||||
$label = $langs->trans('BatchStockMouvementAddInGlobal');
|
||||
$res = $this->correct_stock_batch($user, $fk_entrepot, abs($value), $addOremove, $label, $price, $dlc, $dluo, $batch, $inventorycode, '', null, 0, null, true);
|
||||
|
||||
if ($res > 0) {
|
||||
$label = $langs->trans('BatchStockMouvementAddInGlobal');
|
||||
$res = $this->correct_stock($user, $fk_entrepot, abs($value), (int) empty($addOremove), $label, $price, $inventorycode, '', null, 0);
|
||||
if ($res < 0) {
|
||||
$error++;
|
||||
}
|
||||
} else {
|
||||
$error++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Actions on extra fields
|
||||
if (!$error) {
|
||||
$result = $this->insertExtraFields();
|
||||
|
|
@ -5535,9 +5571,10 @@ class Product extends CommonObject
|
|||
* @param int $origin_id Origin id of element
|
||||
* @param int $disablestockchangeforsubproduct Disable stock change for sub-products of kit (usefull only if product is a subproduct)
|
||||
* @param Extrafields $extrafields Array of extrafields
|
||||
* @param boolean $force_update_batch Force update batch
|
||||
* @return int <0 if KO, >0 if OK
|
||||
*/
|
||||
public function correct_stock_batch($user, $id_entrepot, $nbpiece, $movement, $label = '', $price = 0, $dlc = '', $dluo = '', $lot = '', $inventorycode = '', $origin_element = '', $origin_id = null, $disablestockchangeforsubproduct = 0, $extrafields = null)
|
||||
public function correct_stock_batch($user, $id_entrepot, $nbpiece, $movement, $label = '', $price = 0, $dlc = '', $dluo = '', $lot = '', $inventorycode = '', $origin_element = '', $origin_id = null, $disablestockchangeforsubproduct = 0, $extrafields = null, $force_update_batch = false)
|
||||
{
|
||||
// phpcs:enable
|
||||
if ($id_entrepot) {
|
||||
|
|
@ -5557,7 +5594,7 @@ class Product extends CommonObject
|
|||
|
||||
$movementstock = new MouvementStock($this->db);
|
||||
$movementstock->setOrigin($origin_element, $origin_id); // Set ->origin_type and ->fk_origin
|
||||
$result = $movementstock->_create($user, $this->id, $id_entrepot, $op[$movement], $movement, $price, $label, $inventorycode, '', $dlc, $dluo, $lot, false, 0, $disablestockchangeforsubproduct);
|
||||
$result = $movementstock->_create($user, $this->id, $id_entrepot, $op[$movement], $movement, $price, $label, $inventorycode, '', $dlc, $dluo, $lot, false, 0, $disablestockchangeforsubproduct, 0, $force_update_batch);
|
||||
|
||||
if ($result >= 0) {
|
||||
if ($extrafields) {
|
||||
|
|
|
|||
|
|
@ -175,9 +175,10 @@ class MouvementStock extends CommonObject
|
|||
* @param int $id_product_batch Id product_batch (when skip_batch is false and we already know which record of product_batch to use)
|
||||
* @param int $disablestockchangeforsubproduct Disable stock change for sub-products of kit (usefull only if product is a subproduct)
|
||||
* @param int $donotcleanemptylines Do not clean lines in stock table with qty=0 (because we want to have this done by the caller)
|
||||
* @param boolean $force_update_batch Allows to add batch stock movement even if $product doesn't use batch anymore
|
||||
* @return int <0 if KO, 0 if fk_product is null or product id does not exists, >0 if OK
|
||||
*/
|
||||
public function _create($user, $fk_product, $entrepot_id, $qty, $type, $price = 0, $label = '', $inventorycode = '', $datem = '', $eatby = '', $sellby = '', $batch = '', $skip_batch = false, $id_product_batch = 0, $disablestockchangeforsubproduct = 0, $donotcleanemptylines = 0)
|
||||
public function _create($user, $fk_product, $entrepot_id, $qty, $type, $price = 0, $label = '', $inventorycode = '', $datem = '', $eatby = '', $sellby = '', $batch = '', $skip_batch = false, $id_product_batch = 0, $disablestockchangeforsubproduct = 0, $donotcleanemptylines = 0, $force_update_batch = false)
|
||||
{
|
||||
// phpcs:enable
|
||||
global $conf, $langs;
|
||||
|
|
@ -559,7 +560,7 @@ class MouvementStock extends CommonObject
|
|||
}
|
||||
|
||||
// Update detail of stock for the lot.
|
||||
if (!$error && isModEnabled('productbatch') && $product->hasbatch() && !$skip_batch) {
|
||||
if (!$error && isModEnabled('productbatch') && (($product->hasbatch() && !$skip_batch) || $force_update_batch)) {
|
||||
if ($id_product_batch > 0) {
|
||||
$result = $this->createBatch($id_product_batch, $qty);
|
||||
if ($result == -2 && $fk_product_stock > 0) { // The entry for this product batch does not exists anymore, bu we already have a llx_product_stock, so we recreate the batch entry in product_batch
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user