Merge pull request #6584 from atm-ph/NEW_inventory_coreobject_listview

New inventory coreobject listview
This commit is contained in:
Laurent Destailleur 2017-04-29 21:31:46 +02:00 committed by GitHub
commit f5bdfc426f
22 changed files with 4466 additions and 0 deletions

152
htdocs/admin/inventory.php Normal file
View File

@ -0,0 +1,152 @@
<?php
/* <one line to give the program's name and a brief idea of what it does.>
* Copyright (C) 2015 ATM Consulting <support@atm-consulting.fr>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**
* \file admin/inventory.php
* \ingroup inventory
* \brief This file is an example module setup page
* Put some comments here
*/
// Dolibarr environment
require '../main.inc.php';
// Libraries
require_once DOL_DOCUMENT_ROOT . "/core/lib/admin.lib.php";
require_once DOL_DOCUMENT_ROOT .'/inventory/lib/inventory.lib.php';
// Translations
$langs->load("stock");
$langs->load("inventory");
// Access control
if (! $user->admin) {
accessforbidden();
}
// Parameters
$action = GETPOST('action', 'alpha');
/*
* Actions
*/
if (preg_match('/set_(.*)/',$action,$reg))
{
$code=$reg[1];
if (dolibarr_set_const($db, $code, GETPOST($code), 'chaine', 0, '', $conf->entity) > 0)
{
header("Location: ".$_SERVER["PHP_SELF"]);
exit;
}
else
{
dol_print_error($db);
}
}
if (preg_match('/del_(.*)/',$action,$reg))
{
$code=$reg[1];
if (dolibarr_del_const($db, $code, 0) > 0)
{
Header("Location: ".$_SERVER["PHP_SELF"]);
exit;
}
else
{
dol_print_error($db);
}
}
/*
* View
*/
$page_name = "inventorySetup";
llxHeader('', $langs->trans($page_name));
// Subheader
$linkback = '<a href="' . DOL_URL_ROOT . '/admin/modules.php">'
. $langs->trans("BackToModuleList") . '</a>';
print_fiche_titre($langs->trans($page_name), $linkback);
// Configuration header
$head = inventoryAdminPrepareHead();
dol_fiche_head(
$head,
'settings',
$langs->trans("Module104420Name"),
0,
"inventory@inventory"
);
// Setup page goes here
$form=new Form($db);
$var=false;
print '<table class="noborder" width="100%">';
print '<tr class="liste_titre">';
print '<td>'.$langs->trans("Parameters").'</td>'."\n";
print '<td align="center" width="20">&nbsp;</td>';
print '<td align="center" width="100">'.$langs->trans("Value").'</td>'."\n";
// Example with a yes / no select
$var=!$var;
print '<tr '.$bc[$var].'>';
print '<td>'.$langs->trans("INVENTORY_DISABLE_VIRTUAL").'</td>';
print '<td align="center" width="20">&nbsp;</td>';
print '<td align="right" width="300">';
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
print '<input type="hidden" name="action" value="set_INVENTORY_DISABLE_VIRTUAL">';
print $form->selectyesno("INVENTORY_DISABLE_VIRTUAL",$conf->global->INVENTORY_DISABLE_VIRTUAL,1);
print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
print '</form>';
print '</td></tr>';
// Example with a yes / no select
$var=!$var;
print '<tr '.$bc[$var].'>';
print '<td>'.$langs->trans("INVENTORY_USE_MIN_PA_IF_NO_LAST_PA").'</td>';
print '<td align="center" width="20">&nbsp;</td>';
print '<td align="right" width="300">';
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
print '<input type="hidden" name="action" value="set_INVENTORY_USE_MIN_PA_IF_NO_LAST_PA">';
print $form->selectyesno("INVENTORY_USE_MIN_PA_IF_NO_LAST_PA",$conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA,1);
print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
print '</form>';
print '</td></tr>';
// Example with a yes / no select
$var=!$var;
print '<tr '.$bc[$var].'>';
print '<td>'.$langs->trans("INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT").'</td>';
print '<td align="center" width="20">&nbsp;</td>';
print '<td align="right" width="300">';
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
print '<input type="hidden" name="action" value="set_INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT">';
print $form->selectyesno("INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT",$conf->global->INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT,1);
print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
print '</form>';
print '</td></tr>';
print '</table>';
llxFooter();
$db->close();

View File

