diff --git a/htdocs/install/mysql/migration/14.0.0-15.0.0.sql b/htdocs/install/mysql/migration/14.0.0-15.0.0.sql
index 5ec019cf253..263e94e4575 100644
--- a/htdocs/install/mysql/migration/14.0.0-15.0.0.sql
+++ b/htdocs/install/mysql/migration/14.0.0-15.0.0.sql
@@ -476,3 +476,6 @@ ALTER TABLE llx_propal ADD COLUMN online_sign_name varchar(64);
ALTER TABLE llx_entrepot ADD COLUMN warehouse_usage integer DEFAULT 1;
ALTER TABLE llx_session MODIFY COLUMN user_agent VARCHAR(255) NULL;
+
+ALTER TABLE llx_inventorydet ADD COLUMN fk_movement integer NULL;
+
diff --git a/htdocs/install/mysql/tables/llx_inventory.sql b/htdocs/install/mysql/tables/llx_inventory.sql
index aa35ebb0c42..c25ccb9767b 100644
--- a/htdocs/install/mysql/tables/llx_inventory.sql
+++ b/htdocs/install/mysql/tables/llx_inventory.sql
@@ -21,7 +21,7 @@ CREATE TABLE llx_inventory
(
rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY,
entity integer DEFAULT 0,
- ref varchar(48),
+ ref varchar(48), -- We will also use this code as inventory code
date_creation datetime DEFAULT NULL,
tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
fk_user_creat integer, -- user making creation
diff --git a/htdocs/install/mysql/tables/llx_inventorydet.sql b/htdocs/install/mysql/tables/llx_inventorydet.sql
index ce23fe0f749..8b75f68460d 100644
--- a/htdocs/install/mysql/tables/llx_inventorydet.sql
+++ b/htdocs/install/mysql/tables/llx_inventorydet.sql
@@ -25,9 +25,10 @@ CREATE TABLE llx_inventorydet
fk_inventory integer DEFAULT 0,
fk_warehouse integer DEFAULT 0,
fk_product integer DEFAULT 0,
- batch varchar(128) DEFAULT NULL, -- Lot or serial number
- qty_stock double DEFAULT NULL, -- The targeted value. can be filled during draft edition
- qty_view double DEFAULT NULL, -- must be filled once regulation is done
- qty_regulated double DEFAULT NULL -- must be filled once regulation is done
+ batch varchar(128) DEFAULT NULL, -- Lot or serial number
+ qty_stock double DEFAULT NULL, -- Value or real stock we have, when we start the inventory (may be updated during intermediary steps).
+ qty_view double DEFAULT NULL, -- Quantity found during inventory. It is the targeted value, filled during edition of inventory.
+ qty_regulated double DEFAULT NULL, -- Never used. Deprecated because we already have the fk_movement now.
+ fk_movement integer NULL -- can contain the id of stock movement we recorded to make the inventory regulation of this line
)
ENGINE=innodb;
diff --git a/htdocs/product/inventory/card.php b/htdocs/product/inventory/card.php
index 1f036e1fa3c..49ce49958d5 100644
--- a/htdocs/product/inventory/card.php
+++ b/htdocs/product/inventory/card.php
@@ -207,6 +207,8 @@ if ($action == 'create') {
// Other attributes
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php';
+ //print '
'.$langs->trans("InventoryCode").'
INV'.$object->id.'
';
+
print ''."\n";
print dol_get_fiche_end();
diff --git a/htdocs/product/inventory/inventory.php b/htdocs/product/inventory/inventory.php
index 5346e37aec4..c6abe95bc80 100644
--- a/htdocs/product/inventory/inventory.php
+++ b/htdocs/product/inventory/inventory.php
@@ -103,122 +103,6 @@ if ($cancel) {
$action = '';
}
-if ($action == 'cancel_record' && $permissiontoadd) {
- $object->setCanceled($user);
-}
-
-if ($action == 'update' && !empty($user->rights->stock->mouvement->creer)) {
- $stockmovment = new MouvementStock($db);
- $stockmovment->setOrigin($object->element, $object->id);
-
- $db->begin();
-
- $sql = 'SELECT id.rowid, id.datec as date_creation, id.tms as date_modification, id.fk_inventory, id.fk_warehouse,';
- $sql .= ' id.fk_product, id.batch, id.qty_stock, id.qty_view, id.qty_regulated';
- $sql .= ' FROM '.MAIN_DB_PREFIX.'inventorydet as id';
- $sql .= ' WHERE id.fk_inventory = '.((int) $object->id);
-
- $resql = $db->query($sql);
- if ($resql) {
- $num = $db->num_rows($resql);
- $i = 0;
- $totalarray = array();
- while ($i < $num) {
- $line = $db->fetch_object($resql);
- $qty_stock = $line->qty_stock;
- $qty_view = $line->qty_view; // The quantity viewed by inventorier, the qty we target
-
- if (!is_null($qty_view)) {
- $stock_movement_qty = price2num($qty_view - $qty_stock, 'MS');
- if ($stock_movement_qty != 0) {
- if ($stock_movement_qty < 0) {
- $movement_type = 1;
- } else {
- $movement_type = 0;
- }
-
- $datemovement = '';
-
- $idstockmove = $stockmovment->_create($user, $line->fk_product, $line->fk_warehouse, $stock_movement_qty, $movement_type, 0, $langs->trans('LabelOfInventoryMovemement', $object->id), 'INV'.$object->id, $datemovement, '', '', $line->batch);
- if ($idstockmove < 0) {
- $error++;
- setEventMessages($stockmovment->error, $stockmovment->errors, 'errors');
- break;
- }
- }
- }
- $i++;
- }
-
- if (!$error) {
- $object->setRecorded($user);
- }
- } else {
- setEventMessages($db->lasterror, null, 'errors');
- $error++;
- }
-
- if (! $error) {
- $db->commit();
- } else {
- $db->rollback();
- }
-}
-
-if ($action =='updateinventorylines' && $permissiontoadd) {
- $sql = 'SELECT id.rowid, id.datec as date_creation, id.tms as date_modification, id.fk_inventory, id.fk_warehouse,';
- $sql .= ' id.fk_product, id.batch, id.qty_stock, id.qty_view, id.qty_regulated';
- $sql .= ' FROM '.MAIN_DB_PREFIX.'inventorydet as id';
- $sql .= ' WHERE id.fk_inventory = '.((int) $object->id);
-
- $db->begin();
-
- $resql = $db->query($sql);
- if ($resql) {
- $num = $db->num_rows($resql);
- $i = 0;
- $totalarray = array();
- $inventoryline = new InventoryLine($db);
-
- while ($i < $num) {
- $line = $db->fetch_object($resql);
- $lineid = $line->rowid;
-
- if (GETPOST("id_".$lineid, 'alpha') != '') { // If a value was set ('0' or something else)
- $qtytoupdate = price2num(GETPOST("id_".$lineid, 'alpha'), 'MS');
- $result = $inventoryline->fetch($lineid);
- if ($qtytoupdate < 0) {
- $result = -1;
- setEventMessages($langs->trans("FieldCannotBeNegative", $langs->transnoentitiesnoconv("RealQty")), null, 'errors');
- }
- if ($result > 0) {
- $inventoryline->qty_view = $qtytoupdate;
- $resultupdate = $inventoryline->update($user);
- }
- } else {
- // Delete record
- $result = $inventoryline->fetch($lineid);
- if ($result > 0) {
- $inventoryline->qty_view = null;
- $resultupdate = $inventoryline->update($user);
- }
- }
-
- if ($result < 0 || $resultupdate < 0) {
- $error++;
- }
-
- $i++;
- }
- }
-
- if (!$error) {
- $db->commit();
- } else {
- $db->rollback();
- }
-}
-
$parameters = array();
$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook < 0) {
@@ -228,6 +112,138 @@ if ($reshook < 0) {
if (empty($reshook)) {
$error = 0;
+ if ($action == 'cancel_record' && $permissiontoadd) {
+ $object->setCanceled($user);
+ }
+
+ // Close inventory by recording the stock movements
+ if ($action == 'update' && !empty($user->rights->stock->mouvement->creer)) {
+ $stockmovment = new MouvementStock($db);
+ $stockmovment->setOrigin($object->element, $object->id);
+
+ $db->begin();
+
+ $sql = 'SELECT id.rowid, id.datec as date_creation, id.tms as date_modification, id.fk_inventory, id.fk_warehouse,';
+ $sql .= ' id.fk_product, id.batch, id.qty_stock, id.qty_view, id.qty_regulated';
+ $sql .= ' FROM '.MAIN_DB_PREFIX.'inventorydet as id';
+ $sql .= ' WHERE id.fk_inventory = '.((int) $object->id);
+
+ $resql = $db->query($sql);
+ if ($resql) {
+ $num = $db->num_rows($resql);
+ $i = 0;
+ $totalarray = array();
+ while ($i < $num) {
+ $line = $db->fetch_object($resql);
+
+ $qty_stock = $line->qty_stock;
+ $qty_view = $line->qty_view; // The quantity viewed by inventorier, the qty we target
+
+ if (!is_null($qty_view)) {
+ $stock_movement_qty = price2num($qty_view - $qty_stock, 'MS');
+ if ($stock_movement_qty != 0) {
+ if ($stock_movement_qty < 0) {
+ $movement_type = 1;
+ } else {
+ $movement_type = 0;
+ }
+
+ $datemovement = '';
+ //$inventorycode = 'INV'.$object->id;
+ $inventorycode = 'INV-'.$object->ref;
+
+ $idstockmove = $stockmovment->_create($user, $line->fk_product, $line->fk_warehouse, $stock_movement_qty, $movement_type, 0, $langs->trans('LabelOfInventoryMovemement', $object->id), $inventorycode, $datemovement, '', '', $line->batch);
+ if ($idstockmove < 0) {
+ $error++;
+ setEventMessages($stockmovment->error, $stockmovment->errors, 'errors');
+ break;
+ }
+
+ // Update line with id of stock movement
+ $sqlupdate = 'UPDATE '.MAIN_DB_PREFIX.'inventorydet SET fk_movement = '.((int) $idstockmove).' WHERE rowid = '.$line->rowid;
+ $resqlupdate = $db->query($sqlupdate);
+ if (! $resqlupdate) {
+ $error++;
+ setEventMessages($db->lasterror(), null, 'errors');
+ break;
+ }
+ }
+ }
+ $i++;
+ }
+
+ if (!$error) {
+ $object->setRecorded($user);
+ }
+ } else {
+ setEventMessages($db->lasterror, null, 'errors');
+ $error++;
+ }
+
+ if (! $error) {
+ $db->commit();
+ } else {
+ $db->rollback();
+ }
+ }
+
+ // Save quantity found during inventory
+ if ($action =='updateinventorylines' && $permissiontoadd) {
+ $sql = 'SELECT id.rowid, id.datec as date_creation, id.tms as date_modification, id.fk_inventory, id.fk_warehouse,';
+ $sql .= ' id.fk_product, id.batch, id.qty_stock, id.qty_view, id.qty_regulated';
+ $sql .= ' FROM '.MAIN_DB_PREFIX.'inventorydet as id';
+ $sql .= ' WHERE id.fk_inventory = '.((int) $object->id);
+
+ $db->begin();
+
+ $resql = $db->query($sql);
+ if ($resql) {
+ $num = $db->num_rows($resql);
+ $i = 0;
+ $totalarray = array();
+ $inventoryline = new InventoryLine($db);
+
+ while ($i < $num) {
+ $line = $db->fetch_object($resql);
+ $lineid = $line->rowid;
+
+ if (GETPOST("id_".$lineid, 'alpha') != '') { // If a value was set ('0' or something else)
+ $qtytoupdate = price2num(GETPOST("id_".$lineid, 'alpha'), 'MS');
+ $result = $inventoryline->fetch($lineid);
+ if ($qtytoupdate < 0) {
+ $result = -1;
+ setEventMessages($langs->trans("FieldCannotBeNegative", $langs->transnoentitiesnoconv("RealQty")), null, 'errors');
+ }
+ if ($result > 0) {
+ $inventoryline->qty_stock = price2num(GETPOST('stock_qty_'.$lineid, 'alpha'), 'MS'); // The new value we want
+ $inventoryline->qty_view = $qtytoupdate; // The new value we want
+ $resultupdate = $inventoryline->update($user);
+ }
+ } else {
+ // Delete record
+ $result = $inventoryline->fetch($lineid);
+ if ($result > 0) {
+ $inventoryline->qty_view = null; // The new value we want
+ $resultupdate = $inventoryline->update($user);
+ }
+ }
+
+ if ($result < 0 || $resultupdate < 0) {
+ $error++;
+ }
+
+ $i++;
+ }
+ }
+
+ if (!$error) {
+ $db->commit();
+ } else {
+ $db->rollback();
+ }
+ }
+
+
$backurlforlist = DOL_URL_ROOT.'/product/inventory/list.php';
$backtopage = DOL_URL_ROOT.'/product/inventory/inventory.php?id='.$object->id;
@@ -443,6 +459,8 @@ if ($object->id > 0) {
// Other attributes. Fields from hook formObjectOptions and Extrafields.
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
+ //print '
';
- print '';
}
+ print '';
// Line to add a new line in inventory
- if ($object->status == $object::STATUS_VALIDATED) {
+ if ($object->status == $object::STATUS_DRAFT || $object->status == $object::STATUS_VALIDATED) {
print '