From a636d27ccbfc1e5ea59862af1d7e909b382ffff7 Mon Sep 17 00:00:00 2001 From: Alexis Algoud Date: Wed, 14 Dec 2016 14:34:12 +0100 Subject: [PATCH] Div --- htdocs/core/class/coreobject.class.php | 22 +- htdocs/core/class/listview.class.php | 144 ++-- htdocs/core/lib/functions.lib.php | 114 ++- htdocs/inventory/class/inventory.class.php | 24 +- htdocs/inventory/img/inventory.png | Bin 0 -> 1802 bytes htdocs/inventory/inventory.php | 797 +++++++++++++++++++++ htdocs/inventory/lib/inventory.lib.php | 245 +++++++ htdocs/inventory/tpl/inventory.tpl.php | 211 ++++++ 8 files changed, 1433 insertions(+), 124 deletions(-) create mode 100644 htdocs/inventory/img/inventory.png create mode 100644 htdocs/inventory/inventory.php create mode 100644 htdocs/inventory/lib/inventory.lib.php create mode 100644 htdocs/inventory/tpl/inventory.tpl.php diff --git a/htdocs/core/class/coreobject.class.php b/htdocs/core/class/coreobject.class.php index 96cbbb89a88..b7e4b2770e3 100644 --- a/htdocs/core/class/coreobject.class.php +++ b/htdocs/core/class/coreobject.class.php @@ -1,5 +1,7 @@ +/* EXPERIMENTAL + * + * Copyright (C) 2016 ATM Consulting * * 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 @@ -220,9 +222,8 @@ class CoreObject extends CommonObject { WHERE rowid='.$id; $res = $this->db->query( $sql ); - if($obj = $this->db->fetch_object($res)) { - $this->rowid=$id; + $this->id=$id; $this->set_vars_by_db($obj); @@ -248,12 +249,12 @@ class CoreObject extends CommonObject { $this->{$className}=array(); - $sql = " SELECT rowid FROM ".MAIN_DB_PREFIX.$childTable." WHERE ".$this->fk_element."=".$this->rowid; + $sql = " SELECT rowid FROM ".MAIN_DB_PREFIX.$childTable." WHERE ".$this->fk_element."=".$this->id; $res = $this->db->query($sql); if($res) { - - while($obj = $db->fetch_object($res)) { + $Tab=array(); + while($obj = $this->db->fetch_object($res)) { $o=new $className($this->db); $o->fetch($obj->rowid); @@ -282,5 +283,14 @@ class CoreObject extends CommonObject { } + public function get_date($field,$format='') { + if(empty($this->{$field})) return ''; + elseif($this->{$field}<=strtotime('1000-01-01 00:00:00')) return ''; + else { + return dol_print_date($this->{$field}, $format); + } + + } + } diff --git a/htdocs/core/class/listview.class.php b/htdocs/core/class/listview.class.php index db66f9f15a3..e94a648ec27 100644 --- a/htdocs/core/class/listview.class.php +++ b/htdocs/core/class/listview.class.php @@ -1,7 +1,8 @@ + Copyright (C) 2016 ATM Consulting This program and all files within this directory and sub directory is free software: you can redistribute it and/or modify it under @@ -505,88 +506,91 @@ class Listview { } private function renderList(&$THeader, &$TField, &$TTotal,&$TTotalGroup, &$TParam) { - + $javaScript = $this->getJS($TParam); - $TPagination=array( + /*$TPagination=array( 'pagination'=>array('pageSize'=>$TParam['limit']['nbLine'], 'pageNum'=>$TParam['limit']['page'], 'blockName'=>'champs', 'totalNB'=>count($TField)) - ); + );*/ $TSearch = $this->setSearch($THeader, $TParam); $TExport=$this->setExport($TParam, $TField, $THeader); $TField = $this->addTotalGroup($TField,$TTotalGroup); $out = $javaScript; + $out.=load_fiche_titre($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $TParam['limit']['page'], count($TField), 'title_products.png', 0, '', '', $limit); + $out.=' + '; - $out.=load_fiche_titre($TParam['list']['title']); - print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, count($TField), 'title_products.png', 0, '', '', $limit); - /* - $out.='
- - [onshow;block=begin; when [liste.noheader]==0] - - - [onshow;block=end] - - -
- [liste.image;magnet=img; strconv=no] -
[liste.titre; strconv=no]
- -
+ if(!empty($TParam['liste']['head_search'])) { + $out.=' + '.$TParam['liste']['head_search'].' + '; + } + + $out.=''; - - - - - - - - + foreach($THeader as $head) { + $out.=''; + } + + $out.=''; + + if(!empty($TParam['liste']['nbSearch'])) { + $out.=' + + '; + } - [onshow;block=tr;when [liste.nbSearch]+-0] - - - - - - - - - - - - - - - - - [onshow;block=tr; when [liste.haveTotal]+-0 ] - - - - -
[liste.head_search;strconv=no;magnet=tr]
[entete.libelle;block=th;strconv=no] - [onshow;block=span; when [entete.order]==1][liste.order_down;strconv=no][liste.order_up;strconv=no] - [entete.more;strconv=no;] -
'.$head['libelle']; + + if($head['order']) $out.='[onshow;block=span; when [entete.order]==1]'.img_down().' + '.img_up().''; + + $out.=$head['more']; + $out.='
'.img_search().'
[recherche.val;block=td;strconv=no]
[champs_sub1.val;block=td; strconv=no]
[champs_sub1.val;block=td; strconv=no]
[total.val;block=td;strconv=no;frm=0 000,00]
+ $out.=''; -
- [onshow;block=div; when [liste.haveExport]+-0 ] - [export.label;block=a;] -
-

- [liste.messageNothing;strconv=no] [onshow; block=p; when [liste.totalNB]==0] -

';*/ + $class='pair'; + + if(empty($TField)) { + $out.=' + '.$TParam['liste']['messageNothing'].''; + + } + else{ + + foreach($TField as $fields) { //TODO pagination limit + + $class = ($class=='pair') ? 'impair' : 'pair'; + $out.=' '; + + foreach($fields as $field=>$value) { + $out.=''.$value.''; + } + + $out.=''; + + } + + $out.=''; + + if(!empty($TParam['liste']['haveTotal'])) { + $out.=' + '; + + foreach($TTotal as $field=>$total) { + $out.=''.price($total).''; + } + + $out.=''; + } + + } + + + $out.=''; + + return $out; } public function renderArray(&$db,$TField, $TParam=array()) { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 082177b5cbc..c4b21e4ee82 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -3157,7 +3157,7 @@ function load_fiche_titre($titre, $morehtmlright='', $picto='title_generic.png', } /** - * Print a title with navigation controls for pagination + * return a title with navigation controls for pagination * * @param string $titre Title to show (required) * @param int $page Numero of page to show in navigation links (required) @@ -3176,7 +3176,7 @@ function load_fiche_titre($titre, $morehtmlright='', $picto='title_generic.png', * @param int $hideselectlimit Force to hide select limit * @return void */ -function print_barre_liste($titre, $page, $file, $options='', $sortfield='', $sortorder='', $center='', $num=-1, $totalnboflines=-1, $picto='title_generic.png', $pictoisfullpath=0, $morehtml='', $morecss='', $limit=-1, $hideselectlimit=0) +function load_barre_liste($titre, $page, $file, $options='', $sortfield='', $sortorder='', $center='', $num=-1, $totalnboflines=-1, $picto='title_generic.png', $pictoisfullpath=0, $morehtml='', $morecss='', $limit=-1, $hideselectlimit=0) { global $conf,$langs; @@ -3196,27 +3196,26 @@ function print_barre_liste($titre, $page, $file, $options='', $sortfield='', $so $nextpage = 0; } //print 'totalnboflines='.$totalnboflines.'-savlimit='.$savlimit.'-limit='.$limit.'-num='.$num.'-nextpage='.$nextpage; - - print "\n"; - print "\n"; - print ''; + $out = "\n"; + $out.= "\n"; + $out.='
'; // Left - //if ($picto && $titre) print ''; - print ''; + //if ($picto && $titre) $out.=''; + $out.=''; // Center if ($center) { - print ''; + $out.=''; } // Right - print ''; + $out.=load_fleche_navigation($page, $file, $options, $nextpage, $pagelist, $morehtml, $savlimit, $totalnboflines, $hideselectlimit); // output the div and ul for previous/last completed with page numbers into $pagelist + $out.=''; - print '
'.img_picto('', $picto, 'id="pictotitle"', $pictoisfullpath).''; - if ($picto && $titre) print img_picto('', $picto, 'class="hideonsmartphone valignmiddle" id="pictotitle"', $pictoisfullpath); - print '
'.$titre; - if (!empty($titre) && $savtotalnboflines >= 0) print ' ('.$totalnboflines.')'; - print '
'.img_picto('', $picto, 'id="pictotitle"', $pictoisfullpath).''; + if ($picto && $titre) $out.=img_picto('', $picto, 'class="hideonsmartphone valignmiddle" id="pictotitle"', $pictoisfullpath); + $out.='
'.$titre; + if (!empty($titre) && $savtotalnboflines >= 0) $out.=' ('.$totalnboflines.')'; + $out.='
'.$center.''.$center.''; + $out.=''; if ($sortfield) $options .= "&sortfield=".$sortfield; if ($sortorder) $options .= "&sortorder=".$sortorder; // Show navigation bar @@ -3265,15 +3264,39 @@ function print_barre_liste($titre, $page, $file, $options='', $sortfield='', $so $pagelist.= 'dol_use_jmobile != 4)?' class="pagination"':'').'>dol_use_jmobile != 4)?'class="active"':'data-role="button"').'>'.($page+1).""; } } - print_fleche_navigation($page, $file, $options, $nextpage, $pagelist, $morehtml, $savlimit, $totalnboflines, $hideselectlimit); // output the div and ul for previous/last completed with page numbers into $pagelist - print '
'."\n"; - print "\n\n"; + $out.=''."\n"; + $out.="\n\n"; +} +/** + * Print a title with navigation controls for pagination + * + * @param string $titre Title to show (required) + * @param int $page Numero of page to show in navigation links (required) + * @param string $file Url of page (required) + * @param string $options More parameters for links ('' by default, does not include sortfield neither sortorder) + * @param string $sortfield Field to sort on ('' by default) + * @param string $sortorder Order to sort ('' by default) + * @param string $center String in the middle ('' by default). We often find here string $massaction comming from $form->selectMassAction() + * @param int $num Number of records found by select with limit+1 + * @param int $totalnboflines Total number of records/lines for all pages (if known). Use a negative value to not show number. + * @param string $picto Icon to use before title (should be a 32x32 transparent png file) + * @param int $pictoisfullpath 1=Icon name is a full absolute url of image + * @param string $morehtml More html to show + * @param string $morecss More css to the table + * @param int $limit Max number of lines (-1 = use default, 0 = no limit, > 0 = limit). + * @param int $hideselectlimit Force to hide select limit + * @return void + */ +function print_barre_liste($titre, $page, $file, $options='', $sortfield='', $sortorder='', $center='', $num=-1, $totalnboflines=-1, $picto='title_generic.png', $pictoisfullpath=0, $morehtml='', $morecss='', $limit=-1, $hideselectlimit=0) +{ + echo load_barre_liste($titre, $page, $file, $options, $sortfield, $sortorder, $center, $num, $totalnboflines, $picto, $pictoisfullpath, $morehtml, $morecss, $limit, $hideselectlimit); } /** - * Function to show navigation arrows into lists + * Function to return navigation arrows into lists * * @param int $page Number of page * @param string $file Page URL (in most cases provided with $_SERVER["PHP_SELF"]) @@ -3286,11 +3309,11 @@ function print_barre_liste($titre, $page, $file, $options='', $sortfield='', $so * @param int $hideselectlimit Force to hide select limit * @return void */ -function print_fleche_navigation($page, $file, $options='', $nextpage=0, $betweenarrows='', $afterarrows='', $limit=-1, $totalnboflines=0, $hideselectlimit=0) +function load_fleche_navigation($page, $file, $options='', $nextpage=0, $betweenarrows='', $afterarrows='', $limit=-1, $totalnboflines=0, $hideselectlimit=0) { global $conf, $langs; - print ''."\n"; +} +/** + * Function to show navigation arrows into lists + * + * @param int $page Number of page + * @param string $file Page URL (in most cases provided with $_SERVER["PHP_SELF"]) + * @param string $options Other url paramaters to propagate ("" by default, may include sortfield and sortorder) + * @param integer $nextpage Do we show a next page button + * @param string $betweenarrows HTML content to show between arrows. MUST contains '
  • ' tags or '
  • '. + * @param string $afterarrows HTML content to show after arrows. Must NOT contains '
  • ' tags. + * @param int $limit Max nb of record to show (-1 = no combo with limit, 0 = no limit, > 0 = limit) + * @param int $totalnboflines Total number of records/lines for all pages (if known) + * @param int $hideselectlimit Force to hide select limit + * @return void + */ +function print_fleche_navigation($page, $file, $options='', $nextpage=0, $betweenarrows='', $afterarrows='', $limit=-1, $totalnboflines=0, $hideselectlimit=0) +{ + echo load_fleche_navigation($page, $file, $options, $nextpage, $betweenarrows, $afterarrows, $limit, $totalnboflines, $hideselectlimit); } - /** * Return a string with VAT rate label formated for view output diff --git a/htdocs/inventory/class/inventory.class.php b/htdocs/inventory/class/inventory.class.php index 59ad70cec4e..2a485d24a0a 100644 --- a/htdocs/inventory/class/inventory.class.php +++ b/htdocs/inventory/class/inventory.class.php @@ -97,17 +97,20 @@ class Inventory extends CoreObject if(!$annexe) $this->withChild = false; $res = parent::fetch($id); - $this->sort_det(); - $this->amount = 0; - - if(!empty($this->Inventorydet )) { - foreach($this->Inventorydet as &$det){ - $this->amount+=$det->qty_view * $det->pmp; - } + if($res>0) { + $this->sort_det(); + $this->amount = 0; + + if(!empty($this->Inventorydet )) { + foreach($this->Inventorydet as &$det){ + $this->amount+=$det->qty_view * $det->pmp; + } + + } } - + return $res; } @@ -312,9 +315,8 @@ class Inventory extends CoreObject global $langs,$db; $i = new Inventory($db); - $i->fetch($id, false); - - return $i->getNomUrl(); + if($i->fetch($id, false)>0) return $i->getNomUrl(); + else return $langs->trans('InventoryUnableToFetchObject'); } diff --git a/htdocs/inventory/img/inventory.png b/htdocs/inventory/img/inventory.png new file mode 100644 index 0000000000000000000000000000000000000000..e54ad0eef7d76b373e8769153f9039a75681ab3b GIT binary patch literal 1802 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 literal 0 HcmV?d00001 diff --git a/htdocs/inventory/inventory.php b/htdocs/inventory/inventory.php new file mode 100644 index 00000000000..d46f05059b4 --- /dev/null +++ b/htdocs/inventory/inventory.php @@ -0,0 +1,797 @@ + + * + * 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 htdocs/inventory/inventory.php + * \ingroup product + * \brief File of class to manage inventory + */ + +require_once '../main.inc.php'; + +ini_set('memory_limit', '512M'); + +require_once DOL_DOCUMENT_ROOT.'/core/class/listview.class.php'; +require_once DOL_DOCUMENT_ROOT.'/inventory/class/inventory.class.php'; +require_once DOL_DOCUMENT_ROOT.'/inventory/lib/inventory.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; +include_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; +require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; + +set_time_limit(0); + +if(!$user->rights->inventory->read) accessforbidden(); + +$langs->load("inventory"); + +_action(); + +function _action() +{ + global $user, $db, $conf, $langs; + + /******************************************************************* + * ACTIONS + * + * Put here all code to do according to value of "action" parameter + ********************************************************************/ + + $action=GETPOST('action'); + + switch($action) { + case 'list': + _list(); + + break; + + case 'create': + if (!$user->rights->inventory->create) accessforbidden(); + + $inventory = new Inventory($db); + + _fiche_warehouse($user, $db, $conf, $langs, $inventory); + + break; + + case 'confirmCreate': + if (!$user->rights->inventory->create) accessforbidden(); + + + $inventory = new Inventory($db); + $inventory->set_values($_REQUEST); + + $fk_inventory = $inventory->save(); + $fk_category = (int)GETPOST('fk_category'); + $fk_supplier = (int)GETPOST('fk_supplier'); + $fk_warehouse = (int)GETPOST('fk_warehouse'); + $only_prods_in_stock = (int)GETPOST('OnlyProdsInStock'); + + $e = new Entrepot($db); + $e->fetch($fk_warehouse); + $TChildWarehouses = array($fk_warehouse); + if(method_exists($e, 'get_children_warehouses')) $e->get_children_warehouses($fk_warehouse, $TChildWarehouses); + + $sql = 'SELECT ps.fk_product, ps.fk_entrepot + FROM '.MAIN_DB_PREFIX.'product_stock ps + INNER JOIN '.MAIN_DB_PREFIX.'product p ON (p.rowid = ps.fk_product) + LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product cp ON (cp.fk_product = p.rowid) + LEFT JOIN '.MAIN_DB_PREFIX.'product_fournisseur_price pfp ON (pfp.fk_product = p.rowid) + WHERE ps.fk_entrepot IN ('.implode(', ', $TChildWarehouses).')'; + + if($fk_category>0) $sql.= " AND cp.fk_categorie=".$fk_category; + if($fk_supplier>0) $sql.= " AND pfp.fk_soc=".$fk_supplier; + if($only_prods_in_stock>0) $sql.= ' AND ps.reel > 0'; + + $sql.=' GROUP BY ps.fk_product, ps.fk_entrepot + ORDER BY p.ref ASC,p.label ASC'; + + + $Tab = $PDOdb->ExecuteAsArray($sql); + + foreach($Tab as &$row) { + + $inventory->add_product($PDOdb, $row->fk_product, $row->fk_entrepot); + } + + $inventory->save($PDOdb); + + header('Location: '.dol_buildpath('inventory/inventory.php?id='.$inventory->getId().'&action=edit', 1)); + + case 'edit': + if (!$user->rights->inventory->write) accessforbidden(); + + + $id = __get('id', 0, 'int'); + + $inventory = new Inventory($db); + $inventory->load($PDOdb, $id); + + _fiche($PDOdb, $user, $db, $conf, $langs, $inventory, __get('action', 'edit', 'string')); + + break; + + case 'save': + if (!$user->rights->inventory->write) accessforbidden(); + + + $id = __get('id', 0, 'int'); + + $inventory = new Inventory($db); + $inventory->load($PDOdb, $id); + + $inventory->set_values($_REQUEST); + + if ($inventory->errors) + { + setEventMessage($inventory->errors, 'errors'); + _fiche($PDOdb, $user, $db, $conf, $langs, $inventory, 'edit'); + } + else + { + $inventory->save($PDOdb); + header('Location: '.dol_buildpath('inventory/inventory.php?id='.$inventory->getId().'&action=view', 1)); + } + + break; + + case 'regulate': + + $id = __get('id', 0, 'int'); + + $inventory = new Inventory($db); + $inventory->load($PDOdb, $id); + + if($inventory->status == 0) { + $inventory->status = 1; + $inventory->save($PDOdb); + + _fiche($PDOdb, $user, $db, $conf, $langs, $inventory, 'view'); + + + } + else { + _fiche($PDOdb, $user, $db, $conf, $langs, $inventory, 'view'); + } + + break; + + case 'changePMP': + + $id = __get('id', 0, 'int'); + + $inventory = new Inventory($db); + $inventory->load($PDOdb, $id); + + $inventory->changePMP($PDOdb); + + _fiche($PDOdb, $user, $db, $conf, $langs, $inventory, 'view'); + + break; + + case 'add_line': + if (!$user->rights->inventory->write) accessforbidden(); + + + $id = __get('id', 0, 'int'); + $fk_warehouse = __get('fk_warehouse', 0, 'int'); + + $inventory = new Inventory($db); + $inventory->load($PDOdb, $id); + + $type = (!empty($conf->use_javascript_ajax) && !empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT) ? 'string' : 'int'); //AA heu ? + + $fk_product = __get('fk_product', 0, $type); + + if ($fk_product) + { + $product = new Product($db); + $product->fetch($fk_product); // ! ref TODO vérifier quand même + if($product->type != 0) { + setEventMessage($langs->trans('ThisIsNotAProduct'),'errors'); + } + else{ + + //Check product not already exists + $alreadyExists = false; + foreach ($inventory->Inventorydet as $invdet) + { + if ($invdet->fk_product == $product->id + && $invdet->fk_warehouse == $fk_warehouse) + { + $alreadyExists = true; + break; + } + } + + if (!$alreadyExists) + { + $inventory->add_product($PDOdb, $product->id, $fk_warehouse); + + } + else + { + setEventMessage($langs->trans('inventoryWarningProductAlreadyExists'), 'warnings'); + } + + } + + $inventory->save($PDOdb); + $inventory->sort_det(); + } + + _fiche($PDOdb, $user, $db, $conf, $langs, $inventory, 'edit'); + + break; + + case 'delete_line': + if (!$user->rights->inventory->write) accessforbidden(); + + + //Cette action devrais se faire uniquement si le status de l'inventaire est à 0 mais aucune vérif + $rowid = __get('rowid', 0, 'int'); + $Inventorydet = new Inventory($db); + $Inventorydet->load($PDOdb, $rowid); + $Inventorydet->delete($PDOdb); + + $id = __get('id', 0, 'int'); + $inventory = new Inventory($db); + $inventory->load($PDOdb, $id); + + _fiche($PDOdb, $user, $db, $conf, $langs, $inventory, 'edit'); + + break; + case 'flush': + if (!$user->rights->inventory->create) accessforbidden(); + + + $id = __get('id', 0, 'int'); + + $inventory = new Inventory($db); + $inventory->load($PDOdb, $id); + + $inventory->deleteAllLine($PDOdb); + + setEventMessage('Inventaire vidé'); + + _fiche($PDOdb, $user, $db, $conf, $langs, $inventory, 'edit'); + + + break; + case 'delete': + if (!$user->rights->inventory->create) accessforbidden(); + + + $id = __get('id', 0, 'int'); + + $inventory = new Inventory($db); + $inventory->load($PDOdb, $id); + + $inventory->delete($PDOdb); + + header('Location: '.dol_buildpath('/inventory/inventory.php', 1)); + exit; + //_list(); + + case 'printDoc': + + $id = __get('id', 0, 'int'); + + $inventory = new Inventory($db); + $inventory->load($PDOdb, $id); + + generateODT($PDOdb, $db, $conf, $langs, $inventory); + break; + + case 'exportCSV': + + $id = __get('id', 0, 'int'); + + $inventory = new Inventory($db); + $inventory->load($PDOdb, $id); + + exportCSV($inventory); + + exit; + break; + + default: + if (!$user->rights->inventory->write) accessforbidden(); + + $id = GETPOST('id'); + + $inventory = new Inventory($db); + $inventory->fetch($id); + + _card($inventory, $action ); + + + break; + } + +} + +function _list() +{ + + global $db, $conf, $langs, $user; + + llxHeader('',$langs->trans('inventoryListTitle'),'',''); + + $inventory = new Inventory($db); + $l = new ListView($db,'listInventory'); + + $THide = array('label'); + + echo $l->render(Inventory::getSQL('All'), array( + 'limit'=>array( + 'nbLine'=>'30' + ) + ,'subQuery'=>array() + ,'link'=>array( + 'fk_warehouse'=>''.img_picto('','object_stock.png','',0).' @label@' + ) + ,'translate'=>array() + ,'hide'=>$THide + ,'type'=>array( + 'date_cre'=>'date' + ,'date_maj'=>'datetime' + ,'date_inventory'=>'date' + ) + ,'liste'=>array( + 'titre'=>$langs->trans('inventoryListTitle') + ,'image'=>img_picto('','title.png', '', 0) + ,'picto_precedent'=>img_picto('','back.png', '', 0) + ,'picto_suivant'=>img_picto('','next.png', '', 0) + ,'noheader'=> (int)isset($_REQUEST['fk_soc']) | (int)isset($_REQUEST['fk_product']) + ,'messageNothing'=>$langs->trans('inventoryListEmpty') + ,'picto_search'=>img_picto('','search.png', '', 0) + ) + ,'title'=>array( + 'rowid'=>$langs->trans('Title') + ,'fk_warehouse'=>$langs->trans('Warehouse') + ,'date_inventory'=>$langs->trans('InventoryDate') + ,'datec'=>$langs->trans('DateCreation') + ,'tms'=>$langs->trans('DateUpdate') + ,'status'=>$langs->trans('Status') + ) + ,'eval'=>array( + 'status' => '(@val@ ? img_picto("'.$langs->trans("inventoryValidate").'", "statut4") : img_picto("'.$langs->trans("inventoryDraft").'", "statut3"))' + ,'rowid'=>'Inventory::getLink(@val@)' + + ) + )); + + + if ($user->rights->inventory->create) + { + print '
    '; + print ''.$langs->trans('inventoryCreate').''; + print '
    '; + } + + llxFooter(''); +} + +function _fiche_warehouse(&$PDOdb, &$user, &$db, &$conf, $langs, $inventory) +{ + dol_include_once('/categories/class/categorie.class.php'); + + llxHeader('',$langs->trans('inventorySelectWarehouse'),'',''); + print dol_get_fiche_head(inventoryPrepareHead($inventory)); + + $form=new TFormCore('inventory.php', 'confirmCreate'); + print $form->hidden('action', 'confirmCreate'); + $form->Set_typeaff('edit'); + + $formproduct = new FormProduct($db); + $formDoli = new Form($db); + + ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    trans('Title') ?>texte('', 'title', '',50,255) ?>
    trans('Date') ?>calendrier('', 'date_inventory',time()) ?>
    trans('inventorySelectWarehouse') ?>selectWarehouses('', 'fk_warehouse') ?>
    trans('SelectCategory') ?>select_all_categories(0,'', 'fk_category') ?>
    trans('SelectFournisseur') ?>select_thirdparty('','fk_supplier','s.fournisseur = 1') ?>
    trans('OnlyProdsInStock') ?>
    + '; + print ''; + print ''; + + print $form->end_form(); + llxFooter(''); +} + +function _card(&$inventory, $mode='edit') +{ + global $langs, $conf, $db, $user; + + llxHeader('',$langs->trans('inventoryEdit'),'',''); + + $warehouse = new Entrepot($db); + $warehouse->fetch($inventory->fk_warehouse); + + print dol_get_fiche_head(inventoryPrepareHead($inventory, $langs->trans('inventoryOfWarehouse', $warehouse->libelle), '&action='.$mode)); + + $lines = array(); + _card_line($inventory, $lines, $form); + + print ''.$langs->trans('inventoryOnDate')." ".$inventory->get_date('date_inventory').'

    '; + + $inventoryTPL = array( + 'id'=> $inventory->id + ,'date_cre' => $inventory->get_date('date_cre', 'd/m/Y') + ,'date_maj' => $inventory->get_date('date_maj', 'd/m/Y H:i') + ,'fk_warehouse' => $inventory->fk_warehouse + ,'status' => $inventory->status + ,'entity' => $inventory->entity + ,'amount' => price( round($inventory->amount,2) ) + ,'amount_actual'=>price (round($inventory->amount_actual,2)) + + ); + + $can_validate = !empty($user->rights->inventory->validate); + $view_url = dol_buildpath('/inventory/inventory.php', 1); + + $view = array( + 'mode' => $mode + ,'url' => dol_buildpath('/inventory/inventory.php', 1) + ,'can_validate' => (int) $user->rights->inventory->validate + ,'is_already_validate' => (int) $inventory->status + ,'token'=>$_SESSION['newtoken'] + ); + + include './tpl/inventory.tpl.php'; + + llxFooter(''); +} + + +function _card_line(&$inventory, &$lines, &$form) +{ + global $db; + $inventory->amount_actual = 0; + + $TCacheEntrepot = array(); + + foreach ($inventory->Inventorydet as $k => $Inventorydet) + { + + $product = & $Inventorydet->product; + $stock = $Inventorydet->qty_stock; + + $pmp = $Inventorydet->pmp; + $pmp_actual = $pmp * $stock; + $inventory->amount_actual+=$pmp_actual; + + $last_pa = $Inventorydet->pa; + $current_pa = $Inventorydet->current_pa; + + $e = new Entrepot($db); + if(!empty($TCacheEntrepot[$Inventorydet->fk_warehouse])) $e = $TCacheEntrepot[$Inventorydet->fk_warehouse]; + elseif($e->fetch($Inventorydet->fk_warehouse) > 0) $TCacheEntrepot[$e->id] = $e; + + $lines[]=array( + 'produit' => $product->getNomUrl(1).' - '.$product->label + ,'entrepot'=>$e->getNomUrl(1) + ,'barcode' => $product->barcode + /*,'qty' => $form->texte('', 'qty_to_add['.$k.']', (isset($_REQUEST['qty_to_add'][$k]) ? $_REQUEST['qty_to_add'][$k] : 0), 8, 0, "style='text-align:center;'") + .($form->type_aff!='view' ? ''.img_picto('Ajouter', 'plus16@inventory').'' : '') + ,'qty_view' => $Inventorydet->qty_view ? $Inventorydet->qty_view : 0 + ,'qty_stock' => $stock + ,'qty_regulated' => $Inventorydet->qty_regulated ? $Inventorydet->qty_regulated : 0 + ,'action' => $user->rights->inventory->write ? ''.img_picto($langs->trans('inventoryDeleteLine'), 'delete').'' : '' + ,'pmp_stock'=>round($pmp_actual,2) + ,'pmp_actual'=> round($pmp * $Inventorydet->qty_view,2) + ,'pmp_new'=>(!empty($user->rights->inventory->changePMP) ? $form->texte('', 'new_pmp['.$k.']',$Inventorydet->new_pmp, 8, 0, "style='text-align:right;'") + .($form->type_aff!='view' ? ''.img_picto($langs->trans('Save'), 'bt-save.png@inventory').'' : '') : '' ) + */,'pa_stock'=>round($last_pa * $stock,2) + ,'pa_actual'=>round($last_pa * $Inventorydet->qty_view,2) + ,'current_pa_stock'=>round($current_pa * $stock,2) + ,'current_pa_actual'=>round($current_pa * $Inventorydet->qty_view,2) + + ,'k'=>$k + ,'id'=>$Inventorydet->id + + ); + } + +} + +function exportCSV(&$inventory) { + global $conf; + + header('Content-Type: application/octet-stream'); + header('Content-disposition: attachment; filename=inventory-'. $inventory->getId().'-'.date('Ymd-His').'.csv'); + header('Pragma: no-cache'); + header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0'); + header('Expires: 0'); + + echo 'Ref;Label;barcode;qty theorique;PMP;dernier PA;'; + if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) echo 'PA courant;'; + echo 'qty réelle;PMP;dernier PA;'; + if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) echo 'PA courant;'; + echo 'qty regulée;'."\r\n"; + + foreach ($inventory->Inventorydet as $k => $Inventorydet) + { + $product = & $Inventorydet->product; + $stock = $Inventorydet->qty_stock; + + $pmp = $Inventorydet->pmp; + $pmp_actual = $pmp * $stock; + $inventory->amount_actual+=$pmp_actual; + + $last_pa = $Inventorydet->pa; + $current_pa = $Inventorydet->current_pa; + + if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) { + $row=array( + 'produit' => $product->ref + ,'label'=>$product->label + ,'barcode' => $product->barcode + ,'qty_stock' => $stock + ,'pmp_stock'=>round($pmp_actual,2) + ,'pa_stock'=>round($last_pa * $stock,2) + ,'current_pa_stock'=>round($current_pa * $stock,2) + ,'qty_view' => $Inventorydet->qty_view ? $Inventorydet->qty_view : 0 + ,'pmp_actual'=>round($pmp * $Inventorydet->qty_view,2) + ,'pa_actual'=>round($last_pa * $Inventorydet->qty_view,2) + ,'current_pa_actual'=>round($current_pa * $Inventorydet->qty_view,2) + ,'qty_regulated' => $Inventorydet->qty_regulated ? $Inventorydet->qty_regulated : 0 + + ); + + } + else{ + $row=array( + 'produit' => $product->ref + ,'label'=>$product->label + ,'barcode' => $product->barcode + ,'qty_stock' => $stock + ,'pmp_stock'=>round($pmp_actual,2) + ,'pa_stock'=>round($last_pa * $stock,2) + ,'qty_view' => $Inventorydet->qty_view ? $Inventorydet->qty_view : 0 + ,'pmp_actual'=>round($pmp * $Inventorydet->qty_view,2) + ,'pa_actual'=>round($last_pa * $Inventorydet->qty_view,2) + + ,'qty_regulated' => $Inventorydet->qty_regulated ? $Inventorydet->qty_regulated : 0 + + ); + + } + + + echo '"'.implode('";"', $row).'"'."\r\n"; + + } + + exit; +} + +function generateODT(&$PDOdb, &$db, &$conf, &$langs, &$inventory) +{ + $TBS=new TTemplateTBS(); + + $InventoryPrint = array(); // Tableau envoyé à la fonction render contenant les informations concernant l'inventaire + + foreach($inventory->Inventorydet as $k => $v) + { + $prod = new Product($db); + $prod->fetch($v->fk_product); + //$prod->fetch_optionals($prod->id); + + $InventoryPrint[] = array( + 'product' => $prod->ref.' - '.$prod->label + , 'qty_view' => $v->qty_view + ); + } + + $warehouse = new Entrepot($db); + $warehouse->fetch($inventory->fk_warehouse); + + $dirName = 'INVENTORY'.$inventory->getId().'('.date("d_m_Y").')'; + $dir = DOL_DATA_ROOT.'/inventory/'.$dirName.'/'; + + @mkdir($dir, 0777, true); + + $template = "templateINVENTORY.odt"; + //$template = "templateOF.doc"; + + $file_gen = $TBS->render(dol_buildpath('inventory/exempleTemplate/'.$template) + ,array( + 'InventoryPrint'=>$InventoryPrint + ) + ,array( + 'date_cre'=>$inventory->get_date('date_cre', 'd/m/Y') + ,'date_maj'=>$inventory->get_date('date_maj', 'd/m/Y H:i') + ,'date_inv'=>$inventory->get_date('date_inventory', 'd/m/Y') + ,'numero'=>empty($inventory->title) ? 'Inventaire n°'.$inventory->getId() : $inventory->title + ,'warehouse'=>$warehouse->libelle + ,'status'=>($inventory->status ? $langs->transnoentitiesnoconv('inventoryValidate') : $langs->transnoentitiesnoconv('inventoryDraft')) + ,'logo'=>DOL_DATA_ROOT."/mycompany/logos/".MAIN_INFO_SOCIETE_LOGO + ) + ,array() + ,array( + 'outFile'=>$dir.$inventory->getId().".odt" + ,"convertToPDF"=>(!empty($conf->global->INVENTORY_GEN_PDF) ? true : false) + ,'charset'=>OPENTBS_ALREADY_UTF8 + + ) + + ); + + header("Location: ".DOL_URL_ROOT."/document.php?modulepart=inventory&entity=".$conf->entity."&file=".$dirName."/".$inventory->getId(). (!empty($conf->global->INVENTORY_GEN_PDF) ? '.pdf' : '.odt') ); + + /* + $size = filesize("./" . basename($file_gen)); + header("Content-Type: application/force-download; name=\"" . basename($file_gen) . "\""); + header("Content-Transfer-Encoding: binary"); + header("Content-Length: $size"); + header("Content-Disposition: attachment; filename=\"" . basename($file_gen) . "\""); + header("Expires: 0"); + header("Cache-Control: no-cache, must-revalidate"); + header("Pragma: no-cache"); + + readfile($file_gen); + */ + + //header("Location: ".DOL_URL_ROOT."/document.php?modulepart=asset&entity=1&file=".$dirName."/".$assetOf->numero.".doc"); + +} +function _footerList($view,$total_pmp,$total_pmp_actual,$total_pa,$total_pa_actual, $total_current_pa,$total_current_pa_actual) { + global $conf,$user,$langs; + + + if ($view['can_validate'] == 1) { ?> + +   + barcode->enabled)) { ?> +   + + + + global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ + echo ''.price($total_current_pa).''; + } + ?> +   + + rights->inventory->changePMP)) { + echo ' '; + } + ?> + + global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ + echo ''.price($total_current_pa_actual).''; + } + ?> + +   + +   + + + + +   Produit + Entrepôt + barcode->enabled)) { ?> + Code-barre + + + Quantité théorique + global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ + echo 'Valeur théorique'; + } + else { + echo 'Valeur théorique'; + } + + ?> + + + Quantité réelle + + + global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) $colspan++; + if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) $colspan++; + + echo 'Valeur réelle'; + + ?> + + Quantité régulée + + + # + + + + + +   + PMP + Dernier PA + global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ + echo 'PA courant'; + } + + ?> +   + PMP + rights->inventory->changePMP)) { + echo ''.$langs->trans('ColumnNewPMP').''; + } + ?> + Dernier PA + global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ + echo 'PA courant'; + } + + ?> +   + +   + + + + * Copyright (C) 2015 ATM Consulting + * + * 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 lib/inventory.lib.php + * \ingroup inventory + * \brief This file is an example module library + * Put some comments here + */ + +function inventoryAdminPrepareHead() +{ + global $langs, $conf; + + $langs->load("inventory@inventory"); + + $h = 0; + $head = array(); + + $head[$h][0] = dol_buildpath("/inventory/admin/inventory_setup.php", 1); + $head[$h][1] = $langs->trans("Parameters"); + $head[$h][2] = 'settings'; + $h++; + $head[$h][0] = dol_buildpath("/inventory/admin/inventory_about.php", 1); + $head[$h][1] = $langs->trans("About"); + $head[$h][2] = 'about'; + $h++; + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + //$this->tabs = array( + // 'entity:+tabname:Title:@inventory:/inventory/mypage.php?id=__ID__' + //); // to add new tab + //$this->tabs = array( + // 'entity:-tabname:Title:@inventory:/inventory/mypage.php?id=__ID__' + //); // to remove a tab + complete_head_from_modules($conf, $langs, $object, $head, $h, 'inventory'); + + return $head; +} + +function inventoryPrepareHead(&$inventory, $title='Inventaire', $get='') +{ + return array( + array(dol_buildpath('/inventory/inventory.php?id='.$inventory->id.$get, 1), $title,'inventaire') + ); +} + + + +function inventorySelectProducts(&$inventory) +{ + global $conf,$db; + + $except_product_id = array(); + + foreach ($inventory->Inventorydet as $Inventorydet) + { + $except_product_id[] = $Inventorydet->fk_product; + } + + ob_start(); + $form = new Form($db); + $form->select_produits(-1, 'fk_product'); + + // Il nous faut impérativement une liste custom car il ne faut que les entrepôts de la famille de celui qu'on inventorie + $TChildWarehouses = array($inventory->fk_warehouse); + $e = new Entrepot($db); + $e->fetch($inventory->fk_warehouse); + if(method_exists($e, 'get_children_warehouses')) $e->get_children_warehouses($e->id, $TChildWarehouses); + + $Tab = array(); + $sql = 'SELECT rowid, label + FROM '.MAIN_DB_PREFIX.'entrepot WHERE rowid IN('.implode(', ', $TChildWarehouses).')'; + if(method_exists($e, 'get_children_warehouses')) $sql.= ' ORDER BY fk_parent'; + $resql = $db->query($sql); + while($res = $db->fetch_object($resql)) { + $Tab[$res->rowid] = $res->label; + } + print '   '; + print 'Entrepôt : '.$form::selectarray('fk_warehouse', $Tab); + + $select_html = ob_get_clean(); + + return $select_html; +} + +function ajaxAutocompleter($selected, $htmlname, $url, $urloption='', $minLength=2, $autoselect=0, $ajaxoptions=array()) +{ + if (empty($minLength)) $minLength=1; + + $script = ''; + + $script.= ''; + + return $script; +} diff --git a/htdocs/inventory/tpl/inventory.tpl.php b/htdocs/inventory/tpl/inventory.tpl.php new file mode 100644 index 00000000000..d7022245f5b --- /dev/null +++ b/htdocs/inventory/tpl/inventory.tpl.php @@ -0,0 +1,211 @@ + + +status != 1) { ?> + trans('AddInventoryProduct'); ?> : +
    + + + + + + +
    + + +
    + + +
    Cet inventaire est validé
    + + + + + + + $row) { + + $total_pmp+=$row['pmp_stock']; + $total_pa+=$row['pa_stock']; + $total_pmp_actual+=$row['pmp_actual']; + $total_pa_actual+=$row['pa_actual']; + + if($i%20 === 0) + { + _headerList($view); + } // Fin IF principal + ?> + + + + barcode->enabled)) { ?> + + + + + + + global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ + echo ''; + $total_current_pa+=$row['current_pa_stock']; + } + + ?> + + + + + rights->inventory->changePMP)) { + echo ''; + } + ?> + + global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ + echo ''; + $total_current_pa_actual+=$row['current_pa_actual']; + } + + ?> + + + + + + + + + + + + +
      '.price($row['current_pa_stock']).'   + + '.$row['pmp_new'].''.price($row['current_pa_actual']).'
    + + +
    + + trans('Print') ?> + trans('ExportCSV') ?> + trans('Modify') ?> + rights->inventory->changePMP)) { + echo ''.$langs->trans('ApplyPMP').''; + } + + if ($can_validate == 1) { ?> + Réguler le stock + + + + + + + Vider +     + Supprimer + +
    + + + + +
    +

    Date de création : get_date('datec') ?> +
    Dernière mise à jour : get_date('tms') ?>

    + + +