@ -0,0 +1,673 @@
<?php
/* EXPERIMENTAL
*
* Copyright (C) 2016 ATM Consulting <support@atm-consulting.fr>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/core/class/coreobject.inventory.php
* \ingroup core
* \brief File of class to manage all object. Might be replace or merge into commonobject
*/
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
class CoreObject extends CommonObject
{
public $withChild = true;
/**
* @var Array $_fields Fields to synchronize with Database
*/
protected $__fields=array();
/**
* Constructor
*
* @param DoliDB $db Database handler
*/
function __construct(DoliDB &$db)
{
$this->db = $db;
}
/**
* Function to init fields
*
* @return bool
*/
protected function init()
{
$this->id = 0;
$this->datec = 0;
$this->tms = 0;
if (!empty($this->__fields))
{
foreach ($this->__fields as $field=>$info)
{
if ($this->is_date($info)) $this->{$field} = time();
elseif ($this->is_array($info)) $this->{$field} = array();
elseif ($this->is_int($info)) $this->{$field} = (int) 0;
elseif ($this->is_float($info)) $this->{$field} = (double) 0;
else $this->{$field} = '';
}
$this->to_delete=false;
$this->is_clone=false;
return true;
}
else
{
return false;
}
}
/**
* Test type of field
*
* @param string $field name of field
* @param string $type type of field to test
* @return value of field or false
*/
private function checkFieldType($field, $type)
{
if (isset($this->__fields[$field]) && method_exists($this, 'is_'.$type))
{
return $this->{'is_'.$type}($this->__fields[$field]);
}
else
{
return false;
}
}
/**
* Function test if type is date
*
* @param array $info content informations of field
* @return bool
*/
private function is_date($info)
{
if(isset($info['type']) && $info['type']=='date') return true;
else return false;
}
/**
* Function test if type is array
*
* @param array $info content informations of field
* @return bool
*/
private function is_array($info)
{
if(is_array($info))
{
if(isset($info['type']) && $info['type']=='array') return true;
else return false;
}
else return false;
}
/**
* Function test if type is null
*
* @param array $info content informations of field
* @return bool
*/
private function is_null($info)
{
if(is_array($info))
{
if(isset($info['type']) && $info['type']=='null') return true;
else return false;
}
else return false;
}
/**
* Function test if type is integer
*
* @param array $info content informations of field
* @return bool
*/
private function is_int($info)
{
if(is_array($info))
{
if(isset($info['type']) && ($info['type']=='int' || $info['type']=='integer' )) return true;
else return false;
}
else return false;
}
/**
* Function test if type is float
*
* @param array $info content informations of field
* @return bool
*/
private function is_float($info)
{
if(is_array($info))
{
if(isset($info['type']) && $info['type']=='float') return true;
else return false;
}
else return false;
}
/**
* Function test if type is text
*
* @param array $info content informations of field
* @return bool
*/
private function is_text($info)
{
if(is_array($info))
{
if(isset($info['type']) && $info['type']=='text') return true;
else return false;
}
else return false;
}
/**
* Function test if is indexed
*
* @param array $info content informations of field
* @return bool
*/
private function is_index($info)
{
if(is_array($info))
{
if(isset($info['index']) && $info['index']==true) return true;
else return false;
}
else return false;
}
/**
* Function to prepare the values to insert
*
* @return array
*/
private function set_save_query()
{
$query=array();
foreach ($this->__fields as $field=>$info)
{
if($this->is_date($info))
{
if(empty($this->{$field}))
{
$query[$field] = NULL;
}
else
{
$query[$field] = $this->db->idate($this->{$field});
}
}
else if($this->is_array($info))
{
$query[$field] = serialize($this->{$field});
}
else if($this->is_int($info))
{
$query[$field] = (int) price2num($this->{$field});
}
else if($this->is_float($info))
{
$query[$field] = (double) price2num($this->{$field});
}
elseif($this->is_null($info))
{
$query[$field] = (is_null($this->{$field}) || (empty($this->{$field}) && $this->{$field}!==0 && $this->{$field}!=='0') ? null : $this->{$field});
}
else
{
$query[$field] = $this->{$field};
}
}
return $query;
}
/**
* Function to concat keys of fields
*
* @return string
*/
private function get_field_list()
{
$keys = array_keys($this->__fields);
return implode(',', $keys);
}
/**
* Function to load data into current object this
*
* @param stdClass $obj Contain data of object from database
*/
private function set_vars_by_db(&$obj)
{
foreach ($this->__fields as $field => $info)
{
if($this->is_date($info))
{
if(empty($obj->{$field}) || $obj->{$field} === '0000-00-00 00:00:00' || $obj->{$field} === '1000-01-01 00:00:00') $this->{$field} = 0;
else $this->{$field} = strtotime($obj->{$field});
}
elseif($this->is_array($info))
{
$this->{$field} = @unserialize($obj->{$field});
// Hack for data not in UTF8
if($this->{$field } === FALSE) @unserialize(utf8_decode($obj->{$field}));
}
elseif($this->is_int($info))
{
$this->{$field} = (int) $obj->{$field};
}
elseif($this->is_float($info))
{
$this->{$field} = (double) $obj->{$field};
}
elseif($this->is_null($info))
{
$val = $obj->{$field};
// zero is not null
$this->{$field} = (is_null($val) || (empty($val) && $val!==0 && $val!=='0') ? null : $val);
}
else
{
$this->{$field} = $obj->{$field};
}
}
}
/**
* Get object and children from database
*
* @param int $id Id of object to load
* @param bool $loadChild used to load children from database
* @return int >0 if OK, <0 if KO, 0 if not found
*/
public function fetch($id, $loadChild = true)
{
if (empty($id)) return false;
$sql = 'SELECT '.$this->get_field_list().', datec, tms';
$sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element;
$sql.= ' WHERE rowid = '.$id;
$res = $this->db->query($sql);
if($obj = $this->db->fetch_object($res))
{
$this->id = $id;
$this->set_vars_by_db($obj);
$this->datec = $this->db->idate($obj->datec);
$this->tms = $this->db->idate($obj->tms);
if ($loadChild) $this->fetchChild();
return $this->id;
}
else
{
$this->error = $this->db->lasterror();
$this->errors[] = $this->error;
return -1;
}
}
/**
* Function to instantiate a new child
*
* @param string $tabName Table name of child
* @param int $id If id is given, we try to return his key if exist or load if we try_to_load
* @param string $key Attribute name of the object id
* @param bool $try_to_load Force the fetch if an id is given
* @return int
*/
public function addChild($tabName, $id=0, $key='id', $try_to_load = false)
{
if(!empty($id))
{
foreach($this->{$tabName} as $k=>&$object)
{
if($object->{$key} === $id) return $k;
}
}
$k = count($this->{$tabName});
$className = ucfirst($tabName);
$this->{$tabName}[$k] = new $className($this->db);
if($id>0 && $key==='id' && $try_to_load)
{
$this->{$tabName}[$k]->fetch($id);
}
return $k;
}
/**
* Function to set a child as to delete
*
* @param string $tabName Table name of child
* @param int $id Id of child to set as to delete
* @param string $key Attribute name of the object id
* @return bool
*/
public function removeChild($tabName, $id, $key='id')
{
foreach ($this->{$tabName} as &$object)
{
if ($object->{$key} == $id)
{
$object->to_delete = true;
return true;
}
}
return false;
}
/**
* Function to fetch children objects
*/
public function fetchChild()
{
if($this->withChild && !empty($this->childtables) && !empty($this->fk_element))
{
foreach($this->childtables as &$childTable)
{
$className = ucfirst($childTable);
$this->{$className}=array();
$sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.$childTable.' WHERE '.$this->fk_element.' = '.$this->id;
$res = $this->db->query($sql);
if($res)
{
while($obj = $this->db->fetch_object($res))
{
$o=new $className($this->db);
$o->fetch($obj->rowid);
$this->{$className}[] = $o;
}
}
else
{
$this->errors[] = $this->db->lasterror();
}
}
}
}
/**
* Function to update children data
*
* @param User $user user object
*/
public function saveChild(User &$user)
{
if($this->withChild && !empty($this->childtables) && !empty($this->fk_element))
{
foreach($this->childtables as &$childTable)
{
$className = ucfirst($childTable);
if(!empty($this->{$className}))
{
foreach($this->{$className} as $i => &$object)
{
$object->{$this->fk_element} = $this->id;
$object->update($user);
if($this->unsetChildDeleted && isset($object->to_delete) && $object->to_delete==true) unset($this->{$className}[$i]);
}
}
}
}
}
/**
* Function to update object or create or delete if needed
*
* @param User $user user object
* @return < 0 if ko, > 0 if ok
*/
public function update(User &$user)
{
if (empty($this->id)) return $this->create($user); // To test, with that, no need to test on high level object, the core decide it, update just needed
elseif (isset($this->to_delete) && $this->to_delete==true) return $this->delete($user);
$error = 0;
$this->db->begin();
$query = $this->set_save_query();
$query['rowid'] = $this->id;
$res = $this->db->update($this->table_element, $query, array('rowid'));
if ($res)
{
$result = $this->call_trigger(strtoupper($this->element). '_UPDATE', $user);
if ($result < 0) $error++;
else $this->saveChild($user);
}
else
{
$error++;
$this->error = $this->db->lasterror();
$this->errors[] = $this->error;
}
if (empty($error))
{
$this->db->commit();
return $this->id;
}
else
{
$this->db->rollback();
return -1;
}
}
/**
* Function to create object in database
*
* @param User $user user object
* @return < 0 if ko, > 0 if ok
*/
public function create(User &$user)
{
if($this->id > 0) return $this->update($user);
$error = 0;
$this->db->begin();
$query = $this->set_save_query();
$query['datec'] = date("Y-m-d H:i:s", dol_now());
$res = $this->db->insert($this->table_element, $query);
if($res)
{
$this->id = $this->db->last_insert_id($this->table_element);
$result = $this->call_trigger(strtoupper($this->element). '_CREATE', $user);
if ($result < 0) $error++;
else $this->saveChild($user);
}
else
{
$error++;
$this->error = $this->db->lasterror();
$this->errors[] = $this->error;
}
if (empty($error))
{
$this->db->commit();
return $this->id;
}
else
{
$this->db->rollback();
return -1;
}
}
/**
* Function to delete object in database
*
* @param User $user user object
* @return < 0 if ko, > 0 if ok
*/
public function delete(User &$user)
{
if ($this->id <= 0) return 0;
$error = 0;
$this->db->begin();
$result = $this->call_trigger(strtoupper($this->element). '_DELETE', $user);
if ($result < 0) $error++;
if (!$error)
{
$this->db->delete($this->table_element, array('rowid' => $this->id), array('rowid'));
if($this->withChild && !empty($this->childtables))
{
foreach($this->childtables as &$childTable)
{
$className = ucfirst($childTable);
if (!empty($this->{$className}))
{
foreach($this->{$className} as &$object)
{
$object->delete($user);
}
}
}
}
}
if (empty($error))
{
$this->db->commit();
return 1;
}
else
{
$this->error = $this->db->lasterror();
$this->errors[] = $this->error;
$this->db->rollback();
return -1;
}
}
/**
* Function to get a formatted date
*
* @param string $field Attribute to return
* @param string $format Output date format
* @return string
*/
public function getDate($field, $format='')
{
if(empty($this->{$field})) return '';
else
{
return dol_print_date($this->{$field}, $format);
}
}
/**
* Function to set date in field
*
* @param string $field field to set
* @param string $date formatted date to convert
* @return mixed
*/
public function setDate($field, $date)
{
if (empty($date))
{
$this->{$field} = 0;
}
else
{
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
$this->{$field} = dol_stringtotime($date);
}
return $this->{$field};
}
/**
* Function to update current object
*
* @param array $Tab Array of values
* @return int
*/
public function setValues(&$Tab)
{
foreach ($Tab as $key => $value)
{
if($this->checkFieldType($key, 'date'))
{
$this->setDate($key, $value);
}
else if( $this->checkFieldType($key, 'array'))
{
$this->{$key} = $value;
}
else if( $this->checkFieldType($key, 'float') )
{
$this->{$key} = (double) price2num($value);
}
else if( $this->checkFieldType($key, 'int') ) {
$this->{$key} = (int) price2num($value);
}
else
{
$this->{$key} = @stripslashes($value);
}
}
return 1;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -295,5 +295,122 @@ abstract class DoliDB implements Database
{
return $this->lastqueryerror;
}
/*
* Add quote to field value if necessary
*
* @param string|int $value value to protect
* @return string|int
*/
function quote($value) {
if(is_null($value)) return 'NULL';
else if(is_numeric($value)) return $value;
else return "'".$this->escape( $value )."'";
}
/**
* Generate and execute Update SQL commande
*
* @param string $table table to update
* @param array $values array of values to update
* @param int|string|array $key key of value to select row to update
* @return bool|result false or boolean
*/
function update($table,$fields,$key){
foreach ($fields as $k => $v) {
if (is_array($key)){
$i=array_search($k , $key );
if ( $i !== false) {
$where[] = $key[$i].'=' . $this->quote( $v ) ;
continue;
}
} else {
if ( $k == $key) {
$where[] = $k.'=' .$this->quote( $v ) ;
continue;
}
}
$tmp[] = $k.'='.$this->quote($v);
}
$sql = 'UPDATE '.MAIN_DB_PREFIX.$table.' SET '.implode( ',', $tmp ).' WHERE ' . implode(' AND ',$where) ;
$res = $this->query( $sql );
if($res===false) {
//error
return false;
}
return true;
}
/**
* Generate and execute Insert SQL commande
*
* @param string $table table to update
* @param array $values array of values to update
* @return bool|result false or boolean
*/
function insert($table,$fields){
foreach ($fields as $k => $v) {
$keys[] = $k;
$values[] = $this->quote($v);
}
$sql = 'INSERT INTO '.MAIN_DB_PREFIX.$table.'
( '.implode( ",", $keys ).' )
VALUES ( '.implode( ",", $values ).' ) ';
$res = $this->query($sql);
if($res===false) {
return false;
}
return true;
}
/**
* Generate and execute Delete SQL commande
*
* @param string $table table for the delete
* @param array $values array of values to delete
* @param int|string|array $key key of value to select row to update
* @return bool|result false or boolean
*/
function delete($table,$fields,$key){
foreach ($fields as $k => $v) {
if (is_array($key)){
$i=array_search($k , $key );
if ( $i !== false) {
$where[] = $key[$i].'=' . $this->quote( $v ) ;
continue;
}
} else {
if ( $k == $key) {
$where[] = $k.'='.$this->quote( $v ) ;
continue;
}
}
}
$sql = 'DELETE FROM '.MAIN_DB_PREFIX.$table.' WHERE '.implode(' AND ',$where);
$res = $this->query( $sql );
if($res===false) {
return false;
}
return true;
}
}

146
htdocs/core/js/listview.js Normal file
View File

@ -0,0 +1,146 @@
var Listview_include = true;
function Listview_OrderDown(idListe, column) {
var base_url = document.location.href;
base_url = Listview_recup_form_param(idListe,base_url);
base_url = Listview_removeParam(base_url,'Listview['+encodeURIComponent(idListe)+'][orderBy]');
base_url = Listview_removeParam(base_url,'get-all-for-export');
document.location.href=Listview_modifyUrl(base_url,"Listview["+encodeURIComponent(idListe)+"][orderBy]["+encodeURIComponent(column)+"]","DESC");
}
function Listview_OrderUp(idListe, column) {
var base_url = document.location.href;
base_url = Listview_recup_form_param(idListe,base_url);
base_url = Listview_removeParam(base_url,'Listview['+encodeURIComponent(idListe)+'][orderBy]');
base_url = Listview_removeParam(base_url,'get-all-for-export');
document.location.href=Listview_modifyUrl(base_url,"Listview["+encodeURIComponent(idListe)+"][orderBy]["+encodeURIComponent(column)+"]","ASC");
}
function Listview_modifyUrl(strURL,paramName,paramNewValue){
if (strURL.indexOf(paramName+'=')!=-1){
var strFirstPart=strURL.substring(0,strURL.indexOf(paramName+'=',0))+paramName+'=';
var strLastPart="";
if (strURL.indexOf('&',strFirstPart.length-1)>0)
strLastPart=strURL.substring(strURL.indexOf('&',strFirstPart.length-1),strURL.length);
strURL=strFirstPart+paramNewValue+strLastPart;
}
else{
if (strURL.search('=')!=-1) // permet de verifier s'il y a dej<65> des param<61>tres dans l'URL
strURL+='&'+paramName+'='+paramNewValue;
else
strURL+='?'+paramName+'='+paramNewValue;
}
return strURL;
}
function Listview_removeParam(strURL, paramMask) {
var cpt=0;
var url = '';
while(strURL.indexOf(paramMask)!=-1 && cpt++ <50){
var strFirstPart= strURL.substring(0,strURL.indexOf(paramMask)-1);
var strLastPart='';
if (strURL.indexOf('&',strFirstPart.length+1)>0) {
strLastPart = strURL.substring(strURL.indexOf('&',strFirstPart.length+1),strURL.length);
}
url = strFirstPart+strLastPart;
}
if(url=='')url = strURL;
return url;
}
function Listview_recup_form_param(idListe,base_url) {
$('#'+idListe+' tr.barre-recherche [listviewtbs],#'+idListe+' tr.barre-recherche-head input,#'+idListe+' tr.barre-recherche-head select,#'+idListe+' div.tabsAction input[listviewtbs]').each(function(i,item) {
if($(item).attr("name")) {
base_url = Listview_modifyUrl(base_url, $(item).attr("name") , $(item).val());
}
});
return base_url;
}
function Listview_GoToPage(idListe,pageNumber){
var base_url = document.location.href;
base_url = Listview_recup_form_param(idListe,base_url);
base_url =Listview_modifyUrl(base_url,"Listview["+encodeURIComponent(idListe)+"][page]",pageNumber);
base_url = Listview_removeParam(base_url,'get-all-for-export');
document.location.href=base_url;
}
function Listview_submitSearch(obj) {
$form = $(obj).closest('form');
console.log($form);
if($form.length>0){
$form.submit();
}
}
function Listview_launch_downloadAs(mode,url,token,session_name) {
$('#listviewdAS_export_form').remove();
$form = $('<form action="'+url+'" method="post" name="listviewdAS_export_form" id="listTBSdAS_export_form"></form>');
$form.append('<input type="hidden" name="mode" value="'+mode+'" />');
$form.append('<input type="hidden" name="token" value="'+token+'" />');
$form.append('<input type="hidden" name="session_name" value="'+session_name+'" />');
$('body').append($form);
$('#listviewdAS_export_form').submit();
}
function Listview_downloadAs(obj, mode,url,token,session_name) {
$form = $(obj).closest('form');
$div = $form.find('div.tabsAction');
$div.append('<input type="hidden" listviewtbs="hidden" name="token" value="'+token+'" />');
$div.append('<input type="hidden" listviewtbs="hidden" name="mode" value="'+mode+'" />');
$div.append('<input type="hidden" listviewtbs="hidden" name="url" value="'+url+'" />');
$div.append('<input type="hidden" listviewtbs="hidden" name="session_name" value="'+session_name+'" />');
$div.append('<input type="hidden" listviewtbs="hidden" name="get-all-for-export" value="1" />');
Listview_submitSearch(obj);
}
$(document).ready(function() {
$('tr.barre-recherche input').keypress(function(e) {
if(e.which == 13) {
var id_list = $(this).closest('table').attr('id');
$('#'+id_list+' .list-search-link').click();
}
});
var $_GET = {};
document.location.search.replace(/\??(?:([^=]+)=([^&]*)&?)/g, function () {
function decode(s) {
return decodeURIComponent(s.split("+").join(" "));
}
$_GET[decode(arguments[1])] = decode(arguments[2]);
});
if(typeof $_GET["get-all-for-export"] != "undefined") {
Listview_launch_downloadAs($_GET['mode'],$_GET['url'],$_GET['token'],$_GET['session_name']);
}
});

View File

@ -0,0 +1,316 @@
<?php
/* Copyright (C) 2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**
* \defgroup inventory Module inventory
* \brief Example of a module descriptor.
* Such a file must be copied into htdocs/inventory/core/modules directory.
* \file htdocs/inventory/core/modules/modinventory.class.php
* \ingroup inventory
* \brief Description and activation file for module inventory
*/
include_once DOL_DOCUMENT_ROOT .'/core/modules/DolibarrModules.class.php';
/**
* Description and activation class for module inventory
*/
class modinventory extends DolibarrModules
{
/**
* Constructor. Define names, constants, directories, boxes, permissions
*
* @param DoliDB $db Database handler
*/
function __construct($db)
{
global $langs,$conf;
$this->db = $db;
// Id for module (must be unique).
// Use here a free id (See in Home -> System information -> Dolibarr for list of used modules id).
$this->numero = 104420; // 104000 to 104999 for ATM CONSULTING
// Key text used to identify module (for permissions, menus, etc...)
$this->rights_class = 'inventory';
// Family can be 'crm','financial','hr','projects','products','ecm','technic','other'
// It is used to group modules in module setup page
$this->family = "products";
// Module label (no space allowed), used if translation string 'ModuleXXXName' not found (where XXX is value of numeric property 'numero' of module)
$this->name = preg_replace('/^mod/i','',get_class($this));
// Module description, used if translation string 'ModuleXXXDesc' not found (where XXX is value of numeric property 'numero' of module)
$this->description = "Description of module inventory";
// Possible values for version are: 'development', 'experimental', 'dolibarr' or version
$this->version = 'dolibarr';
// Key used in llx_const table to save module status enabled/disabled (where MYMODULE is value of property name of module in uppercase)
$this->const_name = 'MAIN_MODULE_'.strtoupper($this->name);
// Where to store the module in setup page (0=common,1=interface,2=others,3=very specific)
$this->special = 0;
// Name of image file used for this module.
// If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue'
// If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module'
$this->picto='inventory';
// Defined all module parts (triggers, login, substitutions, menus, css, etc...)
// for default path (eg: /inventory/core/xxxxx) (0=disable, 1=enable)
// for specific path of parts (eg: /inventory/core/modules/barcode)
// for specific css file (eg: /inventory/css/inventory.css.php)
//$this->module_parts = array(
// 'triggers' => 0, // Set this to 1 if module has its own trigger directory (core/triggers)
// 'login' => 0, // Set this to 1 if module has its own login method directory (core/login)
// 'substitutions' => 0, // Set this to 1 if module has its own substitution function file (core/substitutions)
// 'menus' => 0, // Set this to 1 if module has its own menus handler directory (core/menus)
// 'theme' => 0, // Set this to 1 if module has its own theme directory (theme)
// 'tpl' => 0, // Set this to 1 if module overwrite template dir (core/tpl)
// 'barcode' => 0, // Set this to 1 if module has its own barcode directory (core/modules/barcode)
// 'models' => 0, // Set this to 1 if module has its own models directory (core/modules/xxx)
// 'css' => array('/inventory/css/inventory.css.php'), // Set this to relative path of css file if module has its own css file
// 'js' => array('/inventory/js/inventory.js'), // Set this to relative path of js file if module must load a js on all pages
// 'hooks' => array('hookcontext1','hookcontext2') // Set here all hooks context managed by module
// 'dir' => array('output' => 'othermodulename'), // To force the default directories names
// 'workflow' => array('WORKFLOW_MODULE1_YOURACTIONTYPE_MODULE2'=>array('enabled'=>'! empty($conf->module1->enabled) && ! empty($conf->module2->enabled)', 'picto'=>'yourpicto@inventory')) // Set here all workflow context managed by module
// );
$this->module_parts = array();
// Data directories to create when module is enabled.
// Example: this->dirs = array("/inventory/temp");
$this->dirs = array();
// Config pages. Put here list of php page, stored into inventory/admin directory, to use to setup module.
$this->config_page_url = array("inventory.php");
// Dependencies
$this->hidden = false; // A condition to hide module
$this->depends = array('modStock'); // List of modules id that must be enabled if this module is enabled
$this->requiredby = array(); // List of modules id to disable if this one is disabled
$this->conflictwith = array(); // List of modules id this module is in conflict with
$this->phpmin = array(5,0); // Minimum version of PHP required by module
$this->need_dolibarr_version = array(3,0); // Minimum version of Dolibarr required by module
$this->langfiles = array("inventory");
// Constants
// List of particular constants to add when module is enabled (key, 'chaine', value, desc, visible, 'current' or 'allentities', deleteonunactive)
// Example: $this->const=array(0=>array('MYMODULE_MYNEWCONST1','chaine','myvalue','This is a constant to add',1),
// 1=>array('MYMODULE_MYNEWCONST2','chaine','myvalue','This is another constant to add',0, 'current', 1)
// );
$this->const = array();
// Array to add new pages in new tabs
// Example: $this->tabs = array('objecttype:+tabname1:Title1:mylangfile@inventory:$user->rights->inventory->read:/inventory/mynewtab1.php?id=__ID__', // To add a new tab identified by code tabname1
// 'objecttype:+tabname2:Title2:mylangfile@inventory:$user->rights->othermodule->read:/inventory/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2
// 'objecttype:-tabname:NU:conditiontoremove'); // To remove an existing tab identified by code tabname
// where objecttype can be
// 'categories_x' to add a tab in category view (replace 'x' by type of category (0=product, 1=supplier, 2=customer, 3=member)
// 'contact' to add a tab in contact view
// 'contract' to add a tab in contract view
// 'group' to add a tab in group view
// 'intervention' to add a tab in intervention view
// 'invoice' to add a tab in customer invoice view
// 'invoice_supplier' to add a tab in supplier invoice view
// 'member' to add a tab in fundation member view
// 'opensurveypoll' to add a tab in opensurvey poll view
// 'order' to add a tab in customer order view
// 'order_supplier' to add a tab in supplier order view
// 'payment' to add a tab in payment view
// 'payment_supplier' to add a tab in supplier payment view
// 'product' to add a tab in product view
// 'propal' to add a tab in propal view
// 'project' to add a tab in project view
// 'stock' to add a tab in stock view
// 'thirdparty' to add a tab in third party view
// 'user' to add a tab in user view
$this->tabs = array();
// Dictionaries
if (! isset($conf->inventory->enabled))
{
$conf->inventory=new stdClass();
$conf->inventory->enabled=0;
}
$this->dictionaries=array();
/* Example:
if (! isset($conf->inventory->enabled)) $conf->inventory->enabled=0; // This is to avoid warnings
$this->dictionaries=array(
'langs'=>'mylangfile@inventory',
'tabname'=>array(MAIN_DB_PREFIX."table1",MAIN_DB_PREFIX."table2",MAIN_DB_PREFIX."table3"), // List of tables we want to see into dictonnary editor
'tablib'=>array("Table1","Table2","Table3"), // Label of tables
'tabsql'=>array('SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table1 as f','SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table2 as f','SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table3 as f'), // Request to select fields
'tabsqlsort'=>array("label ASC","label ASC","label ASC"), // Sort order
'tabfield'=>array("code,label","code,label","code,label"), // List of fields (result of select to show dictionary)
'tabfieldvalue'=>array("code,label","code,label","code,label"), // List of fields (list of fields to edit a record)
'tabfieldinsert'=>array("code,label","code,label","code,label"), // List of fields (list of fields for insert)
'tabrowid'=>array("rowid","rowid","rowid"), // Name of columns with primary key (try to always name it 'rowid')
'tabcond'=>array($conf->inventory->enabled,$conf->inventory->enabled,$conf->inventory->enabled) // Condition to show each dictionary
);
*/
// Boxes
// Add here list of php file(s) stored in core/boxes that contains class to show a box.
$this->boxes = array(); // List of boxes
// Example:
//$this->boxes=array(array(0=>array('file'=>'myboxa.php','note'=>'','enabledbydefaulton'=>'Home'),1=>array('file'=>'myboxb.php','note'=>''),2=>array('file'=>'myboxc.php','note'=>'')););
// Permissions
$this->rights = array(); // Permission array used by this module
$r=0;
// Add here list of permission defined by an id, a label, a boolean and two constant strings.
// Example:
// $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used)
// $this->rights[$r][1] = 'Permision label'; // Permission label
// $this->rights[$r][3] = 1; // Permission by default for new user (0/1)
// $this->rights[$r][4] = 'level1'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2)
// $this->rights[$r][5] = 'level2'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2)
// $r++;
$this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used)
$this->rights[$r][1] = 'inventoryReadPermission'; // Permission label
$this->rights[$r][3] = 1; // Permission by default for new user (0/1)
$this->rights[$r][4] = 'read'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2)
$r++;
$this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used)
$this->rights[$r][1] = 'inventoryCreatePermission'; // Permission label
$this->rights[$r][3] = 0; // Permission by default for new user (0/1)
$this->rights[$r][4] = 'create'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2)
$r++;
$this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used)
$this->rights[$r][1] = 'inventoryWritePermission'; // Permission label
$this->rights[$r][3] = 0; // Permission by default for new user (0/1)
$this->rights[$r][4] = 'write'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2)
$r++;
$this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used)
$this->rights[$r][1] = 'inventoryValidatePermission'; // Permission label
$this->rights[$r][3] = 0; // Permission by default for new user (0/1)
$this->rights[$r][4] = 'validate'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2)
$r++;
$this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used)
$this->rights[$r][1] = 'inventoryChangePMPPermission'; // Permission label
$this->rights[$r][3] = 0; // Permission by default for new user (0/1)
$this->rights[$r][4] = 'changePMP'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2)
$r++;
// Main menu entries
$this->menu = array(); // List of menus to add
$r=0;
$this->menu[$r]=array(
'fk_menu'=>'fk_mainmenu=products', // Put 0 if this is a top menu
'type'=>'left', // This is a Top menu entry
'titre'=>'Inventory',
'mainmenu'=>'products',
'leftmenu'=>'inventory_left',
'url'=>'/inventory/list.php',
'langs'=>'inventory', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.
'position'=>100+$r,
'enabled'=>'$conf->inventory->enabled', // Define condition to show or hide menu entry. Use '$conf->inventory->enabled' if entry must be visible if module is enabled.
'perms'=>'$user->rights->inventory->read', // Use 'perms'=>'$user->rights->inventory->level1->level2' if you want your menu with a permission rules
'target'=>'',
'user'=>2
); // 0=Menu for internal users, 1=external users, 2=both
$r++;
$this->menu[$r]=array(
'fk_menu'=>'fk_mainmenu=products,fk_leftmenu=inventory_left', // Put 0 if this is a top menu
'type'=>'left', // This is a Top menu entry
'titre'=>'NewInventory',
'mainmenu'=>'products',
'leftmenu'=>'inventory_left_create',
'url'=>'/inventory/inventory.php?action=create',
'position'=>100+$r,
'enabled'=>'$conf->inventory->enabled', // Define condition to show or hide menu entry. Use '$conf->inventory->enabled' if entry must be visible if module is enabled.
'perms'=>'$user->rights->inventory->create', // Use 'perms'=>'$user->rights->inventory->level1->level2' if you want your menu with a permission rules
'target'=>'',
'user'=>2
); // 0=Menu for internal users, 1=external users, 2=both
$r++;
$this->menu[$r]=array(
'fk_menu'=>'fk_mainmenu=products,fk_leftmenu=inventory_left', // Put 0 if this is a top menu
'type'=>'left', // This is a Top menu entry
'titre'=>'ListInventory',
'mainmenu'=>'products',
'leftmenu'=>'inventory_left_list',
'url'=>'/inventory/list.php',
'langs'=>'inventory', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.
'position'=>100+$r,
'enabled'=>'$conf->inventory->enabled', // Define condition to show or hide menu entry. Use '$conf->inventory->enabled' if entry must be visible if module is enabled.
'perms'=>'$user->rights->inventory->read', // Use 'perms'=>'$user->rights->inventory->level1->level2' if you want your menu with a permission rules
'target'=>'',
'user'=>2
); // 0=Menu for internal users, 1=external users, 2=both
$r++;
// Exports
$r=1;
// Example:
// $this->export_code[$r]=$this->rights_class.'_'.$r;
// $this->export_label[$r]='CustomersInvoicesAndInvoiceLines'; // Translation key (used only if key ExportDataset_xxx_z not found)
// $this->export_enabled[$r]='1'; // Condition to show export in list (ie: '$user->id==3'). Set to 1 to always show when module is enabled.
// $this->export_permission[$r]=array(array("facture","facture","export"));
// $this->export_fields_array[$r]=array('s.rowid'=>"IdCompany",'s.nom'=>'CompanyName','s.address'=>'Address','s.zip'=>'Zip','s.town'=>'Town','s.fk_pays'=>'Country','s.phone'=>'Phone','s.siren'=>'ProfId1','s.siret'=>'ProfId2','s.ape'=>'ProfId3','s.idprof4'=>'ProfId4','s.code_compta'=>'CustomerAccountancyCode','s.code_compta_fournisseur'=>'SupplierAccountancyCode','f.rowid'=>"InvoiceId",'f.facnumber'=>"InvoiceRef",'f.datec'=>"InvoiceDateCreation",'f.datef'=>"DateInvoice",'f.total'=>"TotalHT",'f.total_ttc'=>"TotalTTC",'f.tva'=>"TotalVAT",'f.paye'=>"InvoicePaid",'f.fk_statut'=>'InvoiceStatus','f.note'=>"InvoiceNote",'fd.rowid'=>'LineId','fd.description'=>"LineDescription",'fd.price'=>"LineUnitPrice",'fd.tva_tx'=>"LineVATRate",'fd.qty'=>"LineQty",'fd.total_ht'=>"LineTotalHT",'fd.total_tva'=>"LineTotalTVA",'fd.total_ttc'=>"LineTotalTTC",'fd.date_start'=>"DateStart",'fd.date_end'=>"DateEnd",'fd.fk_product'=>'ProductId','p.ref'=>'ProductRef');
// $this->export_entities_array[$r]=array('s.rowid'=>"company",'s.nom'=>'company','s.address'=>'company','s.zip'=>'company','s.town'=>'company','s.fk_pays'=>'company','s.phone'=>'company','s.siren'=>'company','s.siret'=>'company','s.ape'=>'company','s.idprof4'=>'company','s.code_compta'=>'company','s.code_compta_fournisseur'=>'company','f.rowid'=>"invoice",'f.facnumber'=>"invoice",'f.datec'=>"invoice",'f.datef'=>"invoice",'f.total'=>"invoice",'f.total_ttc'=>"invoice",'f.tva'=>"invoice",'f.paye'=>"invoice",'f.fk_statut'=>'invoice','f.note'=>"invoice",'fd.rowid'=>'invoice_line','fd.description'=>"invoice_line",'fd.price'=>"invoice_line",'fd.total_ht'=>"invoice_line",'fd.total_tva'=>"invoice_line",'fd.total_ttc'=>"invoice_line",'fd.tva_tx'=>"invoice_line",'fd.qty'=>"invoice_line",'fd.date_start'=>"invoice_line",'fd.date_end'=>"invoice_line",'fd.fk_product'=>'product','p.ref'=>'product');
// $this->export_sql_start[$r]='SELECT DISTINCT ';
// $this->export_sql_end[$r] =' FROM ('.MAIN_DB_PREFIX.'facture as f, '.MAIN_DB_PREFIX.'facturedet as fd, '.MAIN_DB_PREFIX.'societe as s)';
// $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product as p on (fd.fk_product = p.rowid)';
// $this->export_sql_end[$r] .=' WHERE f.fk_soc = s.rowid AND f.rowid = fd.fk_facture';
// $this->export_sql_order[$r] .=' ORDER BY s.nom';
// $r++;
}
/**
* Function called when module is enabled.
* The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database.
* It also creates data directories
*
* @param string $options Options when enabling module ('', 'noboxes')
* @return int 1 if OK, 0 if KO
*/
function init($options='')
{
$sql = array();
define('INC_FROM_DOLIBARR', true);
dol_include_once('/inventory/config.php');
dol_include_once("/inventory/script/create-maj-base.php");
return $this->_init($sql, $options);
}
/**
* Function called when module is disabled.
* Remove from database constants, boxes and permissions from Dolibarr database.
* Data directories are not deleted
*
* @param string $options Options when enabling module ('', 'noboxes')
* @return int 1 if OK, 0 if KO
*/
function remove($options='')
{
$sql = array();
return $this->_remove($sql, $options);
}
}

