diff --git a/htdocs/admin/stock.php b/htdocs/admin/stock.php index 019c5745efb..e258011de76 100644 --- a/htdocs/admin/stock.php +++ b/htdocs/admin/stock.php @@ -323,63 +323,73 @@ $found++; print ''; +print '
'; +print ''; +print ''; +print " \n"; +print " \n"; +print ''."\n"; + +$var=!$var; +print ""; +print ''; +print '\n"; +print "\n"; + // Option to force stock to be enough before adding a line into document -if ($conf->invoice->enabled || $conf->order->enabled || $conf->expedition->enabled) -{ - print '
'; - print '
".$langs->trans("RuleForStockAvailability")." 
'.$langs->trans("WarehouseAllowNegativeTransfer").''; +print "
"; +print ''; +print ""; +print $form->selectyesno("STOCK_ALLOW_NEGATIVE_TRANSFER",$conf->global->STOCK_ALLOW_NEGATIVE_TRANSFER,1); +print ''; +print '
'; +print "
'; - print ''; - print " \n"; - print " \n"; - print ''."\n"; - - if($conf->invoice->enabled) { - $var = !$var; - print ""; - print ''; - print '\n"; - print "\n"; - } - - if($conf->order->enabled) { - $var = !$var; - print ""; - print ''; - print '\n"; - print "\n"; - } - - if($conf->expedition->enabled) { - $var = !$var; - print ""; - print ''; - print '\n"; - print "\n"; - } - print '
".$langs->trans("RuleForStockAvailability")." 
'.$langs->trans("StockMustBeEnoughForInvoice").''; - print "
"; - print ''; - print ""; - print $form->selectyesno("STOCK_MUST_BE_ENOUGH_FOR_INVOICE",$conf->global->STOCK_MUST_BE_ENOUGH_FOR_INVOICE,1); - print ''; - print '
'; - print "
'.$langs->trans("StockMustBeEnoughForOrder").''; - print "
"; - print ''; - print ""; - print $form->selectyesno("STOCK_MUST_BE_ENOUGH_FOR_ORDER",$conf->global->STOCK_MUST_BE_ENOUGH_FOR_ORDER,1); - print ''; - print '
'; - print "
'.$langs->trans("StockMustBeEnoughForShipment").''; - print "
"; - print ''; - print ""; - print $form->selectyesno("STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT",$conf->global->STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT,1); - print ''; - print '
'; - print "
'; +if($conf->invoice->enabled) { + $var = !$var; + print ""; + print ''.$langs->trans("StockMustBeEnoughForInvoice").''; + print ''; + print "
"; + print ''; + print ""; + print $form->selectyesno("STOCK_MUST_BE_ENOUGH_FOR_INVOICE",$conf->global->STOCK_MUST_BE_ENOUGH_FOR_INVOICE,1); + print ''; + print '
'; + print "\n"; + print "\n"; } +if($conf->order->enabled) { + $var = !$var; + print ""; + print ''.$langs->trans("StockMustBeEnoughForOrder").''; + print ''; + print "
"; + print ''; + print ""; + print $form->selectyesno("STOCK_MUST_BE_ENOUGH_FOR_ORDER",$conf->global->STOCK_MUST_BE_ENOUGH_FOR_ORDER,1); + print ''; + print '
'; + print "\n"; + print "\n"; +} + +if($conf->expedition->enabled) { + $var = !$var; + print ""; + print ''.$langs->trans("StockMustBeEnoughForShipment").''; + print ''; + print "
"; + print ''; + print ""; + print $form->selectyesno("STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT",$conf->global->STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT,1); + print ''; + print '
'; + print "\n"; + print "\n"; +} +print ''; + $virtualdiffersfromphysical=0; if (! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) || ! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) @@ -432,21 +442,6 @@ print ''; print "\n"; print "\n"; -$var=!$var; - -print ""; -print ''.$langs->trans("WarehouseAllowNegativeTransfer").''; - -print ''; -print "
"; -print ''; -print ""; -print $form->selectyesno("STOCK_ALLOW_NEGATIVE_TRANSFER",$conf->global->STOCK_ALLOW_NEGATIVE_TRANSFER,1); -print ''; -print '
'; -print "\n"; -print "\n"; - print '
'; /* I keep the option/feature, but hidden to end users for the moment. If feature is used by module, no need to have users see it. diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index c032e72e073..9d2d6bf947d 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -114,13 +114,13 @@ RecordMovement=Record transfert ReceivingForSameOrder=Receipts for this order StockMovementRecorded=Stock movements recorded RuleForStockAvailability=Rules on stock requirements -StockMustBeEnoughForInvoice=Stock level must be enough to add product/service to invoice -StockMustBeEnoughForOrder=Stock level must be enough to add product/service to order -StockMustBeEnoughForShipment= Stock level must be enough to add product/service to shipment +StockMustBeEnoughForInvoice=Stock level must be enough to add product/service to invoice (even if real stock change occurs later on another event) +StockMustBeEnoughForOrder=Stock level must be enough to add product/service to order (even if stock change occurs later on another event) +StockMustBeEnoughForShipment= Stock level must be enough to add product/service to shipment (even if stock change occurs later on another event) MovementLabel=Label of movement InventoryCode=Movement or inventory code IsInPackage=Contained into package -WarehouseAllowNegativeTransfer=Allow transfer even without stock +WarehouseAllowNegativeTransfer=Stock can be negative qtyToTranferIsNotEnough=You don't have enough stock from your source warehouse ShowWarehouse=Show warehouse MovementCorrectStock=Stock correction for product %s diff --git a/htdocs/product/class/productbatch.class.php b/htdocs/product/class/productbatch.class.php index ed03c3e729e..5ab70506693 100644 --- a/htdocs/product/class/productbatch.class.php +++ b/htdocs/product/class/productbatch.class.php @@ -494,11 +494,13 @@ class Productbatch extends CommonObject if ($fk_product > 0) { $sql.= ", pl.eatby as eatby, pl.sellby as sellby"; + // TODO May add extrafields to ? } $sql.= " FROM ".MAIN_DB_PREFIX."product_batch as t"; if ($fk_product > 0) { $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_lot as pl ON pl.fk_product = ".$fk_product." AND pl.batch = t.batch"; + // TODO May add extrafields to ? } $sql.= " WHERE fk_product_stock=".$fk_product_stock; if ($with_qty) $sql.= " AND t.qty <> 0"; @@ -523,7 +525,7 @@ class Productbatch extends CommonObject $tmp->qty = $obj->qty; $tmp->import_key = $obj->import_key; - array_push($ret,$tmp); + $ret[$tmp->batch] = $tmp; // $ret is for a $fk_product_stock and unique key is on $fk_product_stock+batch $i++; } $db->free($resql); diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 2a74f885c80..0d42abace37 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -240,31 +240,45 @@ class MouvementStock extends CommonObject } } - // TODO Check qty is ok for stock move. - if (! empty($conf->productbatch->enabled) && $product->hasbatch() && ! $skip_batch) - { - - } - else - { - - } - - if (empty($conf->global->STOCK_ALLOW_NEGATIVE_TRANSFER) && in_array($type, array(1, 2))) - { - if (empty($product->stock_warehouse[$entrepot_id]->real) || $product->stock_warehouse[$entrepot_id]->real < abs($qty)) - { - $this->error = $langs->trans('qtyToTranferIsNotEnough'); - $this->errors[] = $langs->trans('qtyToTranferIsNotEnough'); - $this->db->rollback(); - return -8; - } - } - // Define if we must make the stock change (If product type is a service or if stock is used also for services) $movestock=0; if ($product->type != Product::TYPE_SERVICE || ! empty($conf->global->STOCK_SUPPORTS_SERVICES)) $movestock=1; + // Check if stock is enough when qty is < 0 + // Note that qty should be > 0 with type 0 or 3, < 0 with type 1 or 2. + if ($qty < 0 && empty($conf->global->STOCK_ALLOW_NEGATIVE_TRANSFER)) + { + if (! empty($conf->productbatch->enabled) && $product->hasbatch() && ! $skip_batch) + { + $foundforbatch=0; + $qtyisnotenough=0; + foreach($product->stock_warehouse[$entrepot_id]->detail_batch as $batchcursor => $prodbatch) + { + if ($batch != $batchcursor) continue; + $foundforbatch=1; + if ($prodbatch->qty < abs($qty)) $qtyisnotenough=1; + break; + } + if (! $foundforbatch || $qtyisnotenough) + { + $this->error = $langs->trans('qtyToTranferLotIsNotEnough'); + $this->errors[] = $langs->trans('qtyToTranferLotIsNotEnough'); + $this->db->rollback(); + return -8; + } + } + else + { + if (empty($product->stock_warehouse[$entrepot_id]->real) || $product->stock_warehouse[$entrepot_id]->real < abs($qty)) + { + $this->error = $langs->trans('qtyToTranferIsNotEnough'); + $this->errors[] = $langs->trans('qtyToTranferIsNotEnough'); + $this->db->rollback(); + return -8; + } + } + } + if ($movestock && $entrepot_id > 0) // Change stock for current product, change for subproduct is done after { if(!empty($this->origin)) { // This is set by caller for tracking reason