From 7a0577ccfc292f8cc2a39b9575a8a5849cbb9896 Mon Sep 17 00:00:00 2001 From: gauthier Date: Fri, 16 Sep 2016 17:09:38 +0200 Subject: [PATCH 01/10] NEW : add limit stock product by warehouse --- htdocs/admin/stock.php | 18 + .../tables/llx_product_stock_entrepot.sql | 31 + htdocs/langs/en_US/stocks.lang | 1 + .../class/productstockentrepot.class.php | 615 ++++++++++++++++++ htdocs/product/stock/product.php | 29 + 5 files changed, 694 insertions(+) create mode 100644 htdocs/install/mysql/tables/llx_product_stock_entrepot.sql create mode 100644 htdocs/product/stock/class/productstockentrepot.class.php diff --git a/htdocs/admin/stock.php b/htdocs/admin/stock.php index 6faaff1e006..4f556f417be 100644 --- a/htdocs/admin/stock.php +++ b/htdocs/admin/stock.php @@ -49,6 +49,9 @@ if($action) { $res = dolibarr_set_const($db, "STOCK_USERSTOCK_AUTOCREATE", GETPOST('STOCK_USERSTOCK_AUTOCREATE','alpha'),'chaine',0,'',$conf->entity); } + if ($action == 'STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE') { + $res = dolibarr_set_const($db, "STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE", GETPOST('STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE','alpha'),'chaine',0,'',$conf->entity); + } if ($action == 'STOCK_ALLOW_NEGATIVE_TRANSFER') { $res = dolibarr_set_const($db, "STOCK_ALLOW_NEGATIVE_TRANSFER", GETPOST('STOCK_ALLOW_NEGATIVE_TRANSFER','alpha'),'chaine',0,'',$conf->entity); @@ -473,6 +476,21 @@ print ''; print "\n"; print "\n"; +$var=!$var; + +print ""; +print ''.$langs->trans("AllowAddLimitStockByWarehouse").''; + +print ''; +print "
"; +print ''; +print ""; +print $form->selectyesno("STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE",$conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE,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/install/mysql/tables/llx_product_stock_entrepot.sql b/htdocs/install/mysql/tables/llx_product_stock_entrepot.sql new file mode 100644 index 00000000000..b0fcedc8ab6 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_product_stock_entrepot.sql @@ -0,0 +1,31 @@ +-- ============================================================================ +-- Copyright (C) 2003 Rodolphe Quiedeville +-- Copyright (C) 2009-2016 Laurent Destailleur +-- Copyright (C) 2012 Juanjo Menent +-- +-- 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 +-- along with this program. If not, see . +-- +-- ============================================================================ + +create table llx_product_stock_entrepot +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + tms timestamp, + fk_product integer NOT NULL, + fk_entrepot integer NOT NULL, + seuil_stock_alerte int(11) DEFAULT '0', + desiredstock int(11) DEFAULT '0', + import_key varchar(14) -- Import key +)ENGINE=innodb; + diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index baf8fcde0db..53dc0c087e5 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -45,6 +45,7 @@ PMPValue=Weighted average price PMPValueShort=WAP EnhancedValueOfWarehouses=Warehouses value UserWarehouseAutoCreate=Create a warehouse automatically when creating a user +AllowAddLimitStockByWarehouse=Allow to add limit and desired stock by product and warehouse IndependantSubProductStock=Product stock and subproduct stock are independant QtyDispatched=Quantity dispatched QtyDispatchedShort=Qty dispatched diff --git a/htdocs/product/stock/class/productstockentrepot.class.php b/htdocs/product/stock/class/productstockentrepot.class.php new file mode 100644 index 00000000000..764baee1dd3 --- /dev/null +++ b/htdocs/product/stock/class/productstockentrepot.class.php @@ -0,0 +1,615 @@ + + * Copyright (C) 2014-2016 Juanjo Menent + * Copyright (C) 2015 Florian Henry + * Copyright (C) 2015 Raphaƫl Doursenaud + * Copyright (C) ---Put here your own copyright and developer email--- + * + * 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 + * along with this program. If not, see . + */ + +/** + * \file ProductEntrepot/ProductStockEntrepot.class.php + * \ingroup ProductEntrepot + * \brief This file is an example for a CRUD class file (Create/Read/Update/Delete) + * Put some comments here + */ + +// Put here all includes required by your class file +require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; + +/** + * Class ProductStockEntrepot + * + * Put here description of your class + * + * @see CommonObject + */ +class ProductStockEntrepot extends CommonObject +{ + /** + * @var string Id to identify managed objects + */ + public $element = 'ProductStockEntrepot'; + /** + * @var string Name of table without prefix where object is stored + */ + public $table_element = 'product_stock_entrepot'; + + /** + */ + + public $tms = ''; + public $fk_product; + public $fk_entrepot; + public $seuil_stock_alerte; + public $desiredstock; + public $import_key; + + /** + */ + + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + $this->db = $db; + } + + /** + * Create object into database + * + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * + * @return int <0 if KO, Id of created object if OK + */ + public function create(User $user, $notrigger = false) + { + dol_syslog(__METHOD__, LOG_DEBUG); + + $error = 0; + + // Clean parameters + + if (isset($this->fk_product)) { + $this->fk_product = trim($this->fk_product); + } + if (isset($this->fk_entrepot)) { + $this->fk_entrepot = trim($this->fk_entrepot); + } + if (isset($this->seuil_stock_alerte)) { + $this->seuil_stock_alerte = trim($this->seuil_stock_alerte); + } + if (isset($this->desiredstock)) { + $this->desiredstock = trim($this->desiredstock); + } + if (isset($this->import_key)) { + $this->import_key = trim($this->import_key); + } + + + + // Check parameters + // Put here code to add control on parameters values + + // Insert request + $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . $this->table_element . '('; + + $sql.= 'fk_product,'; + $sql.= 'fk_entrepot,'; + $sql.= 'seuil_stock_alerte'; + $sql.= 'desiredstock'; + $sql.= 'import_key'; + + + $sql .= ') VALUES ('; + + $sql .= ' '.(! isset($this->fk_product)?'NULL':$this->fk_product).','; + $sql .= ' '.(! isset($this->fk_entrepot)?'NULL':$this->fk_entrepot).','; + $sql .= ' '.(! isset($this->seuil_stock_alerte)?'0':$this->seuil_stock_alerte).','; + $sql .= ' '.(! isset($this->desiredstock)?'0':$this->desiredstock).','; + $sql .= ' '.(! isset($this->import_key)?'NULL':"'".$this->db->escape($this->import_key)."'"); + + + $sql .= ')'; + + $this->db->begin(); + + $resql = $this->db->query($sql); + if (!$resql) { + $error ++; + $this->errors[] = 'Error ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); + } + + if (!$error) { + $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . $this->table_element); + + if (!$notrigger) { + // Uncomment this and change MYOBJECT to your own tag if you + // want this action to call a trigger. + + //// Call triggers + //$result=$this->call_trigger('MYOBJECT_CREATE',$user); + //if ($result < 0) $error++; + //// End call triggers + } + } + + // Commit or rollback + if ($error) { + $this->db->rollback(); + + return - 1 * $error; + } else { + $this->db->commit(); + + return $this->id; + } + } + + /** + * Load object in memory from the database + * + * @param int $id Id object + * @param string $ref Ref + * + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetch($id, $ref = null) + { + dol_syslog(__METHOD__, LOG_DEBUG); + + $sql = 'SELECT'; + $sql .= ' t.rowid,'; + + $sql .= " t.tms,"; + $sql .= " t.fk_product,"; + $sql .= " t.fk_entrepot,"; + $sql .= " t.seuil_stock_alerte,"; + $sql .= " t.desiredstock,"; + $sql .= " t.import_key"; + + + $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t'; + if (null !== $ref) { + $sql .= ' WHERE t.ref = ' . '\'' . $ref . '\''; + } else { + $sql .= ' WHERE t.rowid = ' . $id; + } + + $resql = $this->db->query($sql); + if ($resql) { + $numrows = $this->db->num_rows($resql); + if ($numrows) { + $obj = $this->db->fetch_object($resql); + + $this->id = $obj->rowid; + + $this->tms = $this->db->jdate($obj->tms); + $this->fk_product = $obj->fk_product; + $this->fk_entrepot = $obj->fk_entrepot; + $this->seuil_stock_alerte = $obj->seuil_stock_alerte; + $this->desiredstock = $obj->desiredstock; + $this->import_key = $obj->import_key; + + + } + + // Retrieve all extrafields for invoice + // fetch optionals attributes and labels + require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; + $extrafields=new ExtraFields($this->db); + $extralabels=$extrafields->fetch_name_optionals_label($this->table_element,true); + $this->fetch_optionals($this->id,$extralabels); + + // $this->fetch_lines(); + + $this->db->free($resql); + + if ($numrows) { + return 1; + } else { + return 0; + } + } else { + $this->errors[] = 'Error ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); + + return - 1; + } + } + + /** + * Load object in memory from the database + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit offset limit + * @param int $offset offset limit + * @param array $filter filter array + * @param string $filtermode filter mode (AND or OR) + * + * @return int <0 if KO, >0 if OK + */ + public function fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, array $filter = array(), $filtermode='AND') + { + dol_syslog(__METHOD__, LOG_DEBUG); + + $sql = 'SELECT'; + $sql .= ' t.rowid,'; + + $sql .= " t.tms,"; + $sql .= " t.fk_product,"; + $sql .= " t.fk_entrepot,"; + $sql .= " t.seuil_stock_alerte,"; + $sql .= " t.desiredstock,"; + $sql .= " t.import_key"; + + + $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element. ' as t'; + + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + $sqlwhere [] = $key . ' LIKE \'%' . $this->db->escape($value) . '%\''; + } + } + if (count($sqlwhere) > 0) { + $sql .= ' WHERE ' . implode(' '.$filtermode.' ', $sqlwhere); + } + + if (!empty($sortfield)) { + $sql .= $this->db->order($sortfield,$sortorder); + } + if (!empty($limit)) { + $sql .= ' ' . $this->db->plimit($limit + 1, $offset); + } + $this->lines = array(); + + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + + while ($obj = $this->db->fetch_object($resql)) { + $line = new ProductStockEntrepotLine(); + + $line->id = $obj->rowid; + + $line->tms = $this->db->jdate($obj->tms); + $line->fk_product = $obj->fk_product; + $line->fk_entrepot = $obj->fk_entrepot; + $line->seuil_stock_alerte = $obj->seuil_stock_alerte; + $line->desiredstock = $obj->desiredstock; + $line->import_key = $obj->import_key; + + + + $this->lines[$line->id] = $line; + } + $this->db->free($resql); + + return $num; + } else { + $this->errors[] = 'Error ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); + + return - 1; + } + } + + /** + * Update object into database + * + * @param User $user User that modifies + * @param bool $notrigger false=launch triggers after, true=disable triggers + * + * @return int <0 if KO, >0 if OK + */ + public function update(User $user, $notrigger = false) + { + $error = 0; + + dol_syslog(__METHOD__, LOG_DEBUG); + + // Clean parameters + + if (isset($this->fk_product)) { + $this->fk_product = trim($this->fk_product); + } + if (isset($this->fk_entrepot)) { + $this->fk_entrepot = trim($this->fk_entrepot); + } + if (isset($this->seuil_stock_alerte)) { + $this->seuil_stock_alerte = trim($this->seuil_stock_alerte); + } + if (isset($this->desiredstock)) { + $this->desiredstock = trim($this->desiredstock); + } + if (isset($this->import_key)) { + $this->import_key = trim($this->import_key); + } + + + + // Check parameters + // Put here code to add a control on parameters values + + // Update request + $sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element . ' SET'; + + $sql .= ' tms = '.(dol_strlen($this->tms) != 0 ? "'".$this->db->idate($this->tms)."'" : "'".$this->db->idate(dol_now())."'").','; + $sql .= ' fk_product = '.(isset($this->fk_product)?$this->fk_product:"null").','; + $sql .= ' fk_entrepot = '.(isset($this->fk_entrepot)?$this->fk_entrepot:"null").','; + $sql .= ' seuil_stock_alerte = '.(isset($this->seuil_stock_alerte)?$this->seuil_stock_alerte:"null").','; + $sql .= ' desiredstock = '.(isset($this->desiredstock)?$this->desiredstock:"null").','; + $sql .= ' import_key = '.(isset($this->import_key)?"'".$this->db->escape($this->import_key)."'":"null"); + + + $sql .= ' WHERE rowid=' . $this->id; + + $this->db->begin(); + + $resql = $this->db->query($sql); + if (!$resql) { + $error ++; + $this->errors[] = 'Error ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); + } + + if (!$error && !$notrigger) { + // Uncomment this and change MYOBJECT to your own tag if you + // want this action calls a trigger. + + //// Call triggers + //$result=$this->call_trigger('MYOBJECT_MODIFY',$user); + //if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail} + //// End call triggers + } + + // Commit or rollback + if ($error) { + $this->db->rollback(); + + return - 1 * $error; + } else { + $this->db->commit(); + + return 1; + } + } + + /** + * Delete object in database + * + * @param User $user User that deletes + * @param bool $notrigger false=launch triggers after, true=disable triggers + * + * @return int <0 if KO, >0 if OK + */ + public function delete(User $user, $notrigger = false) + { + dol_syslog(__METHOD__, LOG_DEBUG); + + $error = 0; + + $this->db->begin(); + + if (!$error) { + if (!$notrigger) { + // Uncomment this and change MYOBJECT to your own tag if you + // want this action calls a trigger. + + //// Call triggers + //$result=$this->call_trigger('MYOBJECT_DELETE',$user); + //if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail} + //// End call triggers + } + } + + if (!$error) { + $sql = 'DELETE FROM ' . MAIN_DB_PREFIX . $this->table_element; + $sql .= ' WHERE rowid=' . $this->id; + + $resql = $this->db->query($sql); + if (!$resql) { + $error ++; + $this->errors[] = 'Error ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); + } + } + + // Commit or rollback + if ($error) { + $this->db->rollback(); + + return - 1 * $error; + } else { + $this->db->commit(); + + return 1; + } + } + + /** + * Load an object from its id and create a new one in database + * + * @param int $fromid Id of object to clone + * + * @return int New id of clone + */ + public function createFromClone($fromid) + { + dol_syslog(__METHOD__, LOG_DEBUG); + + global $user; + $error = 0; + $object = new ProductStockEntrepot($this->db); + + $this->db->begin(); + + // Load source object + $object->fetch($fromid); + // Reset object + $object->id = 0; + + // Clear fields + // ... + + // Create clone + $result = $object->create($user); + + // Other options + if ($result < 0) { + $error ++; + $this->errors = $object->errors; + dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); + } + + // End + if (!$error) { + $this->db->commit(); + + return $object->id; + } else { + $this->db->rollback(); + + return - 1; + } + } + + /** + * Return a link to the user card (with optionaly the picto) + * Use this->id,this->lastname, this->firstname + * + * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) + * @param string $option On what the link point to + * @param integer $notooltip 1=Disable tooltip + * @param int $maxlen Max length of visible user name + * @param string $morecss Add more css on link + * @return string String with URL + */ + function getNomUrl($withpicto=0, $option='', $notooltip=0, $maxlen=24, $morecss='') + { + global $langs, $conf, $db; + global $dolibarr_main_authentication, $dolibarr_main_demo; + global $menumanager; + + + $result = ''; + $companylink = ''; + + $label = '' . $langs->trans("MyModule") . ''; + $label.= '
'; + $label.= '' . $langs->trans('Ref') . ': ' . $this->ref; + + $link = 'ref . $linkend; + return $result; + } + + /** + * Retourne le libelle du status d'un user (actif, inactif) + * + * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto + * @return string Label of status + */ + function getLibStatut($mode=0) + { + return $this->LibStatut($this->status,$mode); + } + + /** + * Renvoi le libelle d'un status donne + * + * @param int $status Id status + * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto + * @return string Label of status + */ + function LibStatut($status,$mode=0) + { + global $langs; + + if ($mode == 0) + { + $prefix=''; + if ($status == 1) return $langs->trans('Enabled'); + if ($status == 0) return $langs->trans('Disabled'); + } + if ($mode == 1) + { + if ($status == 1) return $langs->trans('Enabled'); + if ($status == 0) return $langs->trans('Disabled'); + } + if ($mode == 2) + { + if ($status == 1) return img_picto($langs->trans('Enabled'),'statut4').' '.$langs->trans('Enabled'); + if ($status == 0) return img_picto($langs->trans('Disabled'),'statut5').' '.$langs->trans('Disabled'); + } + if ($mode == 3) + { + if ($status == 1) return img_picto($langs->trans('Enabled'),'statut4'); + if ($status == 0) return img_picto($langs->trans('Disabled'),'statut5'); + } + if ($mode == 4) + { + if ($status == 1) return img_picto($langs->trans('Enabled'),'statut4').' '.$langs->trans('Enabled'); + if ($status == 0) return img_picto($langs->trans('Disabled'),'statut5').' '.$langs->trans('Disabled'); + } + if ($mode == 5) + { + if ($status == 1) return $langs->trans('Enabled').' '.img_picto($langs->trans('Enabled'),'statut4'); + if ($status == 0) return $langs->trans('Disabled').' '.img_picto($langs->trans('Disabled'),'statut5'); + } + } + + + /** + * Initialise object with example values + * Id must be 0 if object instance is a specimen + * + * @return void + */ + public function initAsSpecimen() + { + $this->id = 0; + + $this->tms = ''; + $this->fk_product = ''; + $this->fk_entrepot = ''; + $this->seuil_stock_alerte = ''; + $this->desiredstock = ''; + $this->import_key = ''; + + + } + +} diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index 2411dde51e4..1f90c473248 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -69,6 +69,13 @@ $result=restrictedArea($user,'produit&stock',$id,'product&product','','',$fieldi if ($cancel) $action=''; +if($action == 'addlimitstockwarehouse') { + + //var_dump($_REQUEST);exit; + $action=''; + +} + // Set stock limit if ($action == 'setseuil_stock_alerte') { @@ -824,6 +831,28 @@ print ''; print ""; print ""; +if(!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) { + + print '

'; + print_titre('Indiquer une limite pour alerte et un stock optimal'); + //print '
'; + + print '
'; + print ''; + print ''; + print ''; + + print ''; + print ''; + print ''; + print ''; + print ''; + + print "
'.$formproduct->selectWarehouses().'
"; + + print '
'; + +} llxFooter(); From 0a9fd2dc7e89047586df735baf6a1d81354b8f18 Mon Sep 17 00:00:00 2001 From: Asier Bilbao Date: Sun, 18 Sep 2016 15:51:55 +0200 Subject: [PATCH 02/10] Fix Syntax error, unrecognized expression: input.remain] Fix ``` jquery.min.js?version=4.0.0:2 Uncaught Error: Syntax error, unrecognized expression: input.remain] ``` --- htdocs/compta/paiement.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/paiement.php b/htdocs/compta/paiement.php index c11b2c815bc..4b0039c0a21 100644 --- a/htdocs/compta/paiement.php +++ b/htdocs/compta/paiement.php @@ -394,7 +394,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie json["invoice_type"] = $("#invoice_type").val(); json["amountPayment"] = $("#amountpayment").attr("value"); json["amounts"] = _elemToJson(form.find("input.amount")); - json["remains"] = _elemToJson(form.find("input.remain]")); + json["remains"] = _elemToJson(form.find("input.remain")); if (imgId != null) { json["imgClicked"] = imgId; From a4d0eed50316b968ef2314aacc608bccd2a2ceb5 Mon Sep 17 00:00:00 2001 From: gauthier Date: Mon, 19 Sep 2016 17:33:29 +0200 Subject: [PATCH 03/10] NEW : Save product stock warehouse in database and display list --- htdocs/langs/en_US/stocks.lang | 3 + .../class/productstockentrepot.class.php | 103 +++++++----------- htdocs/product/stock/product.php | 70 +++++++++++- 3 files changed, 107 insertions(+), 69 deletions(-) diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index 53dc0c087e5..793c2889c7c 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -136,3 +136,6 @@ OpenInternal=Open for internal actions OpenShipping=Open for shippings OpenDispatch=Open for dispatch UseDispatchStatus=Use dispatch status (aprouve/refuse) +ProductStockWarehouseCreated=Stock limit for alert and desired optimal stock correctly created +ProductStockWarehouseUpdated=Stock limit for alert and desired optimal stock correctly updated +AddNewProductStockWarehouse=Set new limit for alert and desired optimal stock \ No newline at end of file diff --git a/htdocs/product/stock/class/productstockentrepot.class.php b/htdocs/product/stock/class/productstockentrepot.class.php index 764baee1dd3..afa72d799f7 100644 --- a/htdocs/product/stock/class/productstockentrepot.class.php +++ b/htdocs/product/stock/class/productstockentrepot.class.php @@ -89,23 +89,11 @@ class ProductStockEntrepot extends CommonObject // Clean parameters - if (isset($this->fk_product)) { - $this->fk_product = trim($this->fk_product); - } - if (isset($this->fk_entrepot)) { - $this->fk_entrepot = trim($this->fk_entrepot); - } - if (isset($this->seuil_stock_alerte)) { - $this->seuil_stock_alerte = trim($this->seuil_stock_alerte); - } - if (isset($this->desiredstock)) { - $this->desiredstock = trim($this->desiredstock); - } - if (isset($this->import_key)) { - $this->import_key = trim($this->import_key); - } - - + if (isset($this->fk_product)) $this->fk_product = trim($this->fk_product); + if (isset($this->fk_entrepot)) $this->fk_entrepot = trim($this->fk_entrepot); + if (isset($this->seuil_stock_alerte)) $this->seuil_stock_alerte = trim($this->seuil_stock_alerte); + if (isset($this->desiredstock)) $this->desiredstock = trim($this->desiredstock); + if (isset($this->import_key)) $this->import_key = trim($this->import_key); // Check parameters // Put here code to add control on parameters values @@ -115,8 +103,8 @@ class ProductStockEntrepot extends CommonObject $sql.= 'fk_product,'; $sql.= 'fk_entrepot,'; - $sql.= 'seuil_stock_alerte'; - $sql.= 'desiredstock'; + $sql.= 'seuil_stock_alerte,'; + $sql.= 'desiredstock,'; $sql.= 'import_key'; @@ -170,12 +158,15 @@ class ProductStockEntrepot extends CommonObject * Load object in memory from the database * * @param int $id Id object - * @param string $ref Ref + * @param int $fk_product Id product + * @param int $fk_entrepot Id warehouse * * @return int <0 if KO, 0 if not found, >0 if OK */ - public function fetch($id, $ref = null) + public function fetch($id, $fk_product, $fk_entrepot) { + if(empty($id) && (empty($fk_product) || empty($fk_entrepot))) return -1; + dol_syslog(__METHOD__, LOG_DEBUG); $sql = 'SELECT'; @@ -190,12 +181,9 @@ class ProductStockEntrepot extends CommonObject $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t'; - if (null !== $ref) { - $sql .= ' WHERE t.ref = ' . '\'' . $ref . '\''; - } else { - $sql .= ' WHERE t.rowid = ' . $id; - } - + if(!empty($id)) $sql .= ' WHERE t.rowid = ' . $id; + else $sql.= ' WHERE t.fk_product = '.$fk_product.' AND t.fk_entrepot = '.$fk_entrepot; + $resql = $this->db->query($sql); if ($resql) { $numrows = $this->db->num_rows($resql); @@ -250,7 +238,7 @@ class ProductStockEntrepot extends CommonObject * * @return int <0 if KO, >0 if OK */ - public function fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, array $filter = array(), $filtermode='AND') + public function fetchAll($fk_product='', $sortorder='', $sortfield='', $limit=0, $offset=0, array $filter = array(), $filtermode='AND') { dol_syslog(__METHOD__, LOG_DEBUG); @@ -266,7 +254,9 @@ class ProductStockEntrepot extends CommonObject $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element. ' as t'; - + + $sql .= ' WHERE 1=1'; + // Manage filter $sqlwhere = array(); if (count($filter) > 0) { @@ -274,16 +264,13 @@ class ProductStockEntrepot extends CommonObject $sqlwhere [] = $key . ' LIKE \'%' . $this->db->escape($value) . '%\''; } } - if (count($sqlwhere) > 0) { - $sql .= ' WHERE ' . implode(' '.$filtermode.' ', $sqlwhere); - } - - if (!empty($sortfield)) { - $sql .= $this->db->order($sortfield,$sortorder); - } - if (!empty($limit)) { - $sql .= ' ' . $this->db->plimit($limit + 1, $offset); - } + if (count($sqlwhere) > 0) $sql .= ' AND ' . implode(' '.$filtermode.' ', $sqlwhere); + + if(!empty($fk_product)) $sql .= ' AND fk_product = '.$fk_product; + + if (!empty($sortfield)) $sql .= $this->db->order($sortfield,$sortorder); + if (!empty($limit)) $sql .= ' ' . $this->db->plimit($limit + 1, $offset); + $this->lines = array(); $resql = $this->db->query($sql); @@ -291,20 +278,21 @@ class ProductStockEntrepot extends CommonObject $num = $this->db->num_rows($resql); while ($obj = $this->db->fetch_object($resql)) { - $line = new ProductStockEntrepotLine(); - - $line->id = $obj->rowid; - $line->tms = $this->db->jdate($obj->tms); - $line->fk_product = $obj->fk_product; - $line->fk_entrepot = $obj->fk_entrepot; + //$line->tms = $this->db->jdate($obj->tms); $line->seuil_stock_alerte = $obj->seuil_stock_alerte; $line->desiredstock = $obj->desiredstock; - $line->import_key = $obj->import_key; + //$line->import_key = $obj->import_key; - $this->lines[$line->id] = $line; + $this->lines[$obj->rowid] = array( + 'id'=>$obj->rowid + ,'fk_product'=>$obj->fk_product + ,'fk_entrepot'=>$obj->fk_entrepot + ,'seuil_stock_alerte'=>$obj->seuil_stock_alerte + ,'desiredstock'=>$obj->desiredstock + ); } $this->db->free($resql); @@ -333,22 +321,11 @@ class ProductStockEntrepot extends CommonObject // Clean parameters - if (isset($this->fk_product)) { - $this->fk_product = trim($this->fk_product); - } - if (isset($this->fk_entrepot)) { - $this->fk_entrepot = trim($this->fk_entrepot); - } - if (isset($this->seuil_stock_alerte)) { - $this->seuil_stock_alerte = trim($this->seuil_stock_alerte); - } - if (isset($this->desiredstock)) { - $this->desiredstock = trim($this->desiredstock); - } - if (isset($this->import_key)) { - $this->import_key = trim($this->import_key); - } - + if (isset($this->fk_product)) $this->fk_product = trim($this->fk_product); + if (isset($this->fk_entrepot)) $this->fk_entrepot = trim($this->fk_entrepot); + if (isset($this->seuil_stock_alerte)) $this->seuil_stock_alerte = trim($this->seuil_stock_alerte); + if (isset($this->desiredstock)) $this->desiredstock = trim($this->desiredstock); + if (isset($this->import_key)) $this->import_key = trim($this->import_key); // Check parameters diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index 1f90c473248..a611a7b663a 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -35,6 +35,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; +require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productstockentrepot.class.php'; if (! empty($conf->productbatch->enabled)) require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php'; $langs->load("products"); @@ -71,8 +72,44 @@ if ($cancel) $action=''; if($action == 'addlimitstockwarehouse') { - //var_dump($_REQUEST);exit; - $action=''; + $seuil_stock_alerte = GETPOST('seuil_stock_alerte'); + $desiredstock = GETPOST('desiredstock'); + + $maj_ok = true; + if($seuil_stock_alerte == '') { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("StockLimit")), null, 'errors'); + $maj_ok = false; + } + if($desiredstock == '') { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DesiredStock")), null, 'errors'); + $maj_ok = false; + } + + if($maj_ok) { + + $pse = new ProductStockEntrepot($db); + if($pse->fetch('', GETPOST('id'), GETPOST('fk_entrepot')) > 0) { + + // Update + $pse->seuil_stock_alerte = $seuil_stock_alerte; + $pse->desiredstock = $desiredstock; + if($pse->update($user) > 0) setEventMessage($langs->trans('ProductStockWarehouseUpdated')); + + } else { + + // Create + $pse->fk_entrepot = GETPOST('fk_entrepot'); + $pse->fk_product = GETPOST('id'); + $pse->seuil_stock_alerte = GETPOST('seuil_stock_alerte'); + $pse->desiredstock = GETPOST('desiredstock'); + if($pse->create($user) > 0) setEventMessage($langs->trans('ProductStockWarehouseCreated')); + + } + + } + + header("Location: ".$_SERVER["PHP_SELF"]."?id=".GETPOST('id')); + exit; } @@ -834,7 +871,7 @@ print ""; if(!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) { print '

'; - print_titre('Indiquer une limite pour alerte et un stock optimal'); + print_titre($langs->trans('AddNewProductStockWarehouse')); //print '
'; print '
'; @@ -842,12 +879,33 @@ if(!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) { print ''; print ''; - print ''; - print ''; + print ''; + print ''; print ''; - print ''; + print ''; print ''; + $pse = new ProductStockEntrepot($db); + $pse->fetchAll(GETPOST('id')); + + if(!empty($pse->lines)) { + + $var=false; + foreach($pse->lines as $line) { + + $ent = new Entrepot($db); + $ent->fetch($line['fk_entrepot']); + print ''; + print ''; + print ''; + print ''; + print ''; + $var=!$var; + + } + + } + print "
'.$formproduct->selectWarehouses().'
'.$formproduct->selectWarehouses('', 'fk_entrepot').'
'.$ent->getNomUrl(3).''.$line['seuil_stock_alerte'].''.$line['desiredstock'].' 
"; print '
'; From 43e77d23e94f0946f7112a627fc21d094e8fd04e Mon Sep 17 00:00:00 2001 From: gauthier Date: Mon, 19 Sep 2016 17:40:59 +0200 Subject: [PATCH 04/10] NEW : Delete product stock warehouse --- htdocs/product/stock/product.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index a611a7b663a..6e8f249f661 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -113,6 +113,17 @@ if($action == 'addlimitstockwarehouse') { } +if($action == 'delete_productstockwarehouse') +{ + + $pse = new ProductStockEntrepot($db); + $pse->fetch(GETPOST('fk_productstockwarehouse')); + $pse->delete($user); + + $action = ''; + +} + // Set stock limit if ($action == 'setseuil_stock_alerte') { @@ -898,7 +909,7 @@ if(!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) { print ''.$ent->getNomUrl(3).''; print ''.$line['seuil_stock_alerte'].''; print ''.$line['desiredstock'].''; - print ' '; + print '
'.img_delete().''; print ''; $var=!$var; From a698e40c459f0e3d0374cda3d5c20113a50d469e Mon Sep 17 00:00:00 2001 From: gauthier Date: Tue, 20 Sep 2016 11:55:38 +0200 Subject: [PATCH 05/10] NEW : filter fk_warehouse on replenishment card --- htdocs/product/stock/replenish.php | 61 ++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index ebd9f63f127..dec298afcbf 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -29,6 +29,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; +require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; require_once './lib/replenishment.lib.php'; $langs->load("products"); @@ -53,6 +54,7 @@ $salert = GETPOST('salert', 'alpha'); $mode = GETPOST('mode','alpha'); $fourn_id = GETPOST('fourn_id','int'); +$fk_entrepot = GETPOST('fk_entrepot','int'); $texte = ''; $sortfield = GETPOST('sortfield','alpha'); @@ -250,17 +252,26 @@ if ($action == 'order' && isset($_POST['valid'])) */ $form = new Form($db); +$formproduct = new FormProduct($db); $title = $langs->trans('Status'); $sql = 'SELECT p.rowid, p.ref, p.label, p.description, p.price,'; $sql.= ' p.price_ttc, p.price_base_type,p.fk_product_type,'; $sql.= ' p.tms as datem, p.duration, p.tobuy,'; -$sql.= ' p.desiredstock, p.seuil_stock_alerte as alertstock,'; +if(!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) { + $sql.= ' '.$db->ifsql("pse.desiredstock IS NULL", "p.desiredstock", "pse.desiredstock").' as desiredstock,'; + $sql.= ' '.$db->ifsql("pse.seuil_stock_alerte IS NULL", "p.seuil_stock_alerte", "pse.seuil_stock_alerte").' as alertstock,'; +} else { + $sql.= ' p.desiredstock, p.seuil_stock_alerte as alertstock,'; +} $sql.= ' SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").') as stock_physique'; $sql.= ' FROM ' . MAIN_DB_PREFIX . 'product as p'; $sql.= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'product_stock as s'; $sql.= ' ON p.rowid = s.fk_product'; +if(!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) { + $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock_entrepot pse ON (p.rowid = pse.fk_product AND pse.fk_entrepot = '.$fk_entrepot.')'; +} $sql.= ' WHERE p.entity IN (' . getEntity("product", 1) . ')'; if ($sall) { $sql .= ' AND (p.ref LIKE "%'.$db->escape($sall).'%" '; @@ -295,7 +306,11 @@ if (!empty($canvas)) $sql .= ' AND p.canvas = "' . $db->escape($canvas) . '"'; $sql.= ' GROUP BY p.rowid, p.ref, p.label, p.description, p.price'; $sql.= ', p.price_ttc, p.price_base_type,p.fk_product_type, p.tms'; $sql.= ', p.duration, p.tobuy'; -$sql.= ', p.desiredstock, p.seuil_stock_alerte'; +if(!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) { + $sql.= ', desiredstock, alertstock'; +} else { + $sql.= ', p.desiredstock, p.seuil_stock_alerte'; +} $sql.= ', s.fk_product'; if ($usevirtualstock) @@ -331,24 +346,24 @@ if ($usevirtualstock) $sqlReceptionFourn.= " AND fd.fk_product = p.rowid"; $sqlReceptionFourn.= " AND cf.fk_statut IN (3,4))"; - $sql.= ' HAVING ((('.$db->ifsql("p.desiredstock IS NULL", "0", "p.desiredstock").' > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')'; + $sql.= ' HAVING ((('.$db->ifsql("desiredstock IS NULL", "0", "desiredstock").' > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')'; $sql.= ' - ('.$sqlCommandesCli.' - '.$sqlExpeditionsCli.') + ('.$sqlCommandesFourn.' - '.$sqlReceptionFourn.')))'; - $sql.= ' OR (p.seuil_stock_alerte >= 0 AND (p.seuil_stock_alerte > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')'; + $sql.= ' OR (alertstock >= 0 AND (alertstock > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')'; $sql.= ' - ('.$sqlCommandesCli.' - '.$sqlExpeditionsCli.') + ('.$sqlCommandesFourn.' - '.$sqlReceptionFourn.'))))'; if ($salert == 'on') // Option to see when stock is lower than alert { - $sql.= ' AND (p.seuil_stock_alerte > 0 AND (p.seuil_stock_alerte > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')'; + $sql.= ' AND (alertstock > 0 AND (alertstock > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')'; $sql.= ' - ('.$sqlCommandesCli.' - '.$sqlExpeditionsCli.') + ('.$sqlCommandesFourn.' - '.$sqlReceptionFourn.')))'; $alertchecked = 'checked'; } } else { - $sql.= ' HAVING ((p.desiredstock > 0 AND (p.desiredstock > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')))'; - $sql.= ' OR (p.seuil_stock_alerte > 0 AND (p.seuil_stock_alerte > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").'))))'; + $sql.= ' HAVING ((desiredstock > 0 AND (desiredstock > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')))'; + $sql.= ' OR (alertstock > 0 AND (alertstock > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").'))))'; if ($salert == 'on') // Option to see when stock is lower than alert { - $sql.= ' AND (p.seuil_stock_alerte > 0 AND (p.seuil_stock_alerte > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')))'; + $sql.= ' AND (alertstock > 0 AND (alertstock > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')))'; $alertchecked = 'checked'; } } @@ -384,16 +399,6 @@ $head[1][2] = 'replenishorders'; print load_fiche_titre($langs->trans('Replenishment'), '', 'title_generic.png'); - -print '
'. - ''. - ''. - ''. - ''. - ''. - ''. - ''; - dol_fiche_head($head, 'replenish', '', 0, ''); print $langs->trans("ReplenishmentStatusDesc").'
'."\n"; @@ -401,16 +406,23 @@ if ($usevirtualstock == 1) { print $langs->trans("CurentSelectionMode").': '; print $langs->trans("CurentlyUsingVirtualStock").' - '; - print ''.$langs->trans("UsePhysicalStock").'
'; + print ''.$langs->trans("UsePhysicalStock").'
'; } if ($usevirtualstock == 0) { print $langs->trans("CurentSelectionMode").': '; print $langs->trans("CurentlyUsingPhysicalStock").' - '; - print ''.$langs->trans("UseVirtualStock").'
'; + print ''.$langs->trans("UseVirtualStock").'
'; } print '
'."\n"; +print ''; +print ''; +print ''; +print $formproduct->selectWarehouses($fk_entrepot, 'fk_entrepot', '', 1); +print ' '; +print '
'; + if ($sref || $snom || $sall || $salert || GETPOST('search', 'alpha')) { $filters = '&sref=' . $sref . '&snom=' . $snom; $filters .= '&sall=' . $sall; @@ -455,6 +467,15 @@ $stocklabel = $langs->trans('Stock'); if ($usevirtualstock == 1) $stocklabel = $langs->trans('VirtualStock'); if ($usevirtualstock == 0) $stocklabel = $langs->trans('PhysicalStock'); +print '
'. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''; // Lines of title print ''; From d508d44fef2751c0cb9439c91be7df3e3ca24091 Mon Sep 17 00:00:00 2001 From: gauthier Date: Tue, 20 Sep 2016 12:10:25 +0200 Subject: [PATCH 06/10] NEW : migration script from 4.0.0 to 5.0.0 and langs --- htdocs/install/mysql/migration/4.0.0-5.0.0.sql | 13 ++++++++++--- htdocs/langs/en_US/stocks.lang | 1 + htdocs/product/stock/product.php | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/htdocs/install/mysql/migration/4.0.0-5.0.0.sql b/htdocs/install/mysql/migration/4.0.0-5.0.0.sql index ef7189a3fa0..3c1928f3766 100644 --- a/htdocs/install/mysql/migration/4.0.0-5.0.0.sql +++ b/htdocs/install/mysql/migration/4.0.0-5.0.0.sql @@ -97,6 +97,13 @@ ALTER TABLE llx_product_lot_extrafields ADD INDEX idx_product_lot_extrafields (f ALTER TABLE llx_website_page MODIFY content MEDIUMTEXT; - - - +create table llx_product_stock_entrepot +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + tms timestamp, + fk_product integer NOT NULL, + fk_entrepot integer NOT NULL, + seuil_stock_alerte int(11) DEFAULT '0', + desiredstock int(11) DEFAULT '0', + import_key varchar(14) -- Import key +)ENGINE=innodb; diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index 1d63d4ddeb9..39f6e70aba6 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -139,4 +139,5 @@ UseDispatchStatus=Use dispatch status (aprouve/refuse) OptionMULTIPRICESIsOn=Option "several prices per segment" is on. It means a product has several selling price so value for sell can't be calculated ProductStockWarehouseCreated=Stock limit for alert and desired optimal stock correctly created ProductStockWarehouseUpdated=Stock limit for alert and desired optimal stock correctly updated +ProductStockWarehouseDeleted=Stock limit for alert and desired optimal stock correctly deleted AddNewProductStockWarehouse=Set new limit for alert and desired optimal stock \ No newline at end of file diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index 22af0745357..8ef8e2bc486 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -149,7 +149,7 @@ if($action == 'delete_productstockwarehouse') $pse = new ProductStockEntrepot($db); $pse->fetch(GETPOST('fk_productstockwarehouse')); - $pse->delete($user); + if($pse->delete($user) > 0) setEventMessage($langs->trans('ProductStockWarehouseDeleted')); $action = ''; From dc15eb079ad9a79ac8ed3a0e6794a2ce4757041b Mon Sep 17 00:00:00 2001 From: gauthier Date: Tue, 20 Sep 2016 14:35:07 +0200 Subject: [PATCH 07/10] FIX : keep params when we search or skip to another page --- htdocs/product/stock/replenish.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index dec298afcbf..ca71f36b8a6 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -418,6 +418,9 @@ print '
'."\n"; print ''; print ''; +print ''; +print ''; +print ''; print ''; print $formproduct->selectWarehouses($fk_entrepot, 'fk_entrepot', '', 1); print ' '; @@ -428,6 +431,7 @@ if ($sref || $snom || $sall || $salert || GETPOST('search', 'alpha')) { $filters .= '&sall=' . $sall; $filters .= '&salert=' . $salert; $filters .= '&mode=' . $mode; + $filters .= '&fk_entrepot=' . $fk_entrepot; print_barre_liste( $texte, $page, @@ -444,6 +448,7 @@ if ($sref || $snom || $sall || $salert || GETPOST('search', 'alpha')) { $filters .= (isset($type)?'&type=' . $type:''); $filters .= '&=' . $salert; $filters .= '&mode=' . $mode; + $filters .= '&fk_entrepot=' . $fk_entrepot; print_barre_liste( $texte, $page, @@ -462,6 +467,7 @@ $param = (isset($type)? '&type=' . $type : ''); $param .= '&fourn_id=' . $fourn_id . '&snom='. $snom . '&salert=' . $salert; $param .= '&sref=' . $sref; $param .= '&mode=' . $mode; +$param .= '&fk_entrepot=' . $fk_entrepot; $stocklabel = $langs->trans('Stock'); if ($usevirtualstock == 1) $stocklabel = $langs->trans('VirtualStock'); @@ -643,6 +649,7 @@ if ($num > $conf->liste_limit) $filters .= '&sall=' . $sall; $filters .= '&salert=' . $salert; $filters .= '&mode=' . $mode; + $filters .= '&fk_entrepot=' . $fk_entrepot; print_barre_liste('', $page, 'replenish.php', $filters, $sortfield, $sortorder, '', $num, 0, ''); } else @@ -652,6 +659,7 @@ if ($num > $conf->liste_limit) $filters .= (isset($type)? '&type=' . $type : ''); $filters .= '&salert=' . $salert; $filters .= '&mode=' . $mode; + $filters .= '&fk_entrepot=' . $fk_entrepot; print_barre_liste('', $page, 'replenish.php', $filters, $sortfield, $sortorder, '', $num, 0, ''); } } From b95b84a665935ed0cf5d124fc0388f54838a0940 Mon Sep 17 00:00:00 2001 From: gauthier Date: Tue, 20 Sep 2016 15:31:55 +0200 Subject: [PATCH 08/10] FIX : doc comment for parameter $fk_product --- .../stock/class/productstockentrepot.class.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/htdocs/product/stock/class/productstockentrepot.class.php b/htdocs/product/stock/class/productstockentrepot.class.php index afa72d799f7..cffc14532d9 100644 --- a/htdocs/product/stock/class/productstockentrepot.class.php +++ b/htdocs/product/stock/class/productstockentrepot.class.php @@ -229,11 +229,12 @@ class ProductStockEntrepot extends CommonObject /** * Load object in memory from the database * - * @param string $sortorder Sort Order - * @param string $sortfield Sort field - * @param int $limit offset limit - * @param int $offset offset limit - * @param array $filter filter array + * @param int $fk_product Product from which we want to get limit and desired stock by warehouse + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit offset limit + * @param int $offset offset limit + * @param array $filter filter array * @param string $filtermode filter mode (AND or OR) * * @return int <0 if KO, >0 if OK From 576ef9e541d72fc798680dd75f017af86ef1aa2e Mon Sep 17 00:00:00 2001 From: gauthier Date: Wed, 21 Sep 2016 09:31:40 +0200 Subject: [PATCH 09/10] FIX : sql syntax for travis test --- htdocs/install/mysql/migration/4.0.0-5.0.0.sql | 4 ++-- htdocs/install/mysql/tables/llx_product_stock_entrepot.sql | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/install/mysql/migration/4.0.0-5.0.0.sql b/htdocs/install/mysql/migration/4.0.0-5.0.0.sql index 3c1928f3766..cbbf6676352 100644 --- a/htdocs/install/mysql/migration/4.0.0-5.0.0.sql +++ b/htdocs/install/mysql/migration/4.0.0-5.0.0.sql @@ -103,7 +103,7 @@ create table llx_product_stock_entrepot tms timestamp, fk_product integer NOT NULL, fk_entrepot integer NOT NULL, - seuil_stock_alerte int(11) DEFAULT '0', - desiredstock int(11) DEFAULT '0', + seuil_stock_alerte integer DEFAULT '0', + desiredstock integer DEFAULT '0', import_key varchar(14) -- Import key )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_product_stock_entrepot.sql b/htdocs/install/mysql/tables/llx_product_stock_entrepot.sql index b0fcedc8ab6..ced4a2e8abb 100644 --- a/htdocs/install/mysql/tables/llx_product_stock_entrepot.sql +++ b/htdocs/install/mysql/tables/llx_product_stock_entrepot.sql @@ -24,8 +24,8 @@ create table llx_product_stock_entrepot tms timestamp, fk_product integer NOT NULL, fk_entrepot integer NOT NULL, - seuil_stock_alerte int(11) DEFAULT '0', - desiredstock int(11) DEFAULT '0', + seuil_stock_alerte integer DEFAULT '0', + desiredstock integer DEFAULT '0', import_key varchar(14) -- Import key )ENGINE=innodb; From 2556e59ccf8aa290e27e790f3552f00ee4f0ebcf Mon Sep 17 00:00:00 2001 From: gauthier Date: Wed, 21 Sep 2016 16:21:23 +0200 Subject: [PATCH 10/10] NEW : auto delete product_stock_entrepot elements when we drop a product or a warehouse --- htdocs/product/class/product.class.php | 2 +- htdocs/product/stock/class/entrepot.class.php | 27 ++++++++------ .../class/productstockentrepot.class.php | 36 ++++++++----------- htdocs/product/stock/product.php | 6 ++-- 4 files changed, 36 insertions(+), 35 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index ef1ec0a856e..89a7ac8a910 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -926,7 +926,7 @@ class Product extends CommonObject // Delete all child tables if (! $error) { - $elements = array('product_fournisseur_price','product_price','product_lang','categorie_product','product_stock','product_customer_price','product_lot'); + $elements = array('product_fournisseur_price','product_price','product_lang','categorie_product','product_stock','product_customer_price','product_lot','product_stock_entrepot'); foreach($elements as $table) { if (! $error) diff --git a/htdocs/product/stock/class/entrepot.class.php b/htdocs/product/stock/class/entrepot.class.php index d01d1709335..d99de70f506 100644 --- a/htdocs/product/stock/class/entrepot.class.php +++ b/htdocs/product/stock/class/entrepot.class.php @@ -221,17 +221,24 @@ class Entrepot extends CommonObject { $this->db->begin(); - $sql = "DELETE FROM ".MAIN_DB_PREFIX."stock_mouvement"; - $sql.= " WHERE fk_entrepot = " . $this->id; - dol_syslog(get_class($this)."::delete", LOG_DEBUG); - $resql1=$this->db->query($sql); + $elements = array('stock_mouvement','product_stock','product_stock_entrepot'); + foreach($elements as $table) + { + if (! $error) + { + $sql = "DELETE FROM ".MAIN_DB_PREFIX.$table; + $sql.= " WHERE fk_entrepot = " . $this->id; + dol_syslog(get_class($this)."::delete", LOG_DEBUG); + $result=$this->db->query($sql); + if (! $result) + { + $error++; + $this->errors[] = $this->db->lasterror(); + } + } + } - $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_stock"; - $sql.= " WHERE fk_entrepot = " . $this->id; - dol_syslog(get_class($this)."::delete", LOG_DEBUG); - $resql2=$this->db->query($sql); - - if ($resql1 && $resql2) + if (! $error) { $sql = "DELETE FROM ".MAIN_DB_PREFIX."entrepot"; $sql.= " WHERE rowid = " . $this->id; diff --git a/htdocs/product/stock/class/productstockentrepot.class.php b/htdocs/product/stock/class/productstockentrepot.class.php index cffc14532d9..e11467940d7 100644 --- a/htdocs/product/stock/class/productstockentrepot.class.php +++ b/htdocs/product/stock/class/productstockentrepot.class.php @@ -229,7 +229,8 @@ class ProductStockEntrepot extends CommonObject /** * Load object in memory from the database * - * @param int $fk_product Product from which we want to get limit and desired stock by warehouse + * @param int $fk_product Product from which we want to get limit and desired stock by warehouse + * @param int $fk_entrepot Warehouse in which we want to get products limit and desired stock * @param string $sortorder Sort Order * @param string $sortfield Sort field * @param int $limit offset limit @@ -239,7 +240,7 @@ class ProductStockEntrepot extends CommonObject * * @return int <0 if KO, >0 if OK */ - public function fetchAll($fk_product='', $sortorder='', $sortfield='', $limit=0, $offset=0, array $filter = array(), $filtermode='AND') + public function fetchAll($fk_product='', $fk_entrepot='', $sortorder='', $sortfield='', $limit=0, $offset=0, array $filter = array(), $filtermode='AND') { dol_syslog(__METHOD__, LOG_DEBUG); @@ -268,36 +269,29 @@ class ProductStockEntrepot extends CommonObject if (count($sqlwhere) > 0) $sql .= ' AND ' . implode(' '.$filtermode.' ', $sqlwhere); if(!empty($fk_product)) $sql .= ' AND fk_product = '.$fk_product; + elseif(!empty($fk_entrepot)) $sql .= ' AND fk_entrepot = '.$fk_entrepot; + // "elseif" used instead of "if" because getting list with specified fk_product and specified fk_entrepot would be the same as doing a fetch if (!empty($sortfield)) $sql .= $this->db->order($sortfield,$sortorder); if (!empty($limit)) $sql .= ' ' . $this->db->plimit($limit + 1, $offset); - $this->lines = array(); + $lines = array(); $resql = $this->db->query($sql); if ($resql) { - $num = $this->db->num_rows($resql); - + while ($obj = $this->db->fetch_object($resql)) { - - //$line->tms = $this->db->jdate($obj->tms); - $line->seuil_stock_alerte = $obj->seuil_stock_alerte; - $line->desiredstock = $obj->desiredstock; - //$line->import_key = $obj->import_key; - - - - $this->lines[$obj->rowid] = array( - 'id'=>$obj->rowid - ,'fk_product'=>$obj->fk_product - ,'fk_entrepot'=>$obj->fk_entrepot - ,'seuil_stock_alerte'=>$obj->seuil_stock_alerte - ,'desiredstock'=>$obj->desiredstock - ); + $lines[$obj->rowid] = array( + 'id'=>$obj->rowid + ,'fk_product'=>$obj->fk_product + ,'fk_entrepot'=>$obj->fk_entrepot + ,'seuil_stock_alerte'=>$obj->seuil_stock_alerte + ,'desiredstock'=>$obj->desiredstock + ); } $this->db->free($resql); - return $num; + return $lines; } else { $this->errors[] = 'Error ' . $this->db->lasterror(); dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index 8ef8e2bc486..4482e249410 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -937,12 +937,12 @@ if(!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) { print ''; $pse = new ProductStockEntrepot($db); - $pse->fetchAll(GETPOST('id')); + $lines = $pse->fetchAll(GETPOST('id')); - if(!empty($pse->lines)) { + if(!empty($lines)) { $var=false; - foreach($pse->lines as $line) { + foreach($lines as $line) { $ent = new Entrepot($db); $ent->fetch($line['fk_entrepot']);