View File

@ -182,3 +182,40 @@ ALTER TABLE llx_supplier_proposaldet ADD INDEX idx_supplier_proposaldet_fk_produ
ALTER TABLE llx_supplier_proposaldet ADD CONSTRAINT fk_supplier_proposaldet_fk_unit FOREIGN KEY (fk_unit) REFERENCES llx_c_units (rowid);
ALTER TABLE llx_supplier_proposaldet ADD CONSTRAINT fk_supplier_proposaldet_fk_supplier_proposal FOREIGN KEY (fk_supplier_proposal) REFERENCES llx_supplier_proposal (rowid);
-- NEW inventory module
CREATE TABLE llx_inventory
(
rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY,
datec datetime DEFAULT NULL,
tms timestamp,
fk_warehouse integer DEFAULT 0,
entity integer DEFAULT 0,
status integer DEFAULT 0,
title varchar(255) NOT NULL,
date_inventory datetime DEFAULT NULL
)
ENGINE=InnoDB;
CREATE TABLE llx_inventorydet
(
rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY,
datec datetime DEFAULT NULL,
tms timestamp,
fk_inventory integer DEFAULT 0,
fk_warehouse integer DEFAULT 0,
fk_product integer DEFAULT 0,
entity integer DEFAULT 0,
qty_view double DEFAULT 0,
qty_stock double DEFAULT 0,
qty_regulated double DEFAULT 0,
pmp double DEFAULT 0,
pa double DEFAULT 0,
new_pmp double DEFAULT 0
)
ENGINE=InnoDB;
ALTER TABLE llx_inventory ADD INDEX idx_inventory_tms (tms);
ALTER TABLE llx_inventory ADD INDEX idx_inventory_datec (datec);
ALTER TABLE llx_inventorydet ADD INDEX idx_inventorydet_tms (tms);
ALTER TABLE llx_inventorydet ADD INDEX idx_inventorydet_datec (datec);
ALTER TABLE llx_inventorydet ADD INDEX idx_inventorydet_fk_inventory (fk_inventory);

View File

@ -0,0 +1,21 @@
-- ===================================================================
-- Copyright (C) 2012 Laurent Destailleur <eldy@users.sourceforge.net>
-- Copyright (C) 2017 ATM Consulting <support@atm-consulting.fr>
--
-- 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 <http://www.gnu.org/licenses/>.
--
-- ===================================================================
ALTER TABLE llx_inventory ADD INDEX idx_inventory_tms (tms);
ALTER TABLE llx_inventory ADD INDEX idx_inventory_datec (datec);

View File

@ -0,0 +1,31 @@
-- ===================================================================
-- Copyright (C) 2012 Laurent Destailleur <eldy@users.sourceforge.net>
-- Copyright (C) 2017 ATM Consulting <support@atm-consulting.fr>
--
-- 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 <http://www.gnu.org/licenses/>.
--
-- ===================================================================
CREATE TABLE llx_inventory
(
rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY,
datec datetime DEFAULT NULL,
tms timestamp,
fk_warehouse integer DEFAULT 0,
entity integer DEFAULT 0,
status integer DEFAULT 0,
title varchar(255) NOT NULL,
date_inventory datetime DEFAULT NULL
)
ENGINE=InnoDB;

View File

@ -0,0 +1,22 @@
-- ===================================================================
-- Copyright (C) 2012 Laurent Destailleur <eldy@users.sourceforge.net>
-- Copyright (C) 2017 ATM Consulting <support@atm-consulting.fr>
--
-- 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 <http://www.gnu.org/licenses/>.
--
-- ===================================================================
ALTER TABLE llx_inventorydet ADD INDEX idx_inventorydet_tms (tms);
ALTER TABLE llx_inventorydet ADD INDEX idx_inventorydet_datec (datec);
ALTER TABLE llx_inventorydet ADD INDEX idx_inventorydet_fk_inventory (fk_inventory);

View File

@ -0,0 +1,36 @@
-- ===================================================================
-- Copyright (C) 2012 Laurent Destailleur <eldy@users.sourceforge.net>
-- Copyright (C) 2017 ATM Consulting <support@atm-consulting.fr>
--
-- 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 <http://www.gnu.org/licenses/>.
--
-- ===================================================================
CREATE TABLE llx_inventorydet
(
rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY,
datec datetime DEFAULT NULL,
tms timestamp,
fk_inventory integer DEFAULT 0,
fk_warehouse integer DEFAULT 0,
fk_product integer DEFAULT 0,
entity integer DEFAULT 0,
qty_view double DEFAULT 0,
qty_stock double DEFAULT 0,
qty_regulated double DEFAULT 0,
pmp double DEFAULT 0,
pa double DEFAULT 0,
new_pmp double DEFAULT 0
)
ENGINE=InnoDB;

View File

@ -0,0 +1,51 @@
<?php
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/inventory/class/inventory.class.php';
$get = GETPOST('get');
$put = GETPOST('put');
switch ($put)
{
case 'qty':
if (empty($user->rights->inventory->write)) { echo -1; exit; }
$fk_det_inventory = GETPOST('fk_det_inventory');
$det = new Inventorydet($db);
if( $det->fetch( $fk_det_inventory))
{
$det->qty_view+=GETPOST('qty');
$det->update($user);
echo $det->qty_view;
}
else
{
echo -2;
}
break;
case 'pmp':
if (!$user->rights->inventory->write || !$user->rights->inventory->changePMP) { echo -1; exit; }
$fk_det_inventory = GETPOST('fk_det_inventory');
$det = new Inventorydet($db);
if( $det->fetch( $fk_det_inventory))
{
$det->new_pmp=price2num(GETPOST('pmp'));
$det->update($user);
echo $det->new_pmp;
}
else
{
echo -2;
}
break;
}

View File

@ -0,0 +1,710 @@
<?php
/* Copyright (C) 2016 ATM Consulting <support@atm-consulting.fr>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/inventory/class/product.inventory.php
* \ingroup product
* \brief File of class to manage predefined products stock
*/
require_once DOL_DOCUMENT_ROOT.'/core/class/coreobject.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
/**
* Class to manage inventories
*/
class Inventory extends CoreObject
{
public $element='inventory';
public $table_element='inventory';
public $fk_element='fk_inventory';
protected $childtables=array('inventorydet'); // To test if we can delete object
protected $isnolinkedbythird = 1; // No field fk_soc
protected $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
/**
* Warehouse Id
* @var int
*/
public $fk_warehouse;
/**
* Entity Id
* @var int
*/
public $entity;
/**
* Status
* @var int
*/
public $status;
/**
* Inventory Date
* @var date
*/
public $date_inventory;
/**
* Inventory Title
* @var string
*/
public $title;
/**
* Attribute object linked with database
* @var array
*/
protected $__fields=array(
'fk_warehouse'=>array('type'=>'integer','index'=>true)
,'entity'=>array('type'=>'integer','index'=>true)
,'status'=>array('type'=>'integer','index'=>true)
,'date_inventory'=>array('type'=>'date')
,'title'=>array('type'=>'string')
);
/**
* Constructor
*
* @param DoliDB $db Database handler
*/
public function __construct(DoliDB &$db)
{
global $conf;
parent::__construct($db);
parent::init();
$this->status = 0;
$this->entity = $conf->entity;
$this->errors = array();
$this->amount = 0;
}
/**
* Function to sort children object
*/
public function sortDet()
{
if(!empty($this->Inventorydet)) usort($this->Inventorydet, array('Inventory', 'customSort'));
}
/**
* Get object and children from database
*
* @param int $id Id of object to load
* @param bool $loadChild used to load children from database
* @return int >0 if OK, <0 if KO, 0 if not found
*/
public function fetch($id, $loadChild = true)
{
if(!$loadChild) $this->withChild = false;
$res = parent::fetch($id, $loadChild);
if($res > 0)
{
$this->sortDet();
$this->amount = 0;
if(!empty($this->Inventorydet ))
{
foreach($this->Inventorydet as &$det)
{
$this->amount += $det->qty_view * $det->pmp;
}
}
}
return $res;
}
/**
* Custom function call by usort
*
* @param Inventorydet $objA first Inventorydet object
* @param Inventorydet $objB second Inventorydet object
* @return int
*/
private function customSort(&$objA, &$objB)
{
$r = strcmp(strtoupper(trim($objA->product->ref)), strtoupper(trim($objB->product->ref)));
if ($r < 0) $r = -1;
elseif ($r > 0) $r = 1;
else $r = 0;
return $r;
}
/**
* @param User $user user object
* @return int
*/
public function changePMP(User &$user)
{
$error = 0;
$this->db->begin();
if(!empty($this->Inventorydet))
{
foreach ($this->Inventorydet as $k => &$Inventorydet)
{
if($Inventorydet->new_pmp>0)
{
$Inventorydet->pmp = $Inventorydet->new_pmp;
$Inventorydet->new_pmp = 0;
$res = $this->db->query('UPDATE '.MAIN_DB_PREFIX.'product as p SET pmp = '.$Inventorydet->pmp.' WHERE rowid = '.$Inventorydet->fk_product );
if (!$res)
{
$error++;
$this->error = $this->db->lasterror();
$this->errors[] = $this->db->lasterror();
}
}
}
}
$res = parent::update($user);
if (!$res)
{
$error++;
$this->error = $this->db->lasterror();
$this->errors[] = $this->db->lasterror();
}
if (!$error)
{
$this->db->commit();
return 1;
}
else
{
$this->db->rollback();
return -1;
}
}
/**
* Function to update object or create or delete if needed
*
* @param User $user user object
* @return < 0 if ko, > 0 if ok
*/
public function update(User &$user)
{
$error = 0;
$this->db->begin();
// if we valid the inventory we save the stock at the same time
if ($this->status)
{
$res = $this->regulate();
if ($res < 0)
{
$error++;
$this->error = $this->db->lasterror();
$this->errors[] = $this->db->lasterror();
}
}
$res = parent::update($user);
if (!$res)
{
$error++;
$this->error = $this->db->lasterror();
$this->errors[] = $this->db->lasterror();
}
if (!$error)
{
$this->db->commit();
return $this->id;
}
else
{
$this->db->rollback();
return -1;
}
}
/**
* Function to update current object
*
* @param array $Tab Array of values
* @return int
*/
public function setValues(&$Tab)
{
global $langs;
if (isset($Tab['qty_to_add']))
{
foreach ($Tab['qty_to_add'] as $k => $qty)
{
$qty = (float) price2num($qty);
if ($qty < 0)
{
$this->errors[] = $langs->trans('inventoryErrorQtyAdd');
return -1;
}
$product = new Product($this->db);
$product->fetch($this->Inventorydet[$k]->fk_product);
$this->Inventorydet[$k]->pmp = $product->pmp;
$this->Inventorydet[$k]->qty_view += $qty;
}
}
return parent::setValues($Tab);
}
/**
* Function to delete all Inventorydet
*
* @param User $user user object
* @return < 0 if ko, > 0 if ok
*/
public function deleteAllLine(User &$user)
{
foreach($this->Inventorydet as &$det)
{
$det->to_delete = true;
}
$res = $this->update($user);
if ($res > 0) $this->Inventorydet = array();
else return -1;
}
/**
* Function to add Inventorydet
*
* @param int $fk_product fk_product of Inventorydet
* @param int $fk_warehouse fk_warehouse target
* @return bool
*/
public function addProduct($fk_product, $fk_warehouse=0)
{
$k = $this->addChild('Inventorydet');
$det = &$this->Inventorydet[$k];
$det->fk_inventory = $this->id;
$det->fk_product = $fk_product;
$det->fk_warehouse = empty($fk_warehouse) ? $this->fk_warehouse : $fk_warehouse;
$det->load_product();
$date = $this->getDate('date_inventory', 'Y-m-d');
if(empty($date)) $date = $this->getDate('datec', 'Y-m-d');
$det->setStockDate($date, $fk_warehouse);
return true;
}
/**
* Duplication method product to add datem
* Adjust stock in a warehouse for product
*
* @param int $fk_product id of product
* @param int $fk_warehouse id of warehouse
* @param double $nbpiece nb of units
* @param int $movement 0 = add, 1 = remove
* @param string $label Label of stock movement
* @param double $price Unit price HT of product, used to calculate average weighted price (PMP in french). If 0, average weighted price is not changed.
* @param string $inventorycode Inventory code
* @return int <0 if KO, >0 if OK
*/
public function correctStock($fk_product, $fk_warehouse, $nbpiece, $movement, $label='', $price=0, $inventorycode='')
{
global $conf, $user;
if ($fk_warehouse)
{
$this->db->begin();
require_once DOL_DOCUMENT_ROOT .'/product/stock/class/mouvementstock.class.php';
$op[0] = "+".trim($nbpiece);
$op[1] = "-".trim($nbpiece);
$datem = empty($conf->global->INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT) ? dol_now() : $this->date_inventory;
$movementstock=new MouvementStock($this->db);
$movementstock->origin = new stdClass();
$movementstock->origin->element = 'inventory';
$movementstock->origin->id = $this->id;
$result=$movementstock->_create($user,$fk_product,$fk_warehouse,$op[$movement],$movement,$price,$label,$inventorycode, $datem);
if ($result >= 0)
{
$this->db->commit();
return 1;
}
else
{
$this->error=$movementstock->error;
$this->errors=$movementstock->errors;
$this->db->rollback();
return -1;
}
}
}
/**
* Function to regulate stock
*
* @return int
*/
public function regulate()
{
global $langs,$conf;
if($conf->global->INVENTORY_DISABLE_VIRTUAL)
{
$pdt_virtuel = false;
// Test if virtual product is enabled
if($conf->global->PRODUIT_SOUSPRODUITS)
{
$pdt_virtuel = true;
$conf->global->PRODUIT_SOUSPRODUITS = 0;
}
}
foreach ($this->Inventorydet as $k => $Inventorydet)
{
$product = new Product($this->db);
$product->fetch($Inventorydet->fk_product);
if ($Inventorydet->qty_view != $Inventorydet->qty_stock)
{
$Inventorydet->qty_regulated = $Inventorydet->qty_view - $Inventorydet->qty_stock;
$nbpiece = abs($Inventorydet->qty_regulated);
$movement = (int) ($Inventorydet->qty_view < $Inventorydet->qty_stock); // 0 = add ; 1 = remove
//$href = dol_buildpath('/inventory/inventory.php?id='.$this->id.'&action=view', 1);
$res = $this->correctStock($product->id, $Inventorydet->fk_warehouse, $nbpiece, $movement, $langs->trans('inventoryMvtStock'));
if ($res < 0) return -1;
}
}
if($conf->global->INVENTORY_DISABLE_VIRTUAL)
{
// Test if virtual product was enabled before regulate
if($pdt_virtuel) $conf->global->PRODUIT_SOUSPRODUITS = 1;
}
return 1;
}
/**
* Get the title
* @return string
*/
public function getTitle()
{
global $langs;
return !empty($this->title) ? $this->title : $langs->trans('inventoryTitle').' '.$this->id;
}
/**
* Return clicable link of object (with eventually picto)
*
* @param int $withpicto Add picto into link
* @return string
*/
public function getNomUrl($withpicto = 1)
{
return '<a href="'.dol_buildpath('/inventory/inventory.php?id='.$this->id, 1).'">'.($withpicto ? img_picto('','object_list.png','',0).' ' : '').$this->getTitle().'</a>';
}
/**
* Function to add products by default from warehouse and children
*
* @param int $fk_warehouse id of warehouse
* @param int $fk_category id of category
* @param int $fk_supplier id of supplier
* @param int $only_prods_in_stock only product with stock
*
* @return int
*/
public function addProductsFor($fk_warehouse,$fk_category=0,$fk_supplier=0,$only_prods_in_stock=0)
{
$warehouse = new Entrepot($this->db);
$warehouse->fetch($fk_warehouse);
$TChildWarehouses = array($fk_warehouse);
$warehouse->get_children_warehouses($fk_warehouse, $TChildWarehouses);
$sql = 'SELECT ps.fk_product, ps.fk_entrepot';
$sql.= ' FROM '.MAIN_DB_PREFIX.'product_stock ps';
$sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'product p ON (p.rowid = ps.fk_product)';
$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product cp ON (cp.fk_product = p.rowid)';
$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_fournisseur_price pfp ON (pfp.fk_product = p.rowid)';
$sql.= ' 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 (!empty($only_prods_in_stock)) $sql.= ' AND ps.reel > 0';
$sql.=' GROUP BY ps.fk_product, ps.fk_entrepot ORDER BY p.ref ASC,p.label ASC';
$res = $this->db->query($sql);
if($res)
{
while($obj = $this->db->fetch_object($res))
{
$this->addProduct($obj->fk_product, $obj->fk_entrepot);
}
return 1;
}
else
{
$this->error = $this->db->lasterror();
$this->errors[] = $this->db->lasterror();
return -1;
}
}
/**
* Return clicable link of inventory object
*
* @param int $id id of inventory
* @param int $withpicto Add picto into link
* @return string
*/
static function getLink($id, $withpicto=1)
{
global $langs,$db;
$inventory = new Inventory($db);
if($inventory->fetch($id, false) > 0) return $inventory->getNomUrl($withpicto);
else return $langs->trans('InventoryUnableToFetchObject');
}
/**
* Function to get the sql select of inventory
* @param string $type 'All' to get all data
* @return string
*/
static function getSQL($type)
{
global $conf;
$sql = '';
if($type == 'All')
{
$sql = 'SELECT i.rowid,i.title, e.label, i.date_inventory, i.fk_warehouse, i.datec, i.tms, i.status';
$sql.= ' FROM '.MAIN_DB_PREFIX.'inventory i';
$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'entrepot e ON (e.rowid = i.fk_warehouse)';
$sql.= ' WHERE i.entity = '.(int) $conf->entity;
}
return $sql;
}
}
class Inventorydet extends CoreObject
{
public $element='inventorydet';
public $table_element='inventorydet';
protected $isnolinkedbythird = 1; // No field fk_soc
protected $ismultientitymanaged = 0; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
public $fk_inventory;
public $fk_warehouse;
public $fk_product;
public $entity;
public $qty_view;
public $qty_stock;
public $qty_regulated;
public $pmp;
public $pa;
public $new_pmp;
protected $__fields=array(
'fk_inventory'=>array('type'=>'int')
,'fk_warehouse'=>array('type'=>'int')
,'fk_product'=>array('type'=>'int')
,'entity'=>array('type'=>'int')
,'qty_view'=>array('type'=>'float')
,'qty_stock'=>array('type'=>'float')
,'qty_regulated'=>array('type'=>'float')
,'pmp'=>array('type'=>'float')
,'pa'=>array('type'=>'float')
,'new_pmp'=>array('type'=>'float')
);
/**
* Constructor
*
* @param DoliDB $db Database handler
*/
function __construct(DoliDB &$db)
{
global $conf;
parent::__construct($db);
parent::init();
$this->entity = $conf->entity;
$this->errors = array();
$this->product = null;
$this->current_pa = 0;
}
/**
* Get object and children from database
*
* @param int $id id of inventorydet object
* @param bool $loadChild load children
* @return int
*/
function fetch($id, $loadChild = true)
{
$res = parent::fetch($id);
$this->load_product();
$this->fetch_current_pa();
return $res;
}
/**
* Function to get the unit buy price
*
* @return bool
*/
function fetch_current_pa()
{
global $db,$conf;
if(empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) return false;
if($this->pa > 0)
{
$this->current_pa = $this->pa;
}
else
{
dol_include_once('/fourn/class/fournisseur.product.class.php');
$p= new ProductFournisseur($db);
$p->find_min_price_product_fournisseur($this->fk_product);
if($p->fourn_qty>0) $this->current_pa = $p->fourn_price / $p->fourn_qty;
}
return true;
}
/**
* Function to set pa attribute from date en fk_warehouse
*
* @param date $date date value
* @param int $fk_warehouse fk_warehouse target
*/
function setStockDate($date, $fk_warehouse)
{
list($pmp, $stock) = $this->getPmpStockFromDate($date, $fk_warehouse);
$this->qty_stock = $stock;
$this->pmp = $pmp;
$last_pa = 0;
$sql = 'SELECT price FROM '.MAIN_DB_PREFIX.'stock_mouvement';
$sql.= ' WHERE fk_entrepot = '.$fk_warehouse;
$sql.= ' AND fk_product = '.$this->fk_product;
$sql.= ' AND (origintype=\'order_supplier\' || origintype=\'invoice_supplier\')';
$sql.= ' AND price > 0';
$sql.= ' AND datem <= \''.$date.' 23:59:59\'';
$sql.= ' ORDER BY datem DESC LIMIT 1';
$res = $this->db->query($sql);
if($res && $obj = $this->db->fetch_object($res))
{
$last_pa = $obj->price;
}
$this->pa = $last_pa;
}
/**
* Get the last pmp and last stock from date and warehouse
*
* @param date $date date to check
* @param int $fk_warehouse id of warehouse
* @return array
*/
function getPmpStockFromDate($date, $fk_warehouse)
{
$res = $this->product->load_stock();
if($res>0)
{
$stock = isset($this->product->stock_warehouse[$fk_warehouse]->real) ? $this->product->stock_warehouse[$fk_warehouse]->real : 0;
$pmp = $this->product->pmp;
}
//All Stock mouvement between now and inventory date
$sql = 'SELECT value, price';
$sql.= ' FROM '.MAIN_DB_PREFIX.'stock_mouvement';
$sql.= ' WHERE fk_product = '.$this->product->id;
$sql.= ' AND fk_entrepot = '.$fk_warehouse;
$sql.= ' AND datem > \''.date('Y-m-d 23:59:59', strtotime($date)).'\'';
$sql.= ' ORDER BY datem DESC';
$res = $this->db->query($sql);
$laststock = $stock;
$lastpmp = $pmp;
if($res)
{
while($mouvement = $this->db->fetch_object($res))
{
$price = ($mouvement->price > 0 && $mouvement->value > 0) ? $mouvement->price : $lastpmp;
$stock_value = $laststock * $lastpmp;
$laststock -= $mouvement->value;
$last_stock_value = $stock_value - ($mouvement->value * $price);
$lastpmp = ($laststock != 0) ? $last_stock_value / $laststock : $lastpmp;
}
}
return array($lastpmp, $laststock);
}
/**
* Fetch the product linked with the line
* @return void
*/
function load_product()
{
global $db;
if($this->fk_product>0)
{
$this->product = new Product($db);
$this->product->fetch($this->fk_product);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 B

View File

@ -0,0 +1,648 @@
<?php
/* Copyright (C) 2016 ATM Consulting <support@atm-consulting.fr>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/inventory/inventory.php
* \ingroup product
* \brief File of class to manage inventory
*/
require_once '../main.inc.php';
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';
$langs->load('stock');
$langs->load('inventory');
if(empty($user->rights->inventory->read)) accessforbidden();
_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 'create':
if (empty($user->rights->inventory->create)) accessforbidden();
$inventory = new Inventory($db);
card_warehouse( $inventory);
break;
case 'confirmCreate':
if (empty($user->rights->inventory->create)) accessforbidden();
$inventory = new Inventory($db);
$inventory->setValues($_POST);
$fk_inventory = $inventory->create($user);
if($fk_inventory>0) {
$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');
$inventory->addProductsFor($fk_warehouse,$fk_category,$fk_supplier,$only_prods_in_stock);
$inventory->update($user);
header('Location: '.dol_buildpath('/inventory/inventory.php?id='.$inventory->id.'&action=edit', 1));
}
else{
setEventMessage($inventory->error,'errors');
header('Location: '.dol_buildpath('/inventory/inventory.php?action=create', 1));
}
break;
case 'edit':
if (!$user->rights->inventory->write) accessforbidden();
$inventory = new Inventory($db);
$inventory->fetch(GETPOST('id'));
card($inventory, GETPOST('action'));
break;
case 'save':
if (!$user->rights->inventory->write) accessforbidden();
$id = GETPOST('id');
$inventory = new Inventory($db);
$inventory->fetch($id);
$inventory->setValues($_REQUEST);
if ($inventory->errors)
{
setEventMessage($inventory->errors, 'errors');
card( $inventory, 'edit');
}
else
{
$inventory->udpate($user);
header('Location: '.dol_buildpath('inventory/inventory.php?id='.$inventory->getId().'&action=view', 1));
}
break;
case 'confirm_regulate':
if (!$user->rights->inventory->write) accessforbidden();
$id = GETPOST('id');
$inventory = new Inventory($db);
$inventory->fetch($id);
if($inventory->status == 0) {
$inventory->status = 1;
$inventory->update($user);
card( $inventory, 'view');
}
else {
card( $inventory, 'view');
}
break;
case 'confirm_changePMP':
$id = GETPOST('id');
$inventory = new Inventory($db);
$inventory->fetch( $id );
$inventory->changePMP($user);
card( $inventory, 'view');
break;
case 'add_line':
if (!$user->rights->inventory->write) accessforbidden();
$id = GETPOST('id');
$fk_warehouse = GETPOST('fk_warehouse');
$inventory = new Inventory($db);
$inventory->fetch( $id );
$fk_product = GETPOST('fk_product');
if ($fk_product>0)
{
$product = new Product($db);
if($product->fetch($fk_product)<=0 || $product->type != 0) {
setEventMessage($langs->trans('ThisIsNotAProduct'),'errors');
}
else{
//Check product not already exists
$alreadyExists = false;
if(!empty($inventory->Inventorydet)) {
foreach ($inventory->Inventorydet as $invdet)
{
if ($invdet->fk_product == $product->id
&& $invdet->fk_warehouse == $fk_warehouse)
{
$alreadyExists = true;
break;
}
}
}
if (!$alreadyExists)
{
if($inventory->addProduct($product->id, $fk_warehouse)) {
setEventMessage($langs->trans('ProductAdded'));
}
}
else
{
setEventMessage($langs->trans('inventoryWarningProductAlreadyExists'), 'warnings');
}
}
$inventory->update($user);
$inventory->sortDet();
}
card( $inventory, 'edit');
break;
case 'confirm_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 = GETPOST('rowid');
$Inventorydet = new Inventorydet($db);
if($Inventorydet->fetch($rowid)>0) {
$Inventorydet->delete($user);
setEventMessage("ProductDeletedFromInventory");
}
$id = GETPOST('id');
$inventory = new Inventory($db);
$inventory->fetch( $id);
card($inventory, 'edit');
break;
case 'confirm_flush':
if (!$user->rights->inventory->create) accessforbidden();
$id = GETPOST('id');
$inventory = new Inventory($db);
$inventory->fetch($id);
$inventory->deleteAllLine($user);
setEventMessage($langs->trans('InventoryFlushed'));
card( $inventory, 'edit');
break;
case 'confirm_delete':
if (!$user->rights->inventory->create) accessforbidden();
$id = GETPOST('id');
$inventory = new Inventory($db);
$inventory->fetch($id);
$inventory->delete($user);
setEventMessage($langs->trans('InventoryDeleted'));
header('Location: '.dol_buildpath('/inventory/list.php', 1));
exit;
break;
case 'exportCSV':
$id = GETPOST('id');
$inventory = new Inventory($db);
$inventory->fetch($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 card_warehouse(&$inventory)
{
global $langs,$conf,$db, $user, $form;
dol_include_once('/categories/class/categorie.class.php');
llxHeader('',$langs->trans('inventorySelectWarehouse'),'','');
print dol_get_fiche_head(inventoryPrepareHead($inventory));
echo '<form name="confirmCreate" action="'.$_SERVER['PHP_SELF'].'" method="post" />';
echo '<input type="hidden" name="action" value="confirmCreate" />';
$formproduct = new FormProduct($db);
?>
<table class="border" width="100%" >
<tr>
<td><?php echo $langs->trans('Title') ?></td>
<td><input type="text" name="title" value="" size="50" /></td>
</tr>
<tr>
<td><?php echo $langs->trans('Date') ?></td>
<td><?php echo $form->select_date(time(),'date_inventory'); ?></td>
</tr>
<tr>
<td><?php echo $langs->trans('inventorySelectWarehouse') ?></td>
<td><?php echo $formproduct->selectWarehouses('', 'fk_warehouse') ?></td>
</tr>
<tr>
<td><?php echo $langs->trans('SelectCategory') ?></td>
<td><?php echo $form->select_all_categories(0,'', 'fk_category') ?></td>
</tr>
<tr>
<td><?php echo $langs->trans('SelectFournisseur') ?></td>
<td><?php echo $form->select_thirdparty('','fk_supplier','s.fournisseur = 1') ?></td>
</tr>
<tr>
<td><?php echo $langs->trans('OnlyProdsInStock') ?></td>
<td><input type="checkbox" name="OnlyProdsInStock" value="1"></td>
</tr>
</table>
<?php
print '<div class="tabsAction">';
print '<input type="submit" class="butAction" value="'.$langs->trans('inventoryConfirmCreate').'" />';
print '</div>';
echo '</form>';
llxFooter('');
}
function card(&$inventory, $action='edit')
{
global $langs, $conf, $db, $user,$form;
llxHeader('',$langs->trans('inventoryEdit'),'','');
if($action == 'changePMP')
{
print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$inventory->id, $langs->trans('ApplyNewPMP'), $langs->trans('ConfirmApplyNewPMP', $inventory->getTitle()), 'confirm_changePMP', array(),'no',1);
}
else if($action == 'flush')
{
print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$inventory->id,$langs->trans('FlushInventory'),$langs->trans('ConfirmFlushInventory',$inventory->getTitle()),'confirm_flush',array(),'no',1);
}
else if($action == 'delete')
{
print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$inventory->id,$langs->trans('Delete'),$langs->trans('ConfirmDelete',$inventory->getTitle()),'confirm_delete',array(),'no',1);
}
else if($action == 'delete_line')
{
print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$inventory->id.'&rowid='.GETPOST('rowid'),$langs->trans('DeleteLine'),$langs->trans('ConfirmDeleteLine',$inventory->getTitle()),'confirm_delete_line',array(),'no',1);
}
else if($action == 'regulate')
{
print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$inventory->id,$langs->trans('RegulateStock'),$langs->trans('ConfirmRegulateStock',$inventory->getTitle()),'confirm_regulate',array(),'no',1);
}
$warehouse = new Entrepot($db);
$warehouse->fetch($inventory->fk_warehouse);
print dol_get_fiche_head(inventoryPrepareHead($inventory, $langs->trans('inventoryOfWarehouse', $warehouse->libelle), empty($action) ? '': '&action='.$action));
$lines = array();
card_line($inventory, $lines, $action);
print '<b>'.$langs->trans('inventoryOnDate')." ".$inventory->getDate('date_inventory').'</b><br><br>';
$inventoryTPL = array(
'id'=> $inventory->id
,'date_cre' => $inventory->getDate('date_cre', 'd/m/Y')
,'date_maj' => $inventory->getDate('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' => $action
,'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, $mode)
{
global $db,$langs,$user,$conf;
$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;
$qty = (float)GETPOST('qty_to_add')[$k];
$lines[]=array(
'produit' => $product->getNomUrl(1).'&nbsp;-&nbsp;'.$product->label,
'entrepot'=>$e->getNomUrl(1),
'barcode' => $product->barcode,
'qty' =>($mode == 'edit' ? '<input type="text" name="qty_to_add['.$k.']" value="'.$qty.'" size="8" style="text-align:center;" /> <a id="a_save_qty_'.$k.'" href="javascript:save_qty('.$k.')">'.img_picto($langs->trans('Add'), 'plus16@inventory').'</a>' : '' ),
'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 && $mode=='edit' ? '<a href="'.dol_buildpath('inventory/inventory.php?id='.$inventory->id.'&action=delete_line&rowid='.$Inventorydet->id, 1).'">'.img_picto($langs->trans('inventoryDeleteLine'), 'delete').'</a>' : ''),
'pmp_stock'=>round($pmp_actual,2),
'pmp_actual'=> round($pmp * $Inventorydet->qty_view,2),
'pmp_new'=>(!empty($user->rights->inventory->changePMP) && $mode == 'edit' ? '<input type="text" name="new_pmp['.$k.']" value="'.$Inventorydet->new_pmp.'" size="8" style="text-align:right;" /> <a id="a_save_new_pmp_'.$k.'" href="javascript:save_pmp('.$k.')">'.img_picto($langs->trans('Save'), 'bt-save.png@inventory').'</a>' : price($Inventorydet->new_pmp)),
'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 _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) { ?>
<tr style="background-color:#dedede;">
<th colspan="3">&nbsp;</th>
<?php if (! empty($conf->barcode->enabled)) { ?>
<th align="center">&nbsp;</td>
<?php } ?>
<th align="right"><?php echo price($total_pmp) ?></th>
<th align="right"><?php echo price($total_pa) ?></th>
<?php
if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){
echo '<th align="right">'.price($total_current_pa).'</th>';
}
?>
<th>&nbsp;</th>
<th align="right"><?php echo price($total_pmp_actual) ?></th>
<?php
if(!empty($user->rights->inventory->changePMP)) {
echo '<th>&nbsp;</th>';
}
?>
<th align="right"><?php echo price($total_pa_actual) ?></th>
<?php
if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){
echo '<th align="right">'.price($total_current_pa_actual).'</th>';
}
?>
<th>&nbsp;</th>
<?php if ($view['is_already_validate'] != 1) { ?>
<th>&nbsp;</th>
<?php } ?>
</tr>
<?php }
}
function _headerList($view) {
global $conf,$user,$langs;
?>
<tr style="background-color:#dedede;">
<th align="left" width="20%">&nbsp;&nbsp;Produit</th>
<th align="center"><?php echo $langs->trans('Warehouse'); ?></th>
<?php if (! empty($conf->barcode->enabled)) { ?>
<th align="center"><?php echo $langs->trans('Barcode'); ?></th>
<?php } ?>
<?php if ($view['can_validate'] == 1) { ?>
<th align="center" width="20%"><?php echo $langs->trans('TheoricalQty'); ?></th>
<?php
if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){
echo '<th align="center" width="20%" colspan="3">'.$langs->trans('TheoricalValue').'</th>';
}
else {
echo '<th align="center" width="20%" colspan="2">'.$langs->trans('TheoricalValue').'</th>';
}
?>
<?php } ?>
<th align="center" width="20%"><?php echo $langs->trans('RealQty'); ?></th>
<?php if ($view['can_validate'] == 1) { ?>
<?php
$colspan = 2;
if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) $colspan++;
if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) $colspan++;
echo '<th align="center" width="20%" colspan="'.$colspan.'">'.$langs->trans('RealValue').'</th>';
?>
<th align="center" width="15%"><?php echo $langs->trans('RegulatedQty'); ?></th>
<?php } ?>
<?php if ($view['is_already_validate'] != 1) { ?>
<th align="center" width="5%">#</th>
<?php } ?>
</tr>
<?php if ($view['can_validate'] == 1) { ?>
<tr style="background-color:#dedede;">
<th colspan="<?php echo empty($conf->barcode->enabled) ? 3 : 4; ?>">&nbsp;</th>
<th><?php echo $langs->trans('PMP'); ?></th>
<th><?php echo $langs->trans('LastPA'); ?></th>
<?php
if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){
echo '<th>'.$langs->trans('CurrentPA').'</th>';
}
?>
<th>&nbsp;</th>
<th><?php echo $langs->trans('PMP'); ?></th>
<?php
if(!empty($user->rights->inventory->changePMP)) {
echo '<th rel="newPMP">'.$langs->trans('ColumnNewPMP').'</th>';
}
?>
<th><?php echo $langs->trans('LastPA'); ?></th>
<?php
if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){
echo '<th>'.$langs->trans('CurrentPA').'</th>';
}
?>
<th>&nbsp;</th>
<?php if ($view['is_already_validate'] != 1) { ?>
<th>&nbsp;</th>
<?php } ?>
</tr>
<?php
}
}

View File

@ -0,0 +1,104 @@
<?php
/* <one line to give the program's name and a brief idea of what it does.>
* Copyright (C) 2015 ATM Consulting <support@atm-consulting.fr>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**
* \file lib/inventory.lib.php
* \ingroup inventory
* \brief This file is an example module library
*/
/**
* Define head array for tabs of inventory tools setup pages
*
* @return Array of head
*/
function inventoryAdminPrepareHead()
{
global $langs, $conf;
$langs->load("inventory@inventory");
$h = 0;
$head = array();
$head[$h][0] = dol_buildpath("/admin/inventory.php", 1);
$head[$h][1] = $langs->trans("Parameters");
$head[$h][2] = 'settings';
$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='Inventory', $get='')
{
global $langs;
return array(
array(dol_buildpath('/inventory/inventory.php?id='.$inventory->id.$get, 1), $langs->trans($title),'inventory')
);
}
function inventorySelectProducts(&$inventory)
{
global $conf,$db,$langs;
$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');
$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 '&nbsp;&nbsp;&nbsp;';
print $langs->trans('Warehouse').' : '.$form::selectarray('fk_warehouse', $Tab);
$select_html = ob_get_clean();
return $select_html;
}

104
htdocs/inventory/list.php Normal file
View File

@ -0,0 +1,104 @@
<?php
/* Copyright (C) 2016 ATM Consulting <support@atm-consulting.fr>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/inventory/inventory.php
* \ingroup product
* \brief File of class to manage inventory
*/
require_once '../main.inc.php';
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';
$langs->load("stock");
$langs->load("inventory");
if (empty($user->rights->inventory->read)) accessforbidden();
llxHeader('',$langs->trans('inventoryListTitle'),'','');
echo '<form name="formListInvetory" action="'.$_SERVER['PHP_SELF'].'" method="post" >';
$inventory = new Inventory($db);
$list = new ListView($db, 'listInventory');
$THide = array('label','title');
echo $list->render(Inventory::getSQL('All'), array(
'limit' => array(
'nbLine' => GETPOST('limit')
),
'allow-field-select' => true,
'link'=>array(
'fk_warehouse'=>'<a href="'.DOL_URL_ROOT.'/product/stock/card.php?id=@val@">'.img_picto('','object_stock.png','',0).' @label@</a>'
),
'translate'=>array(),
'hide'=>$THide,
'type'=>array(
'datec'=>'date',
'tms'=>'datetime',
'date_inventory'=>'date'
),
'list'=>array(
'title'=>$langs->trans('inventoryListTitle'),
'messageNothing'=>$langs->trans('inventoryListEmpty'),
'image' => 'inventory.png@inventory'
),
'title'=>array(
'rowid'=>$langs->trans('Title'),
'date_inventory'=>$langs->trans('InventoryDate'),
'datec'=>$langs->trans('DateCreation'),
'fk_warehouse'=>$langs->trans('Warehouse'),
'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@)'
),
'position' => array(
'text-align' => array('status' => 'right')
),
'search'=>array(
'rowid' => array('search_type' => true, 'table' => array('i'), 'field' => array('title')),
'date_inventory'=>array('search_type' => 'calendars', 'table' => array('i'), 'field' => array('date_inventory')),
'status'=>array('search_type' => array(1=>$langs->trans("inventoryValidate"), 0=>$langs->trans("inventoryDraft")))
)
));
/*if (!empty($user->rights->inventory->create))
{
print '<div class="tabsAction">';
print '<a class="butAction" href="inventory.php?action=create">'.$langs->trans('inventoryCreate').'</a>';
print '</div>';
}*/
echo '</form>';
llxFooter('');
$db->close();

View File

@ -0,0 +1,205 @@
<script type="text/javascript">
function save_qty(k) {
var $input = $('input[name="qty_to_add['+k+']"]');
var fk_det_inventory = $('input[name=det_id_'+k+']').val();
var qty = $input.val();
$('#a_save_qty_'+k).hide();
$.ajax({
url:"ajax/ajax.inventory.php"
,data:{
'fk_det_inventory' : fk_det_inventory
,'qty': qty
,'put':'qty'
}
}).done(function(data) {
$('#qty_view_'+k).html(data);
$input.val(0);
$.jnotify("Quantité ajoutée : "+qty, "mesgs" );
$('#a_save_qty_'+k).show();
hide_save_button();
});
}
function save_pmp(k) {
var $input = $('input[name="new_pmp['+k+']"]');
var fk_det_inventory = $('input[name=det_id_'+k+']').val();
var pmp = $input.val();
$('#a_save_new_pmp_'+k).hide();
$.ajax({
url:"ajax/ajax.inventory.php"
,data:{
'fk_det_inventory' : fk_det_inventory
,'pmp': pmp
,'put':'pmp'
}
}).done(function(data) {
$input.css({"background-color":"#66ff66"});
$.jnotify("PMP sauvegardé : "+pmp, "mesgs" );
$('#a_save_new_pmp_'+k).show();
});
}
function hide_save_button() {
var nb = 0;
$('input[name^="qty_to_add"]').each(function() {
nb += $(this).val();
});
if(nb>0) {
$('input[name=modify]').show();
}
else{
$('input[name=modify]').hide();
}
}
</script>
<?php if ($inventory->status != 1) { ?>
<strong><?php echo $langs->trans('AddInventoryProduct'); ?> : </strong>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
<input type="hidden" name="action" value="add_line" />
<input type="hidden" name="id" value="<?php echo $inventory->id; ?>" />
<?php echo inventorySelectProducts($inventory); ?>
<input class="butAction" type="submit" value="<?php echo $langs->trans('AddProduct'); ?>" />
</form>
<?php } ?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
<?php if ($view['is_already_validate'] == 1) { ?>
<div class="warning">Cet inventaire est validé</div>
<?php } ?>
<input type="hidden" name="action" value="save" />
<input type="hidden" name="id" value="<?php echo $inventory->id; ?>" />
<table width="100%" class="border workstation">
<?php
_headerList($view);
$total_pmp = $total_pa = $total_pmp_actual = $total_pa_actual =$total_current_pa=$total_current_pa_actual = 0;
$i=1;
foreach ($lines as $k=>$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
?>
<tr style="background-color:<?php echo ($k%2 == 0) ? '#fff':'#eee'; ?>;">
<td align="left">&nbsp;&nbsp;<?php echo $row['produit']; ?></td>
<td align="center"><?php echo $row['entrepot']; ?></td>
<?php if (! empty($conf->barcode->enabled)) { ?>
<td align="center"><?php echo $row['barcode']; ?></td>
<?php } ?>
<?php if ($can_validate == 1) { ?>
<td align="center" style="background-color: #e8e8ff;"><?php echo $row['qty_stock']; ?></td>
<td align="right" style="background-color: #e8e8ff;"><?php echo price( $row['pmp_stock']); ?></td>
<td align="right" style="background-color: #e8e8ff;"><?php echo price( $row['pa_stock']); ?></td>
<?php
if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){
echo '<td align="right" style="background-color: #e8e8ff;">'.price($row['current_pa_stock']).'</td>';
$total_current_pa+=$row['current_pa_stock'];
}
?>
<?php } ?>
<td align="center"><?php echo $row['qty']; ?>&nbsp;&nbsp;<span id="qty_view_<?php echo $row['k']; ?>"><?php echo $row['qty_view']; ?></span>
<input type="hidden" name="det_id_<?php echo $row['k']; ?>" value="<?php echo $row['id']; ?>" />
</td>
<?php if ($can_validate == 1) { ?>
<td align="right"><?php echo price($row['pmp_actual']); ?></td>
<?php
if(!empty($user->rights->inventory->changePMP)) {
echo '<td align="right">'.$row['pmp_new'].'</td>';
}
?>
<td align="right"><?php echo price($row['pa_actual']); ?></td>
<?php
if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){
echo '<td align="right">'.price($row['current_pa_actual']).'</td>';
$total_current_pa_actual+=$row['current_pa_actual'];
}
?>
<td align="center"><?php echo $row['qty_regulated']; ?></td>
<?php } ?>
<?php if ($view['is_already_validate'] != 1) { ?>
<td align="center" width="20%"><?php echo $row['action']; ?></td>
<?php } ?>
</tr>
<?php $i++;
}
_footerList($view,$total_pmp,$total_pmp_actual,$total_pa,$total_pa_actual, $total_current_pa,$total_current_pa_actual);
?>
</table>
<?php if ($inventory->status != 1) { ?>
<div class="tabsAction" style="height:30px;">
<?php if ($action!= 'edit') { ?>
<a href="<?php echo $view_url; ?>?id=<?php echo $inventory->id; ?>&action=exportCSV" class="butAction"><?php echo $langs->trans('ExportCSV') ?></a>
<a href="<?php echo $view_url; ?>?id=<?php echo $inventory->id; ?>&action=edit" class="butAction"><?php echo $langs->trans('Modify') ?></a>
<?php
if(!empty($user->rights->inventory->changePMP)) {
echo '<a href="'.$view_url.'?id='.$inventory->id.'&action=changePMP" class="butAction">'.$langs->trans('ApplyPMP').'</a>';
}
if ($can_validate == 1) { ?>
<a href="<?php echo $view_url; ?>?id=<?php echo $inventory->id; ?>&action=regulate&token=" class="butAction"><?php echo $langs->trans('RegulateStock') ?></a>
<?php } ?>
<?php } ?>
<?php if ($action == 'edit') { ?>
<input name="back" type="button" class="butAction" value="<?php echo $langs->trans('ExitEditMode'); ?>" onclick="document.location='?id=<?php echo $inventory->id; ?>&action=view';" />
<?php } ?>
<?php if ($can_validate == 1) { ?>
<a href="<?php echo $view_url; ?>?id=<?php echo $inventory->id; ?>&action=flush" class="butActionDelete"><?php echo $langs->trans('Flush'); ?></a>
&nbsp;&nbsp;&nbsp;
<a href="<?php echo $view_url; ?>?id=<?php echo $inventory->id; ?>&action=delete" class="butActionDelete"><?php echo $langs->trans('Delete') ?></a>
<?php } ?>
</div>
<?php } ?>
<?php if ($inventory->status == 1) { ?>
<div class="tabsAction">
<?php if ($can_validate == 1) { ?>
<a href="<?php echo $view_url; ?>?id=<?php echo $inventory->id; ?>&action=exportCSV" class="butAction"><?php echo $langs->trans('ExportCSV') ?></a>
<a href="#" title="<?php echo $langs->trans('InventoryAlreadyValidated'); ?>" class="butActionRefused"><?php echo $langs->trans('Delete') ?></a>
<?php } ?>
</div>
<?php } ?>
</form>
<p>Date de création : <?php echo $inventory->getDate('datec') ?>
<br />Dernière mise à jour : <?php echo $inventory->getDate('tms') ?></p>

View File

@ -0,0 +1,54 @@
# Dolibarr language file - Source file is en_US - inventory
Module104420Name = Inventory
Module104420Desc = Create and manage your inventory
inventorySetup = Inventory Setup
inventoryCreatePermission=Create new inventory
inventoryReadPermission=View inventories
inventoryWritePermission=Update inventories
inventoryValidatePermission=Validate inventory
inventoryTitle=Inventory
inventoryListTitle=Inventories
inventoryListEmpty=No inventory in progress
inventoryCreateDelete=Create/Delete inventory
inventoryCreate=Create new
inventoryEdit=Edit
inventoryValidate=Validated
inventoryDraft=Running
inventorySelectWarehouse=Warehouse choice
inventoryConfirmCreate=Create
inventoryOfWarehouse=Inventory for warehouse : %s
inventoryErrorQtyAdd=Error : one quantity is leaser than zero
inventoryMvtStock=By inventory
inventoryWarningProductAlreadyExists=This product is already into list
SelectCategory=Category filter
SelectFournisseur=Supplier filter
inventoryOnDate=Inventory
INVENTORY_DISABLE_VIRTUAL=Allow to not destock child product from a kit on inventory
INVENTORY_USE_MIN_PA_IF_NO_LAST_PA=Use the buy price if no last buy price can be found
INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT=Stock mouvment have date of inventory
inventoryChangePMPPermission=Allow to change PMP value for a product
ColumnNewPMP=New unit PMP
OnlyProdsInStock=Do not add product without stock
TheoricalQty=Theorique qty
TheoricalValue=Theorique qty
LastPA=Last BP
CurrentPA=Curent BP
RealQty=Real Qty
RealValue=Real Value
RegulatedQty=Regulated Qty
AddInventoryProduct=Add product to inventory
AddProduct=Add
ApplyPMP=Apply PMP
FlushInventory=Flush inventory
ConfirmFlushInventory=Do you confirm this action ?
InventoryFlushed=Inventory flushed
ExitEditMode=Exit edition
inventoryDeleteLine=Delete line
RegulateStock=Regulate Stock
ListInventory=List
NewInventory=New inventory