develop

Conflicts:
	htdocs/compta/facture/impayees.php
This commit is contained in:
Laurent Destailleur 2014-02-24 17:09:21 +01:00
commit f537f62aea
43 changed files with 8631 additions and 6914 deletions

View File

@ -21,7 +21,10 @@ For users:
- New: Add option MAIN_ADD_SALE_REP_SIGNATURE_IN_NOTE.
- New: Add warning if supplier payment is higher that due amount.
- New: Increase length of url into bookmark module.
- New: Add an admin page to make a mass init of barcode values for all products.
- New: Add an admin page to make a mass init of barcode values for all products.
- New: Automatic events for sending mails showing info about mail linked objects.
- New: Price management enhancement (multiprice level, price by customer, if MAIN_FEATURES_LEVEL=2 Price by qty)
- Fix: Project Task numbering rule customs rule works
TODO
- New: Predefined product and free product use same form.

View File

@ -73,7 +73,8 @@ if ($conf->db->type == 'mysql' || $conf->db->type == 'mysqli')
}
else if ($conf->db->type == 'pgsql')
{
$sqls[0] = "select name,setting from pg_settings";
$sqls[0] = "select name,setting from pg_settings"; // TODO function getServerParametersValues
//$sqls[1] = ""; // TODO Use function getServerStatusValues
$base=2;
}
else if ($conf->db->type == 'mssql')

View File

@ -35,9 +35,7 @@ $month=dol_print_date($now,'%m');
$day=dol_print_date($now,'%d');
$forbarcode=GETPOST('forbarcode');
$fk_barcode_type=GETPOST('fk_barcode_type');
$mode=GETPOST('mode');
$modellabel=GETPOST("modellabel"); // Doc template to use
$numberofsticker=GETPOST('numberofsticker','int');
$eraseallbarcode=GETPOST('eraseallbarcode');
$mesg='';
@ -48,6 +46,8 @@ $thirdpartytmp=new Societe($db);
$modBarCodeProduct='';
$maxperinit=1000;
/*
* Actions
@ -102,43 +102,71 @@ if ($action == 'initbarcodeproducts')
$db->begin();
$sql="SELECT rowid, ref, fk_product_type FROM ".MAIN_DB_PREFIX."product where barcode IS NULL or barcode = ''";
$resql=$db->query($sql);
if ($resql)
$nbok=0;
if (! empty($eraseallbarcode))
{
$num=$db->num_rows($resql);
$i=0; $nbok=$nbtry=0;
while ($i < $num)
$sql ="UPDATE ".MAIN_DB_PREFIX."product";
$sql.=" SET barcode = NULL";
$resql=$db->query($sql);
if ($resql)
{
$obj=$db->fetch_object($resql);
if ($obj)
{
$productstatic->id=$obj->rowid;
$productstatic->ref=$obj->ref;
$productstatic->type=$obj->fk_product_type;
$nextvalue=$modBarCodeProduct->getNextValue($productstatic,'');
print 'Set value '.$nextvalue.' to product '.$productstatic->id." ".$productstatic->ref." ".$productstatic->type."<br>\n";
$result=$productstatic->setValueFrom('barcode', $nextvalue);
$nbtry++;
if ($result > 0) $nbok++;
}
$i++;
setEventMessage($langs->trans("AllBarcodeReset"),'mesgs');
}
else
{
$error++;
dol_print_error($db);
}
}
else
{
$error++;
dol_print_error($db);
$sql ="SELECT rowid, ref, fk_product_type";
$sql.=" FROM ".MAIN_DB_PREFIX."product";
$sql.=" WHERE barcode IS NULL or barcode = ''";
$sql.=$db->order("datec","ASC");
$sql.=$db->plimit($maxperinit);
dol_syslog("codeinit sql=".$sql, LOG_DEBUG);
$resql=$db->query($sql);
if ($resql)
{
$num=$db->num_rows($resql);
$i=0; $nbok=$nbtry=0;
while ($i < min($num,$maxperinit))
{
$obj=$db->fetch_object($resql);
if ($obj)
{
$productstatic->id=$obj->rowid;
$productstatic->ref=$obj->ref;
$productstatic->type=$obj->fk_product_type;
$nextvalue=$modBarCodeProduct->getNextValue($productstatic,'');
//print 'Set value '.$nextvalue.' to product '.$productstatic->id." ".$productstatic->ref." ".$productstatic->type."<br>\n";
$result=$productstatic->setValueFrom('barcode', $nextvalue);
$nbtry++;
if ($result > 0) $nbok++;
}
$i++;
}
}
else
{
$error++;
dol_print_error($db);
}
if (! $error)
{
setEventMessage($langs->trans("RecordsModified",$nbok),'mesgs');
}
}
if (! $error)
{
setEventMessage($langs->trans("RecordsModified",$nbok),'mesgs');
//$db->rollback();
$db->commit();
}
@ -217,10 +245,21 @@ if ($conf->societe->enabled)
// For products
if ($conf->product->enabled || $conf->product->service)
{
// Example 1 : Adding jquery code
print '<script type="text/javascript" language="javascript">
function confirm_erase() {
return confirm("'.dol_escape_js($langs->trans("ConfirmEraseAllCurrentBarCode")).'");
}
</script>';
$nbno=$nbtotal=0;
print_fiche_titre($langs->trans("BarcodeInitForProductsOrServices"),'','').'<br>'."\n";
$sql="SELECT count(rowid) as nb, fk_product_type FROM ".MAIN_DB_PREFIX."product where barcode IS NULL or barcode = '' GROUP BY fk_product_type";
$sql ="SELECT count(rowid) as nb, fk_product_type";
$sql.=" FROM ".MAIN_DB_PREFIX."product";
$sql.=" WHERE barcode IS NULL OR barcode = ''";
$sql.=" GROUP BY fk_product_type";
$sql.=" ORDER BY datec";
$resql=$db->query($sql);
if ($resql)
{
@ -263,12 +302,16 @@ if ($conf->product->enabled || $conf->product->service)
}
if (empty($nbno))
{
$disabled=1;
$titleno=$langs->trans("NoRecordWithoutBarcodeDefined");
print '<font class="ok">'.$langs->trans("NoRecordWithoutBarcodeDefined").'</font><br>';
$disabled1=1;
}
print '<br><input class="button" type="submit" id="submitformbarcodeproductgen" value="'.$langs->trans("InitEmptyBarCode",$nbno).'"'.($disabled?' disabled="disabled" title="'.dol_escape_htmltag($titleno).'"':'').'>';
print '<br>';
//print '<input type="checkbox" id="erasealreadyset" name="erasealreadyset"> '.$langs->trans("ResetBarcodeForAllRecords").'<br>';
$moretags1=(($disabled||$disabled1)?' disabled="disabled" title="'.dol_escape_htmltag($titleno).'"':'');
print '<input class="button" type="submit" name="submitformbarcodeproductgen" id="submitformbarcodeproductgen" value="'.$langs->trans("InitEmptyBarCode",min($maxperinit,$nbno)).'"'.$moretags1.'>';
$moretags2=(($nbno == $nbtotal)?' disabled="disabled"':'');
print ' &nbsp; ';
print '<input class="button" type="submit" name="eraseallbarcode" id="eraseallbarcode" value="'.$langs->trans("EraseAllCurrentBarCode").'"'.$moretags2.' onClick="return confirm_erase();">';
print '<br><br><br>';
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,9 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Note: Page can be call with param mode=sendremind to bring feature to send
* remind by emails.
*/
/**
@ -128,7 +131,7 @@ if ($action == 'presend' && GETPOST('sendmail'))
'__REFCLIENT__' => $object->thirdparty->name
);
make_substitutions($message, $substitutionarray);
$message=make_substitutions($message, $substitutionarray);
$actiontypecode='AC_FAC';
$actionmsg=$langs->transnoentities('MailSentBy').' '.$from.' '.$langs->transnoentities('To').' '.$sendto.".\n";

View File

@ -1264,9 +1264,10 @@ class Form
* @param string $selected_input_value Value of preselected input text (with ajax)
* @param int $hidelabel Hide label (0=no, 1=yes, 2=show search icon (before) and placeholder, 3 search icon after)
* @param array $ajaxoptions Options for ajax_autocompleter
* @param int $socid Thridparty Id
* @return void
*/
function select_produits($selected='', $htmlname='productid', $filtertype='', $limit=20, $price_level=0, $status=1, $finished=2, $selected_input_value='', $hidelabel=0, $ajaxoptions=array())
function select_produits($selected='', $htmlname='productid', $filtertype='', $limit=20, $price_level=0, $status=1, $finished=2, $selected_input_value='', $hidelabel=0, $ajaxoptions=array(),$socid=0)
{
global $langs,$conf;
@ -1285,6 +1286,10 @@ class Form
}
// mode=1 means customers products
$urloption='htmlname='.$htmlname.'&outjson=1&price_level='.$price_level.'&type='.$filtertype.'&mode=1&status='.$status.'&finished='.$finished;
//Price by customer
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) {
$urloption.='&socid='.$socid;
}
print ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 0, $ajaxoptions);
if (empty($hidelabel)) print $langs->trans("RefOrLabel").' : ';
else if ($hidelabel > 1) {
@ -1301,7 +1306,7 @@ class Form
}
else
{
print $this->select_produits_list($selected,$htmlname,$filtertype,$limit,$price_level,'',$status,$finished,0);
print $this->select_produits_list($selected,$htmlname,$filtertype,$limit,$price_level,'',$status,$finished,0,$socid);
}
}
@ -1317,9 +1322,10 @@ class Form
* @param int $status -1=Return all products, 0=Products not on sell, 1=Products on sell
* @param int $finished Filter on finished field: 2=No filter
* @param int $outputmode 0=HTML select string, 1=Array
* @param int $socid Thridparty Id
* @return array Array of keys for json
*/
function select_produits_list($selected='',$htmlname='productid',$filtertype='',$limit=20,$price_level=0,$filterkey='',$status=1,$finished=2,$outputmode=0)
function select_produits_list($selected='',$htmlname='productid',$filtertype='',$limit=20,$price_level=0,$filterkey='',$status=1,$finished=2,$outputmode=0,$socid=0)
{
global $langs,$conf,$user,$db;
@ -1328,6 +1334,13 @@ class Form
$sql = "SELECT ";
$sql.= " p.rowid, p.label, p.ref, p.description, p.fk_product_type, p.price, p.price_ttc, p.price_base_type, p.tva_tx, p.duration, p.stock";
//Price by customer
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) {
$sql.=' ,pcp.rowid as idprodcustprice, pcp.price as custprice, pcp.price_ttc as custprice_ttc,';
$sql.=' pcp.price_base_type as custprice_base_type, pcp.tva_tx as custtva_tx';
}
// Multilang : we add translation
if (! empty($conf->global->MAIN_MULTILANGS))
{
@ -1337,15 +1350,19 @@ class Form
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY))
{
$sql.= ", (SELECT pp.rowid FROM ".MAIN_DB_PREFIX."product_price as pp WHERE pp.fk_product = p.rowid";
if ($price_level >= 1) $sql.= " AND price_level=".$price_level;
if ($price_level >= 1 && !empty($conf->global->PRODUIT_MULTIPRICES)) $sql.= " AND price_level=".$price_level;
$sql.= " ORDER BY date_price";
$sql.= " DESC LIMIT 1) as price_rowid";
$sql.= ", (SELECT pp.price_by_qty FROM ".MAIN_DB_PREFIX."product_price as pp WHERE pp.fk_product = p.rowid";
if ($price_level >= 1) $sql.= " AND price_level=".$price_level;
if ($price_level >= 1 && !empty($conf->global->PRODUIT_MULTIPRICES)) $sql.= " AND price_level=".$price_level;
$sql.= " ORDER BY date_price";
$sql.= " DESC LIMIT 1) as price_by_qty";
}
$sql.= " FROM ".MAIN_DB_PREFIX."product as p";
//Price by customer
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) {
$sql.=" LEFT JOIN ".MAIN_DB_PREFIX."product_customer_price as pcp ON pcp.fk_soc=".$socid." AND pcp.fk_product=p.rowid";
}
// Multilang : we add translation
if (! empty($conf->global->MAIN_MULTILANGS))
{
@ -1407,7 +1424,7 @@ class Form
$optJson = array();
$objp = $this->db->fetch_object($result);
if (!empty($objp->price_by_qty) && $objp->price_by_qty == 1)
if (!empty($objp->price_by_qty) && $objp->price_by_qty == 1 && !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY))
{ // Price by quantity will return many prices for the same product
$sql = "SELECT rowid, quantity, price, unitprice, remise_percent, remise";
$sql.= " FROM ".MAIN_DB_PREFIX."product_price_by_qty";
@ -1523,7 +1540,7 @@ class Form
$found=0;
// Multiprice
if ($price_level >= 1) // If we need a particular price level (from 1 to 6)
if ($price_level >= 1 && $conf->global->PRODUIT_MULTIPRICES) // If we need a particular price level (from 1 to 6)
{
$sql = "SELECT price, price_ttc, price_base_type, tva_tx";
$sql.= " FROM ".MAIN_DB_PREFIX."product_price";
@ -1533,7 +1550,7 @@ class Form
$sql.= " ORDER BY date_price";
$sql.= " DESC LIMIT 1";
dol_syslog(get_class($this)."::constructProductListOption search price for level '.$price_level.' sql=".$sql);
dol_syslog(get_class($this).'::constructProductListOption search price for level '.$price_level.' sql='.$sql);
$result2 = $this->db->query($sql);
if ($result2)
{
@ -1564,7 +1581,7 @@ class Form
}
// Price by quantity
if (!empty($objp->quantity) && $objp->quantity >= 1)
if (!empty($objp->quantity) && $objp->quantity >= 1 && $conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)
{
$found = 1;
$outqty=$objp->quantity;
@ -1599,6 +1616,29 @@ class Form
$opt.=" - ".$langs->trans("Discount")." : ".vatrate($objp->remise_percent).' %';
$outval.=" - ".$langs->transnoentities("Discount")." : ".vatrate($objp->remise_percent).' %';
}
//Price by customer
if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
if (!empty($objp->idprodcustprice)) {
$found = 1;
if ($objp->custprice_base_type == 'HT')
{
$opt.= price($objp->custprice,1).' '.$currencytext.' '.$langs->trans("HT");
$outval.= price($objp->custprice,1).' '.$currencytextnoent.' '.$langs->transnoentities("HT");
}
else
{
$opt.= price($objp->custprice_ttc,1).' '.$currencytext.' '.$langs->trans("TTC");
$outval.= price($objp->custprice_ttc,1).' '.$currencytextnoent.' '.$langs->transnoentities("TTC");
}
$outprice_ht=price($objp->custprice);
$outprice_ttc=price($objp->custprice_ttc);
$outpricebasetype=$objp->custprice_base_type;
$outtva_tx=$objp->custtva_tx;
}
}
// If level no defined or multiprice not found, we used the default price
if (! $found)
@ -3735,7 +3775,7 @@ class Form
*
* @param string $htmlname Name of html select area
* @param array $array Array with key+value
* @param int $id Preselected key
* @param string $id Preselected key
* @param int $show_empty 1 si il faut ajouter une valeur vide dans la liste, 0 sinon
* @param int $key_in_label 1 pour afficher la key dans la valeur "[key] value"
* @param int $value_as_key 1 to use value as key

View File

@ -0,0 +1,465 @@
<?php
/* Copyright (C) 2001 Fabien Seisen <seisen@linuxfr.org>
* Copyright (C) 2002-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2004-2011 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
* Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
* Copyright (C) 2014 Raphaël Doursenaud <rdoursenaud@gpcsolutions.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/>.
*/
/**
* Class to manage Dolibarr database access for a Mysql database
*/
interface Database
{
/**
* Format a SQL IF
*
* @param string $test Test string (example: 'cd.statut=0', 'field IS NULL')
* @param string $resok resultat si test egal
* @param string $resko resultat si test non egal
* @return string SQL string
*/
function ifsql($test, $resok, $resko);
/**
* Return datas as an array
*
* @param Resultset $resultset Resultset of request
* @return array Array
*/
function fetch_row($resultset);
/**
* Convert (by PHP) a GM Timestamp date into a string date with PHP server TZ to insert into a date field.
* Function to use to build INSERT, UPDATE or WHERE predica
*
* @param string $param Date TMS to convert
* @return string Date in a string YYYYMMDDHHMMSS
*/
function idate($param);
/**
* Return last error code
*
* @return string lasterrno
*/
function lasterrno();
/**
* Start transaction
*
* @return int 1 if transaction successfuly opened or already opened, 0 if error
*/
function begin();
/**
* Create a new database
* Do not use function xxx_create_db (xxx=mysql, ...) as they are deprecated
* We force to create database with charset this->forcecharset and collate this->forcecollate
*
* @param string $database Database name to create
* @param string $charset Charset used to store data
* @param string $collation Charset used to sort data
* @param string $owner Username of database owner
* @return resource resource defined if OK, null if KO
*/
function DDLCreateDb($database, $charset = '', $collation = '', $owner = '');
/**
* Return version of database server into an array
*
* @return array Version array
*/
function getVersionArray();
/**
* Convert a SQL request in Mysql syntax to native syntax
*
* @param string $line SQL request line to convert
* @param string $type Type of SQL order ('ddl' for insert, update, select, delete or 'dml' for create, alter...)
* @return string SQL request line converted
*/
static function convertSQLFromMysql($line, $type = 'ddl');
/**
* Renvoie le nombre de lignes dans le resultat d'une requete INSERT, DELETE ou UPDATE
*
* @param resultset $resultset Curseur de la requete voulue
* @return int Nombre de lignes
* @see num_rows
*/
function affected_rows($resultset);
/**
* Return description of last error
*
* @return string Error text
*/
function error();
/**
* Return label of manager
*
* @return string Label
*/
function getLabel();
/**
* List tables into a database
*
* @param string $database Name of database
* @param string $table Nmae of table filter ('xxx%')
* @return resource Resource
*/
function DDLListTables($database, $table = '');
/**
* Return last request executed with query()
*
* @return string Last query
*/
function lastquery();
/**
* Define sort criteria of request
*
* @param string $sortfield List of sort fields
* @param string $sortorder Sort order
* @return string String to provide syntax of a sort sql string
*/
function order($sortfield = 0, $sortorder = 0);
/**
* Decrypt sensitive data in database
*
* @param string $value Value to decrypt
* @return string Decrypted value if used
*/
function decrypt($value);
/**
* Return datas as an array
*
* @param Resultset $resultset Resultset of request
* @return array Array
*/
function fetch_array($resultset);
/**
* Return last error label
*
* @return string lasterror
*/
function lasterror();
/**
* Escape a string to insert data
*
* @param string $stringtoencode String to escape
* @return string String escaped
*/
function escape($stringtoencode);
/**
* Get last ID after an insert INSERT
*
* @param string $tab Table name concerned by insert. Ne sert pas sous MySql mais requis pour compatibilite avec Postgresql
* @param string $fieldid Field name
* @return int Id of row
*/
function last_insert_id($tab, $fieldid = 'rowid');
/**
* Return full path of restore program
*
* @return string Full path of restore program
*/
function getPathOfRestore();
/**
* Annulation d'une transaction et retour aux anciennes valeurs
*
* @param string $log Add more log to default log line
* @return int 1 si annulation ok ou transaction non ouverte, 0 en cas d'erreur
*/
function rollback($log = '');
/**
* Execute a SQL request and return the resultset
*
* @param string $query SQL query string
* @param int $usesavepoint 0=Default mode, 1=Run a savepoint before and a rollbock to savepoint if error (this allow to have some request with errors inside global transactions).
* Note that with Mysql, this parameter is not used as Myssql can already commit a transaction even if one request is in error, without using savepoints.
* @param string $type Type of SQL order ('ddl' for insert, update, select, delete or 'dml' for create, alter...)
* @return resource Resultset of answer
*/
function query($query, $usesavepoint = 0, $type = 'auto');
/**
* Connexion to server
*
* @param string $host database server host
* @param string $login login
* @param string $passwd password
* @param string $name name of database (not used for mysql, used for pgsql)
* @param string $port Port of database server
* @return resource Database access handler
* @see close
*/
function connect($host, $login, $passwd, $name, $port = 0);
/**
* Define limits and offset of request
*
* @param int $limit Maximum number of lines returned (-1=conf->liste_limit, 0=no limit)
* @param int $offset Numero of line from where starting fetch
* @return string String with SQL syntax to add a limit and offset
*/
function plimit($limit = 0, $offset = 0);
/**
* Return value of server parameters
*
* @param string $filter Filter list on a particular value
* @return array Array of key-values (key=>value)
*/
function getServerParametersValues($filter = '');
/**
* Return value of server status
*
* @param string $filter Filter list on a particular value
* @return array Array of key-values (key=>value)
*/
function getServerStatusValues($filter = '');
/**
* Return collation used in database
*
* @return string Collation value
*/
function getDefaultCollationDatabase();
/**
* Return number of lines for result of a SELECT
*
* @param Resultset $resultset Resulset of requests
* @return int Nb of lines
* @see affected_rows
*/
function num_rows($resultset);
/**
* Return full path of dump program
*
* @return string Full path of dump program
*/
function getPathOfDump();
/**
* Return version of database client driver
*
* @return string Version string
*/
function getDriverInfo();
/**
* Return generic error code of last operation.
*
* @return string Error code (Exemples: DB_ERROR_TABLE_ALREADY_EXISTS, DB_ERROR_RECORD_ALREADY_EXISTS...)
*/
function errno();
/**
* Create a table into database
*
* @param string $table Nom de la table
* @param array $fields Tableau associatif [nom champ][tableau des descriptions]
* @param string $primary_key Nom du champ qui sera la clef primaire
* @param string $type Type de la table
* @param array $unique_keys Tableau associatifs Nom de champs qui seront clef unique => valeur
* @param array $fulltext_keys Tableau des Nom de champs qui seront indexes en fulltext
* @param string $keys Tableau des champs cles noms => valeur
* @return int <0 if KO, >=0 if OK
*/
function DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys = "", $fulltext_keys = "", $keys = "");
/**
* Return list of available charset that can be used to store data in database
*
* @return array List of Charset
*/
function getListOfCharacterSet();
/**
* Create a new field into table
*
* @param string $table Name of table
* @param string $field_name Name of field to add
* @param string $field_desc Tableau associatif de description du champ a inserer[nom du parametre][valeur du parametre]
* @param string $field_position Optionnel ex.: "after champtruc"
* @return int <0 if KO, >0 if OK
*/
function DDLAddField($table, $field_name, $field_desc, $field_position = "");
/**
* Drop a field from table
*
* @param string $table Name of table
* @param string $field_name Name of field to drop
* @return int <0 if KO, >0 if OK
*/
function DDLDropField($table, $field_name);
/**
* Update format of a field into a table
*
* @param string $table Name of table
* @param string $field_name Name of field to modify
* @param string $field_desc Array with description of field format
* @return int <0 if KO, >0 if OK
*/
function DDLUpdateField($table, $field_name, $field_desc);
/**
* Return list of available collation that can be used for database
*
* @return array List of Collation
*/
function getListOfCollation();
/**
* Return a pointer of line with description of a table or field
*
* @param string $table Name of table
* @param string $field Optionnel : Name of field if we want description of field
* @return resource Resource
*/
function DDLDescTable($table, $field = "");
/**
* Return version of database server
*
* @return string Version string
*/
function getVersion();
/**
* Return charset used to store data in database
*
* @return string Charset
*/
function getDefaultCharacterSetDatabase();
/**
* Create a user and privileges to connect to database (even if database does not exists yet)
*
* @param string $dolibarr_main_db_host Ip serveur
* @param string $dolibarr_main_db_user Nom user a creer
* @param string $dolibarr_main_db_pass Mot de passe user a creer
* @param string $dolibarr_main_db_name Database name where user must be granted
* @return int <0 if KO, >=0 if OK
*/
function DDLCreateUser(
$dolibarr_main_db_host,
$dolibarr_main_db_user,
$dolibarr_main_db_pass,
$dolibarr_main_db_name
);
/**
* Convert (by PHP) a PHP server TZ string date into a GM Timestamps date
* 19700101020000 -> 3600 with TZ+1
*
* @param string $string Date in a string (YYYYMMDDHHMMSS, YYYYMMDD, YYYY-MM-DD HH:MM:SS)
* @return date Date TMS
*/
function jdate($string);
/**
* Encrypt sensitive data in database
* Warning: This function includes the escape, so it must use direct value
*
* @param string $fieldorvalue Field name or value to encrypt
* @param int $withQuotes Return string with quotes
* @return string XXX(field) or XXX('value') or field or 'value'
*/
function encrypt($fieldorvalue, $withQuotes = 0);
/**
* Validate a database transaction
*
* @param string $log Add more log to default log line
* @return int 1 if validation is OK or transaction level no started, 0 if ERROR
*/
function commit($log = '');
/**
* List information of columns into a table.
*
* @param string $table Name of table
* @return array Tableau des informations des champs de la table
*/
function DDLInfoTable($table);
/**
* Free last resultset used.
*
* @param resultset $resultset Curseur de la requete voulue
* @return void
*/
function free($resultset = 0);
/**
* Close database connexion
*
* @return boolean True if disconnect successfull, false otherwise
* @see connect
*/
function close();
/**
* Return last query in error
*
* @return string lastqueryerror
*/
function lastqueryerror();
/**
* Return connexion ID
*
* @return string Id connexion
*/
function DDLGetConnectId();
/**
* Renvoie la ligne courante (comme un objet) pour le curseur resultset
*
* @param Resultset $resultset Curseur de la requete voulue
* @return Object Object result line or false if KO or end of cursor
*/
function fetch_object($resultset);
/**
* Select a database
*
* @param string $database Name of database
* @return boolean true if OK, false if KO
*/
function select_db($database);
}

View File

@ -1,6 +1,6 @@
<?php
/*
* Copyright (C) 2013 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
* Copyright (C) 2013-2014 Raphaël Doursenaud <rdoursenaud@gpcsolutions.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
@ -21,10 +21,12 @@
* \brief Class file to manage Dolibarr database access
*/
require_once DOL_DOCUMENT_ROOT .'/core/db/Database.interface.php';
/**
* Class to manage Dolibarr database access
*/
abstract class DoliDB
abstract class DoliDB implements Database
{
//! Database handler
public $db;
@ -92,6 +94,5 @@ abstract class DoliDB
return '';
}
}
}

View File

@ -237,6 +237,9 @@ class DoliDBMssql extends DoliDB
*/
function getDriverInfo()
{
// FIXME: Dummy method
// TODO: Implement
return '';
}
@ -310,15 +313,16 @@ class DoliDBMssql extends DoliDB
/**
* Annulation d'une transaction et retour aux anciennes valeurs
*
* @return int 1 si annulation ok ou transaction non ouverte, 0 en cas d'erreur
* @param string $log Add more log to default log line
* @return int 1 si annulation ok ou transaction non ouverte, 0 en cas d'erreur
*/
function rollback()
function rollback($log='')
{
if ($this->transaction_opened<=1)
{
$ret=$this->query("ROLLBACK TRANSACTION");
$this->transaction_opened=0;
dol_syslog("ROLLBACK Transaction",LOG_DEBUG);
dol_syslog("ROLLBACK Transaction".($log?' '.$log:''),LOG_DEBUG);
return $ret;
}
else
@ -804,6 +808,23 @@ class DoliDBMssql extends DoliDB
return $this->_results;
}
/**
* List information of columns into a table.
*
* @param string $table Name of table
* @return array Tableau des informations des champs de la table
*/
function DDLInfoTable($table)
{
// FIXME: Dummy method
// TODO: Implement
// May help: https://stackoverflow.com/questions/600446/sql-server-how-do-you-return-the-column-names-from-a-table
$infotables=array();
return $infotables;
}
/**
* Create a table into database
*
@ -975,6 +996,24 @@ class DoliDBMssql extends DoliDB
else return 1;
}
/**
* Create a user and privileges to connect to database (even if database does not exists yet)
*
* @param string $dolibarr_main_db_host Ip serveur
* @param string $dolibarr_main_db_user Nom user a creer
* @param string $dolibarr_main_db_pass Mot de passe user a creer
* @param string $dolibarr_main_db_name Database name where user must be granted
* @return int <0 if KO, >=0 if OK
*/
function DDLCreateUser($dolibarr_main_db_host,$dolibarr_main_db_user,$dolibarr_main_db_pass,$dolibarr_main_db_name)
{
// FIXME: Dummy method
// TODO: Implement
// May help: http://msdn.microsoft.com/fr-fr/library/ms173463.aspx
// Always fail for now
return -1;
}
/**
* Return charset used to store data in database
@ -983,15 +1022,9 @@ class DoliDBMssql extends DoliDB
*/
function getDefaultCharacterSetDatabase()
{
/*
$resql=$this->query('SHOW VARIABLES LIKE \'character_set_database\'');
if (!$resql)
{
return $this->forcecharset;
}
$liste=$this->fetch_array($resql);
return $liste['Value'];
*/
// FIXME: Dummy method
// TODO: Implement
return '';
}
@ -1002,25 +1035,10 @@ class DoliDBMssql extends DoliDB
*/
function getListOfCharacterSet()
{
/*
$resql=$this->query('SHOW CHARSET');
$liste = array();
if ($resql)
{
$i = 0;
while ($obj = $this->fetch_object($resql) )
{
$liste[$i]['charset'] = $obj->Charset;
$liste[$i]['description'] = $obj->Description;
$i++;
}
$this->free($resql);
} else {
return null;
}
return $liste;
*/
return ''; // attente debuggage
// FIXME: Dummy method
// TODO: Implement
return '';
}
/**
@ -1046,24 +1064,10 @@ class DoliDBMssql extends DoliDB
*/
function getListOfCollation()
{
/*
$resql=$this->query('SHOW COLLATION');
$liste = array();
if ($resql)
{
$i = 0;
while ($obj = $this->fetch_object($resql) )
{
$liste[$i]['collation'] = $obj->Collation;
$i++;
}
$this->free($resql);
} else {
return null;
}
return $liste;
*/
return ''; // attente debugage
// FIXME: Dummy method
// TODO: Implement
return '';
}
/**
@ -1073,6 +1077,8 @@ class DoliDBMssql extends DoliDB
*/
function getPathOfDump()
{
// FIXME: Dummy method
// TODO: Implement
return '';
}
@ -1084,9 +1090,42 @@ class DoliDBMssql extends DoliDB
*/
function getPathOfRestore()
{
// FIXME: Dummy method
// TODO: Implement
return '';
}
/**
* Return value of server parameters
*
* @param string $filter Filter list on a particular value
* @return array Array of key-values (key=>value)
*/
function getServerParametersValues($filter='')
{
// FIXME: Dummy method
// TODO: Implement
// May help: SELECT SERVERPROPERTY
$result=array();
return $result;
}
/**
* Return value of server status
*
* @param string $filter Filter list on a particular value
* @return array Array of key-values (key=>value)
*/
function getServerStatusValues($filter='')
{
// FIXME: Dummy method
// TODO: Implement
// May help: http://www.experts-exchange.com/Database/MS-SQL-Server/Q_20971756.html
return array();
}
}
?>

View File

@ -84,6 +84,7 @@ class DoliDBMysql extends DoliDB
{
global $conf,$langs;
// Note that having "static" property for "$forcecharset" and "$forcecollate" will make error here in strict mode, so they are not static
if (! empty($conf->db->character_set)) $this->forcecharset=$conf->db->character_set;
if (! empty($conf->db->dolibarr_main_db_collation)) $this->forcecollate=$conf->db->dolibarr_main_db_collation;
@ -1196,10 +1197,10 @@ class DoliDBMysql extends DoliDB
}
/**
* Return value of server parameters
* Return value of server parameters
*
* @param string $filter Filter list on a particular value
* @return string Value for parameter
* @param string $filter Filter list on a particular value
* @return array Array of key-values (key=>value)
*/
function getServerParametersValues($filter='')
{
@ -1218,17 +1219,17 @@ class DoliDBMysql extends DoliDB
}
/**
* Return value of server status
* Return value of server status
*
* @param string $filter Filter list on a particular value
* @return string Value for parameter
* @param string $filter Filter list on a particular value
* @return array Array of key-values (key=>value)
*/
function getServerStatusValues($filter='')
{
$result=array();
$sql='SHOW STATUS';
if ($filter) $sql.=" LIKE '".addslashes($filter)."'";
if ($filter) $sql.=" LIKE '".$this->escape($filter)."'";
$resql=$this->query($sql);
if ($resql)
{

View File

@ -84,9 +84,9 @@ class DoliDBMysqli extends DoliDB
{
global $conf,$langs;
// TODO error in strict mode (static property for "$forcecharset" and "$forcecollate")
//if (! empty($conf->db->character_set)) $this->forcecharset=$conf->db->character_set;
//if (! empty($conf->db->dolibarr_main_db_collation)) $this->forcecollate=$conf->db->dolibarr_main_db_collation;
// Note that having "static" property for "$forcecharset" and "$forcecollate" will make error here in strict mode, so they are not static
if (! empty($conf->db->character_set)) $this->forcecharset=$conf->db->character_set;
if (! empty($conf->db->dolibarr_main_db_collation)) $this->forcecollate=$conf->db->dolibarr_main_db_collation;
$this->database_user=$user;
@ -233,6 +233,16 @@ class DoliDBMysqli extends DoliDB
return $this->db;
}
/**
* Return label of manager
*
* @return string Label
*/
function getLabel()
{
return $this->label;
}
/**
* Return version of database server
*
@ -1190,10 +1200,10 @@ class DoliDBMysqli extends DoliDB
}
/**
* Return value of server parameters
* Return value of server parameters
*
* @param string $filter Filter list on a particular value
* @return string Value for parameter
* @param string $filter Filter list on a particular value
* @return array Array of key-values (key=>value)
*/
function getServerParametersValues($filter='')
{
@ -1212,17 +1222,17 @@ class DoliDBMysqli extends DoliDB
}
/**
* Return value of server status
* Return value of server status (current indicators on memory, cache...)
*
* @param string $filter Filter list on a particular value
* @return string Value for parameter
* @param string $filter Filter list on a particular value
* @return array Array of key-values (key=>value)
*/
function getServerStatusValues($filter='')
{
$result=array();
$sql='SHOW STATUS';
if ($filter) $sql.=" LIKE '".addslashes($filter)."'";
if ($filter) $sql.=" LIKE '".$this->escape($filter)."'";
$resql=$this->query($sql);
if ($resql)
{

View File

@ -85,6 +85,7 @@ class DoliDBPgsql extends DoliDB
{
global $conf,$langs;
// Note that having "static" property for "$forcecharset" and "$forcecollate" will make error here in strict mode, so they are not static
if (! empty($conf->db->character_set)) $this->forcecharset=$conf->db->character_set;
if (! empty($conf->db->dolibarr_main_db_collation)) $this->forcecollate=$conf->db->dolibarr_main_db_collation;
@ -466,6 +467,9 @@ class DoliDBPgsql extends DoliDB
*/
function getDriverInfo()
{
// FIXME: Dummy method
// TODO: Implement
return '';
}
@ -541,16 +545,17 @@ class DoliDBPgsql extends DoliDB
/**
* Annulation d'une transaction et retour aux anciennes valeurs
*
* @return int 1 si annulation ok ou transaction non ouverte, 0 en cas d'erreur
* @param string $log Add more log to default log line
* @return int 1 si annulation ok ou transaction non ouverte, 0 en cas d'erreur
*/
function rollback()
function rollback($log='')
{
dol_syslog('',0,-1);
if ($this->transaction_opened<=1)
{
$ret=$this->query("ROLLBACK;");
$this->transaction_opened=0;
dol_syslog("ROLLBACK Transaction",LOG_DEBUG);
dol_syslog("ROLLBACK Transaction".($log?' '.$log:''),LOG_DEBUG);
return $ret;
}
else
@ -1382,17 +1387,17 @@ class DoliDBPgsql extends DoliDB
}
/**
* Return value of server parameters
* Return value of server parameters
*
* @param string $filter Filter list on a particular value
* @return string Value for parameter
* @param string $filter Filter list on a particular value
* @return array Array of key-values (key=>value)
*/
function getServerParametersValues($filter='')
{
$result=array();
$resql='select name,setting from pg_settings';
if ($filter) $resql.=" WHERE name = '".addslashes($filter)."'";
if ($filter) $resql.=" WHERE name = '".$this->escape($filter)."'";
$resql=$this->query($resql);
if ($resql)
{
@ -1402,5 +1407,27 @@ class DoliDBPgsql extends DoliDB
return $result;
}
/**
* Return value of server status
*
* @param string $filter Filter list on a particular value
* @return array Array of key-values (key=>value)
*/
function getServerStatusValues($filter='')
{
/* This is to return current running requests.
$sql='SELECT datname,procpid,current_query FROM pg_stat_activity ORDER BY procpid';
if ($filter) $sql.=" LIKE '".$this->escape($filter)."'";
$resql=$this->query($sql);
if ($resql)
{
$obj=$this->fetch_object($resql);
$result[$obj->Variable_name]=$obj->Value;
}
*/
return array();
}
}
?>

View File

@ -84,6 +84,7 @@ class DoliDBSqlite extends DoliDB
{
global $conf,$langs;
// Note that having "static" property for "$forcecharset" and "$forcecollate" will make error here in strict mode, so they are not static
if (! empty($conf->db->character_set)) $this->forcecharset=$conf->db->character_set;
if (! empty($conf->db->dolibarr_main_db_collation)) $this->forcecollate=$conf->db->dolibarr_main_db_collation;
@ -389,6 +390,9 @@ class DoliDBSqlite extends DoliDB
*/
function getDriverInfo()
{
// FIXME: Dummy method
// TODO: Implement
return '';
}
@ -1305,10 +1309,10 @@ class DoliDBSqlite extends DoliDB
}
/**
* Return value of server parameters
* Return value of server parameters
*
* @param string $filter Filter list on a particular value
* @return string Value for parameter
* @param string $filter Filter list on a particular value
* @return array Array of key-values (key=>value)
*/
function getServerParametersValues($filter='')
{
@ -1327,17 +1331,17 @@ class DoliDBSqlite extends DoliDB
}
/**
* Return value of server status
* Return value of server status
*
* @param string $filter Filter list on a particular value
* @return string Value for parameter
* @param string $filter Filter list on a particular value
* @return array Array of key-values (key=>value)
*/
function getServerStatusValues($filter='')
{
$result=array();
$sql='SHOW STATUS';
if ($filter) $sql.=" LIKE '".addslashes($filter)."'";
if ($filter) $sql.=" LIKE '".$this->escape($filter)."'";
$resql=$this->query($sql);
if ($resql)
{

View File

@ -3,7 +3,7 @@
* Copyright (C) 2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2007 Patrick Raguin <patrick.raguin@gmail.com>
* Copyright (C) 2010-2012 Regis Houssin <regis.houssin@capnetworks.com>
* Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2013-2014 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2013 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2013 Christophe Battarel <contact@altairis.fr>
* Copyright (C) 2013 Alexandre Spangaro <alexandre.spangaro@gmail.com>
@ -136,6 +136,16 @@ function societe_prepare_head($object)
$h++;
}
if (($object->client==1 || $object->client==2 || $object->client==3) && (! empty ( $conf->global->PRODUIT_CUSTOMER_PRICES )))
{
$langs->load("products");
// price
$head[$h][0] = DOL_URL_ROOT.'/societe/price.php?socid='.$object->id;
$head[$h][1] = $langs->trans("CustomerPrices");
$head[$h][2] = 'price';
$h++;
}
// Log
$head[$h][0] = DOL_URL_ROOT.'/societe/info.php?socid='.$object->id;
$head[$h][1] = $langs->trans("Info");

View File

@ -2868,7 +2868,7 @@ function get_localtax($tva, $local, $thirdparty_buyer="", $thirdparty_seller="")
global $db, $conf, $mysoc;
if (empty($thirdparty_seller) || ! is_object($thirdparty_seller)) $thirdparty_seller=$mysoc;
dol_syslog("get_localtax tva=".$tva." local=".$local." thirdparty_buyer id=".(is_object($thirdparty_buyer)?$thirdparty_buyer->id:'')."/country_code=".(is_object($thirdparty_buyer)?$thirdparty_buyer->country_code:'')." thirdparty_seller id=".$thirdparty_seller->id."/country_code=".$thirdparty_seller->country_code." thirdparty_seller localtax1_assuj=".$thirdparty_seller->localtax1_assuj." thirdparty_seller localtax2_assuj=".$thirdparty_seller->localtax2_assuj);
// Some test to guess with no need to make database access

View File

@ -270,7 +270,7 @@ class modSociete extends DolibarrModules
$this->export_TypeFields_array[$r]=array('s.nom'=>"Text",'s.status'=>"Number",'s.client'=>"Boolean",'s.fournisseur'=>"Boolean",'s.datec'=>"Date",'s.tms'=>"Date",'s.code_client'=>"Text",'s.code_fournisseur'=>"Text",'s.code_compta'=>"Text",'s.code_compta_fournisseur'=>"Text",'s.address'=>"Text",'s.zip'=>"Text",'s.town'=>"Text",'p.libelle'=>"List:c_pays:libelle:libelle",'p.code'=>"Text",'s.phone'=>"Text",'s.fax'=>"Text",'s.url'=>"Text",'s.email'=>"Text",'s.default_lang'=>"Text",'s.siret'=>"Text",'s.siren'=>"Text",'s.ape'=>"Text",'s.idprof4'=>"Text",'s.idprof5'=>"Text",'s.idprof6'=>"Text",'s.tva_intra'=>"Text",'s.capital'=>"Number",'s.note_private'=>"Text",'s.note_public'=>"Text",'t.libelle'=>"Text",'ce.code'=>"List:c_effectif:libelle:code","cfj.libelle"=>"Text",'s.fk_prospectlevel'=>'List:c_prospectlevel:label:code','st.code'=>'List:c_stcomm:libelle:code','d.nom'=>'Text');
$this->export_entities_array[$r]=array(); // We define here only fields that use another picto
// Add extra fields
$sql="SELECT name, label, type FROM ".MAIN_DB_PREFIX."extrafields WHERE elementtype = 'societe'";
$sql="SELECT name, label, type, param FROM ".MAIN_DB_PREFIX."extrafields WHERE elementtype = 'societe'";
$resql=$this->db->query($sql);
if ($resql) // This can fail when class is used on old database (during migration for example)
{

View File

@ -107,7 +107,7 @@ if (! empty($conf->margin->enabled)) {
'select_type'
)
);
$form->select_produits('', 'idprod', '', $conf->product->limit_size, $buyer->price_level, 1, 2, '', 3, $ajaxoptions);
$form->select_produits('', 'idprod', '', $conf->product->limit_size, $buyer->price_level, 1, 2, '', 3, $ajaxoptions,$buyer->id);
}
?>
<span id="add_product_area" class="hideobject"> | <input type="checkbox" id="add_product_checkbox" name="add_product" value="1" />
@ -270,6 +270,9 @@ $(document).ready(function() {
'id': $(this).val(),
'price_level': <?php echo empty($buyer->price_level)?1:$buyer->price_level; ?>,
'pbq': $("option:selected", this).attr('pbq')
<?php if (! empty ( $conf->global->PRODUIT_CUSTOMER_PRICES )) {?>
,'socid': <?php echo $buyer->id; ?>
<?php }?>
},
function(data) {
if (typeof data != 'undefined') {

View File

@ -101,7 +101,7 @@ else {
echo '<span>';
$filtertype='';
if (! empty($object->element) && $object->element == 'contrat') $filtertype='1';
$form->select_produits('','idprod',$filtertype,$conf->product->limit_size,$buyer->price_level);
$form->select_produits('','idprod',$filtertype,$conf->product->limit_size,$buyer->price_level, 1, 2, '', 3, array(),$buyer->id);
echo '</span>';
if (is_object($hookmanager))

View File

@ -618,6 +618,15 @@ class InterfaceActionsAuto
if ($ok)
{
$now=dol_now();
if(isset($_SESSION['listofnames']))
{
$attachs=$_SESSION['listofnames'];
if($attachs && strpos($action,'SENTBYMAIL'))
{
$object->actionmsg.="\n".$langs->transnoentities("AttachedFiles").': '.$attachs;
}
}
require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';

View File

@ -31,7 +31,6 @@ require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/modules/fichinter/modules_fichinter.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/fichinter.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT . '/core/class/html.formcontract.class.php';
if (! empty($conf->projet->enabled))
{
@ -858,7 +857,8 @@ if (! empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && $user->rights->ficheint
$form = new Form($db);
$formfile = new FormFile($db);
$formcontract = new FormContract($db);
if ($conf->contrat->enabled)
$formcontract = new FormContract($db);
llxHeader('',$langs->trans("Fichinter"));
@ -983,7 +983,7 @@ if ($action == 'create')
$numprojet=$formproject->select_projects($soc->id,GETPOST('projectid','int'),'projectid');
if ($numprojet==0)
{
print ' &nbsp; <a href="'.DOL_DOCUMENT_ROOT.'/projet/fiche.php?socid='.$soc->id.'&action=create">'.$langs->trans("AddProject").'</a>';
print ' &nbsp; <a href="'.DOL_URL_ROOT.'/projet/fiche.php?socid='.$soc->id.'&action=create">'.$langs->trans("AddProject").'</a>';
}
print '</td></tr>';
}

View File

@ -957,3 +957,56 @@ INSERT INTO llx_accountingaccount (fk_pcg_version, pcg_type, pcg_subtype, accoun
INSERT INTO llx_accountingaccount (fk_pcg_version, pcg_type, pcg_subtype, account_number, account_parent, label, active) VALUE ('PCMN-BASE', 'PROD', 'XXXXXX', '793', '79', 'Perte à reporter', '1');
INSERT INTO llx_accountingaccount (fk_pcg_version, pcg_type, pcg_subtype, account_number, account_parent, label, active) VALUE ('PCMN-BASE', 'PROD', 'XXXXXX', '794', '79', 'Intervention d''associés (ou du propriétaire) dans la perte', '1');
ALTER TABLE llx_projet_task ADD COLUMN entity integer DEFAULT 1 NOT NULL AFTER ref;
create table llx_product_customer_price
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
entity integer DEFAULT 1 NOT NULL, -- multi company id
datec datetime,
tms timestamp,
fk_product integer NOT NULL,
fk_soc integer NOT NULL,
price double(24,8) DEFAULT 0,
price_ttc double(24,8) DEFAULT 0,
price_min double(24,8) DEFAULT 0,
price_min_ttc double(24,8) DEFAULT 0,
price_base_type varchar(3) DEFAULT 'HT',
tva_tx double(6,3),
recuperableonly integer NOT NULL DEFAULT '0', -- Other NPR VAT
localtax1_tx double(6,3) DEFAULT 0, -- Other local VAT 1
localtax2_tx double(6,3) DEFAULT 0, -- Other local VAT 2
fk_user integer,
import_key varchar(14) -- Import key
)ENGINE=innodb;
ALTER TABLE llx_product_customer_price ADD INDEX idx_product_customer_price_fk_user (fk_user);
ALTER TABLE llx_product_customer_price ADD CONSTRAINT fk_product_customer_price_fk_user FOREIGN KEY (fk_user) REFERENCES llx_user (rowid);
ALTER TABLE llx_product_customer_price ADD UNIQUE INDEX uk_customer_price_fk_product_fk_soc (fk_product, fk_soc);
ALTER TABLE llx_product_customer_price ADD CONSTRAINT fk_customer_price_fk_product FOREIGN KEY (fk_product) REFERENCES llx_product(rowid) ON DELETE CASCADE;
ALTER TABLE llx_product_customer_price ADD CONSTRAINT fk_customer_price_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe(rowid) ON DELETE CASCADE;
create table llx_product_customer_price_log
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
entity integer DEFAULT 1 NOT NULL, -- multi company id
datec datetime,
fk_product integer NOT NULL,
fk_soc integer NOT NULL,
price double(24,8) DEFAULT 0,
price_ttc double(24,8) DEFAULT 0,
price_min double(24,8) DEFAULT 0,
price_min_ttc double(24,8) DEFAULT 0,
price_base_type varchar(3) DEFAULT 'HT',
tva_tx double(6,3),
recuperableonly integer NOT NULL DEFAULT '0', -- Other NPR VAT
localtax1_tx double(6,3) DEFAULT 0, -- Other local VAT 1
localtax2_tx double(6,3) DEFAULT 0, -- Other local VAT 2
fk_user integer,
import_key varchar(14) -- Import key
)ENGINE=innodb;

View File

@ -0,0 +1,30 @@
-- ============================================================================
-- Copyright (C) 2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
-- Copyright (C) 2005-2012 Laurent Destailleur <eldy@users.sourceforge.net>
-- Copyright (C) 2009-2012 Regis Houssin <regis.houssin@capnetworks.com>
-- Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
--
-- 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_product_customer_price ADD INDEX idx_product_customer_price_fk_user (fk_user);
ALTER TABLE llx_product_customer_price ADD CONSTRAINT fk_product_customer_price_fk_user FOREIGN KEY (fk_user) REFERENCES llx_user (rowid);
ALTER TABLE llx_product_customer_price ADD UNIQUE INDEX uk_customer_price_fk_product_fk_soc (fk_product, fk_soc);
ALTER TABLE llx_product_customer_price ADD CONSTRAINT fk_customer_price_fk_product FOREIGN KEY (fk_product) REFERENCES llx_product(rowid) ON DELETE CASCADE;
ALTER TABLE llx_product_customer_price ADD CONSTRAINT fk_customer_price_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe(rowid) ON DELETE CASCADE;

View File

@ -0,0 +1,42 @@
-- ============================================================================
-- Copyright (C) 2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
-- Copyright (C) 2009-2011 Laurent Destailleur <eldy@users.sourceforge.net>
-- Copyright (C) 2009-2013 Regis Houssin <regis.houssin@capnetworks.com>
-- Copyright (C) 2012 Juanjo Menent <jmenent@2byte.es>
-- Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
--
-- 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_product_customer_price
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
entity integer DEFAULT 1 NOT NULL, -- multi company id
datec datetime,
tms timestamp,
fk_product integer NOT NULL,
fk_soc integer NOT NULL,
price double(24,8) DEFAULT 0,
price_ttc double(24,8) DEFAULT 0,
price_min double(24,8) DEFAULT 0,
price_min_ttc double(24,8) DEFAULT 0,
price_base_type varchar(3) DEFAULT 'HT',
tva_tx double(6,3),
recuperableonly integer NOT NULL DEFAULT '0', -- Other NPR VAT
localtax1_tx double(6,3) DEFAULT 0, -- Other local VAT 1
localtax2_tx double(6,3) DEFAULT 0, -- Other local VAT 2
fk_user integer,
import_key varchar(14) -- Import key
)ENGINE=innodb;

View File

@ -0,0 +1,39 @@
-- ============================================================================
-- Copyright (C) 2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
-- Copyright (C) 2009 Laurent Destailleur <eldy@users.sourceforge.net>
-- Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
--
-- 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_product_customer_price_log
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
entity integer DEFAULT 1 NOT NULL, -- multi company id
datec datetime,
fk_product integer NOT NULL,
fk_soc integer NOT NULL,
price double(24,8) DEFAULT 0,
price_ttc double(24,8) DEFAULT 0,
price_min double(24,8) DEFAULT 0,
price_min_ttc double(24,8) DEFAULT 0,
price_base_type varchar(3) DEFAULT 'HT',
tva_tx double(6,3),
recuperableonly integer NOT NULL DEFAULT '0', -- Other NPR VAT
localtax1_tx double(6,3) DEFAULT 0, -- Other local VAT 1
localtax2_tx double(6,3) DEFAULT 0, -- Other local VAT 2
fk_user integer,
import_key varchar(14) -- Import key
)ENGINE=innodb;

View File

@ -21,6 +21,7 @@ create table llx_projet_task
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
ref varchar(50),
entity integer DEFAULT 1 NOT NULL, -- multi company id
fk_projet integer NOT NULL,
fk_task_parent integer DEFAULT 0 NOT NULL,
datec datetime, -- date creation

View File

@ -380,12 +380,16 @@ DefaultLink=Default link
ValueOverwrittenByUserSetup=Warning, this value may be overwritten by user specific setup (each user can set his own clicktodial url)
ExternalModule=External module - Installed into directory %s
BarcodeInitForThirdparties=Mass barcode init for thirdparties
BarcodeInitForProductsOrServices=Mass barcode init for products or services
BarcodeInitForProductsOrServices=Mass barcode init or reset for products or services
CurrentlyNWithoutBarCode=Currently, you have <strong>%s</strong> records on <strong>%s</strong> %s without barcode defined.
InitEmptyBarCode=Init the %s barcode
InitEmptyBarCode=Init value for next %s empty records
EraseAllCurrentBarCode=Erase all current barcode values
ConfirmEraseAllCurrentBarCode=Are you sure you want to erase all current barcode values ?
AllBarcodeReset=All barcode values have been removed
NoBarcodeNumberingTemplateDefined=No numbering barcode template enabled into barcode module setup.
NoRecordWithoutBarcodeDefined=No record with no barcode value defined.
# Modules
Module0Name=Users & groups
Module0Desc=Users and groups management

View File

@ -220,5 +220,10 @@ DefinitionOfBarCodeForProductNotComplete=Definition of type or value of bar code
DefinitionOfBarCodeForThirdpartyNotComplete=Definition of type or value of bar code non complete for thirdparty %s.
BarCodeDataForProduct=Barcode information of product %s :
BarCodeDataForThirdparty=Barcode information of thirdparty %s :
BarcodeStickersMask=xxx
ResetBarcodeForAllRecords=Define barcode value for all records (this will also reset barcode value already defined with new values)
PriceByCustomer=Price by customer
PriceCatalogue=Catalogue Price
PricingRule=Pricing Rules
AddCustomerPrice=Add price by customers
ForceUpdateChildPriceSoc=Set same price on customer subsidiaries
PriceByCustomerLog=Price by customer log

View File

@ -287,7 +287,7 @@ CurrentVersion=Versión actual de Dolibarr
CallUpdatePage=Llamar a la página de actualización de la estructura y datos de la base de datos %s.
LastStableVersion=Última versión estable disponible
GenericMaskCodes=Puede introducir cualquier máscara numérica. En esta máscara, puede utilizar las siguientes etiquetas:<br><b>{000000} </b> corresponde a un número que se incrementa en cada uno de %s. Introduzca tantos ceros como longitud desee mostrar. El contador se completará a partir de ceros por la izquierda con el fin de tener tantos ceros como la máscara. <br> <b> {000000+000}</ b> Igual que el anterior, con una compensación correspondiente al número a la derecha del signo + se aplica a partir del primer %s. <br> <b> {000000@x}</b> igual que el anterior, pero el contador se restablece a cero cuando se llega a x meses (x entre 1 y 12). Si esta opción se utiliza y x es de 2 o superior, entonces la secuencia {yy}{mm} o {yyyy}{mm} también es necesaria. <br> <b> {dd} </b> días (01 a 31). <br><b> {mm}</b> mes (01 a 12). <br><b>{yy}</b>, <b>{yyyy}</b> ou <b>{y}</b> año en 2, 4 ó 1 cifra.<br>
# GenericMaskCodes2=<b>{cccc}</b> the client code<br><b>{cccc000}</b> the client code on n characters is followed by a client's ref counter without offset and zeroized with the global counter.<br><b>{tttt}</b> The code of company type on n characters (see dictionary-company types).<br>
GenericMaskCodes2=<b>{cccc}</b> el código de cliente en n caracteres<br><b>{cccc000}</b> el código de cliente en n caracteres es seguido por un contador propio al cliente sin offset, completado con ceros hasta completar la máscara, y volviendo a cero al mismo tiempo que el contador global.<br><b>{tttt}</b>El código del tipo de la empresa en n caracteres (ver diccionarios-tipos de empresas).<br>
GenericMaskCodes3=Cualquier otro carácter en la máscara se quedará sin cambios. <br>No se permiten espacios <br>
GenericMaskCodes4a=<u>Ejemplo en la 99 ª %s del tercero La Empresa realizada el 31/03/2007: </u><br>
GenericMaskCodes4b=<u>Ejemplo sobre un tercero creado el 31/03/2007:</u><br>

View File

@ -359,7 +359,7 @@ IntracommunityVATNumber=Número de IVA intracomunitario
PaymentByChequeOrderedTo=Pago mediante cheque nominativo a %s enviado a
PaymentByChequeOrderedToShort=Pago mediante cheque nominativo a
SendTo=enviado a
PaymentByTransferOnThisBankAccount=Pago mediante trasferencia sobre la cuenta bancaria siguiente
PaymentByTransferOnThisBankAccount=Pago mediante transferencia a la cuenta bancaria siguiente
VATIsNotUsedForInvoice=* IVA no aplicable art-293B del CGI
LawApplicationPart1=Por aplicación de la ley 80.335 de 12/05/80
LawApplicationPart2=las mercancías permanecen en propiedad de

View File

@ -102,14 +102,14 @@ NbOfLinesImported=Número de líneas correctamente importadas: <b>%s</b>.
DataComeFromNoWhere=El valor a insertar no corresponde a ningún campo del archivo origen.
DataComeFromFileFieldNb=El valor a insertar se corresponde al campo número <b>%s</b> del archivo origen.
DataComeFromIdFoundFromRef=El valor dado por el campo <b>%s</b> del archivo origen será utilizado para encontrar el ID del objeto padre a usar (el objeto <b>%s</b> con la referencia del archivo origen debe existir en Dolibarr).
# DataComeFromIdFoundFromCodeId=Code that comes from field number <b>%s</b> of source file will be used to find id of parent object to use (So the code from source file must exists into dictionary <b>%s</b>). Note that if you know id, you can also use it into source file instead of code. Import should work in both cases.
DataComeFromIdFoundFromCodeId=El código del campo número <b>%s</b> del archivo de origen se utilizará para encontrar el id del objeto padre a usar (el código del archivo de origen debe existir en el diccionario <b>%s</b>). Tenga en cuenta que si conoce el id, puede usarlo en lugar del código en el archivo de origen. La importación funcionará en los 2 casos.
DataIsInsertedInto=Los datos del archivo de origen se insertarán en el siguiente campo:
DataIDSourceIsInsertedInto=El ID del objeto padre encontrado a partir del dato origen, se insertará en el siguiente campo:
DataCodeIDSourceIsInsertedInto=El id de la línea padre encontrada a partir del código, se insertará en el siguiente campo:
SourceRequired=Datos de origen obligatorios
SourceExample=Ejemplo de datos de origen posibles
ExampleAnyRefFoundIntoElement=Todas las referencias encontradas para los elementos <b>%s</b>
# ExampleAnyCodeOrIdFoundIntoDictionary=Any code (or id) found into dictionary <b>%s</b>
ExampleAnyCodeOrIdFoundIntoDictionary=Cualquier código (o identificador) encontrado en el diccionario <b>%s</b>
CSVFormatDesc=Archivo con formato <b>Valores separados por coma</b> (.csv).<br>Es un fichero con formato de texto en el que los campos son separados por el carácter [ %s ]. Si el separador se encuentra en el contenido de un campo, El campo debe de estar acotado por el carácter [ %s ]. El carácter de escape para incluir un carácter de entorno en un dato es [ %s ].
Excel95FormatDesc=Archivo con formato <b>Excel</b> (.xls)<br>Este es el formato nativo de Excel 95 (BIFF5).
Excel2007FormatDesc=Archivo con formato <b>Excel</b> (.xlsx)<br>Este es el formato nativo de Excel 2007 (SpreadsheetML).

View File

@ -173,8 +173,8 @@ CustomCode=Código aduanero
CountryOrigin=País de origen
HiddenIntoCombo=Oculto en las listas
Nature=Naturaleza
ProductCodeModel=Modelo de código de producto
ServiceCodeModel=Modelo de código de servicio
ProductCodeModel=Modelo de ref. de producto
ServiceCodeModel=Modelo de ref. de servicio
AddThisProductCard=Crear ficha producto
HelpAddThisProductCard=Esta opción permite crear o clonar una ficha de producto en caso de que no exista
AddThisServiceCard=Crear ficha servicio

View File

@ -94,14 +94,20 @@ DesiredStock=Stock deseado
StockToBuy=A pedir
Replenishment=Reaprovisionamiento
ReplenishmentOrders=Ordenes de reaprovisionamiento
UseVirtualStock=Usar stock virtual en lugar de stock físico
VirtualDiffersFromPhysical=De acuerdo con las opciones de incremento/decremento de stock, el stock físico y el stock virtual (físico + pedidos actuales) puede diferir
UseVirtualStockByDefault=Usar stock virtual por defecto, en lugar de stock físico, para la funcionalidad de aprovisionamiento
UseVirtualStock=Usar stock virtual
UsePhysicalStock=Usar stock físico
CurentSelectionMode=Modo de selección actual
CurentlyUsingVirtualStock=Stock virtual
CurentlyUsingPhysicalStock=Stock físico
RuleForStockReplenishment=Regla para el reaprovisionamiento de stock
SelectProductWithNotNullQty=Seleccie al menos un producto con una cantidad distinta de cero y un proveedor
AlertOnly= Sólo alertas
WarehouseForStockDecrease=Para el decremento de stock se usará el almacén <b>%s</b>
WarehouseForStockIncrease=Para el incremento de stock se usará el almacén <b>%s</b>
ForThisWarehouse=Para este almacén
ReplenishmentStatusDesc=Este listado le permite ver productos con un stock inferior a la cantidad mínima deseada (o valor de alerta si el checkbok "Sólo alertas" está activado) y le sugiere crear los pedidos a proveedores para completar la diferencia.
ReplenishmentStatusDesc=Esta es la lista de todos los productos con un stock menor que el stock deseado (o menor que el valor de alerta si el checkbox "sólo alertas" está marcado) y que sugiere crear pedidos de proveedor para rellenar la diferencia.
ReplenishmentOrdersDesc=Este es el listado de pedidos a proveedores en curso
Replenishments=Reaprovisionamiento
NbOfProductBeforePeriod=Cantidad del producto %s en stock antes del periodo seleccionado (< %s)

View File

@ -217,4 +217,9 @@ DefinitionOfBarCodeForThirdpartyNotComplete=Définition du type ou valeure du co
BarCodeDataForProduct=Information de code barre du produit %s :
BarCodeDataForThirdparty=Information de code barre du tiers %s :
BarcodeStickersMask=xxx
PriceByCustomer=Prix par clients
PriceCatalogue=Prix unique
PricingRule=Régles de prix
AddCustomerPrice=Ajouter un prix par client
ForceUpdateChildPriceSoc=Mettre le même prix pour les filliales
PriceByCustomerLog=Historique prix par client

View File

@ -42,6 +42,17 @@ if (! $user->admin || (empty($conf->product->enabled) && empty($conf->service->e
$action = GETPOST('action','alpha');
$value = GETPOST('value','alpha');
// Pricing Rules
$select_pricing_rules=array(
'PRODUCT_PRICE_UNIQ'=>$langs->trans('PriceCatalogue'),
'PRODUIT_MULTIPRICES'=>$langs->trans('MultiPricesAbility'),
'PRODUIT_CUSTOMER_PRICES'=>$langs->trans('PriceByCustomer')
);
if ($conf->global->MAIN_FEATURES_LEVEL==2) {
$select_pricing_rules['PRODUIT_CUSTOMER_PRICES_BY_QTY'] = $langs->trans('PriceByQuantity');
$select_pricing_rules['PRODUIT_CUSTOMER_PRICES_BY_QTY&PRODUIT_MULTIPRICES'] = $langs->trans('MultiPricesAbility') . '+' . $langs->trans('PriceByQuantity');
}
/*
* Actions
@ -96,12 +107,33 @@ else if ($action == 'multiprix_num')
{
$res = dolibarr_set_const($db, "PRODUIT_MULTIPRICES_LIMIT", $value,'chaine',0,'',$conf->entity);
}
if ($action == 'multiprix')
if ($action == 'pricingrule')
{
$multiprix = GETPOST('activate_multiprix','alpha');
$princingrules = GETPOST('princingrule','alpha');
foreach ($select_pricing_rules as $rule=>$label) {
$res = dolibarr_set_const($db, "PRODUIT_MULTIPRICES", $multiprix,'chaine',0,'',$conf->entity);
$res =dolibarr_set_const($db, "PRODUIT_MULTIPRICES_LIMIT", "5",'chaine',0,'',$conf->entity);
if ($rule==$princingrules) {
if ( $princingrules =='PRODUCT_PRICE_UNIQ') {
$res = dolibarr_set_const($db, 'PRODUIT_MULTIPRICES', 0,'chaine',0,'',$conf->entity);
$res = dolibarr_set_const($db, 'PRODUIT_CUSTOMER_PRICES_BY_QTY', 0,'chaine',0,'',$conf->entity);
$res = dolibarr_set_const($db, 'PRODUIT_CUSTOMER_PRICES', 0,'chaine',0,'',$conf->entity);
} else {
$multirule=explode('&',$princingrules);
if (is_array($multirule) && count($multirule)>0) {
foreach($multirule as $rulesselected) {
$res = dolibarr_set_const($db, $rulesselected, 1,'chaine',0,'',$conf->entity);
}
} else {
$res = dolibarr_set_const($db, $rule, 1,'chaine',0,'',$conf->entity);
}
}
} else {
if (strpos($rule,'&')===false) {
$res = dolibarr_set_const($db, $rule, 0,'chaine',0,'',$conf->entity);
}
}
}
}
else if ($action == 'sousproduits')
{
@ -278,15 +310,20 @@ print '<td width="80">&nbsp;</td></tr>'."\n";
* Formulaire parametres divers
*/
// multiprix activation/desactivation
$var=!$var;
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
print '<input type="hidden" name="action" value="multiprix">';
print '<input type="hidden" name="action" value="pricingrule">';
print '<tr '.$bc[$var].'>';
print '<td>'.$langs->trans("MultiPricesAbility").'</td>';
print '<td>'.$langs->trans("PricingRule").'</td>';
print '<td width="60" align="right">';
print $form->selectyesno("activate_multiprix",$conf->global->PRODUIT_MULTIPRICES,1);
$current_rule = 'PRODUCT_PRICE_UNIQ';
if (!empty($conf->global->PRODUIT_MULTIPRICES)) $current_rule='PRODUIT_MULTIPRICES';
if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) $current_rule='PRODUIT_CUSTOMER_PRICES_BY_QTY';
if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) $current_rule='PRODUIT_CUSTOMER_PRICES';
if ((!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) && (!empty($conf->global->PRODUIT_MULTIPRICES)))$current_rule='PRODUIT_CUSTOMER_PRICES_BY_QTY&PRODUIT_MULTIPRICES';
print $form->selectarray("princingrule",$select_pricing_rules,$current_rule);
print '</td><td align="right">';
print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
print '</td>';

View File

@ -18,156 +18,176 @@
*/
/**
* \file htdocs/product/ajax/products.php
* \brief File to return Ajax response on product list request
* \file htdocs/product/ajax/products.php
* \brief File to return Ajax response on product list request
*/
if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL',1); // Disables token renewal
if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1');
if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1');
if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1');
if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1');
if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1');
if (empty($_GET['keysearch']) && ! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1');
if (! defined('NOTOKENRENEWAL'))
define('NOTOKENRENEWAL', 1); // Disables token renewal
if (! defined('NOREQUIREMENU'))
define('NOREQUIREMENU', '1');
if (! defined('NOREQUIREHTML'))
define('NOREQUIREHTML', '1');
if (! defined('NOREQUIREAJAX'))
define('NOREQUIREAJAX', '1');
if (! defined('NOREQUIRESOC'))
define('NOREQUIRESOC', '1');
if (! defined('NOCSRFCHECK'))
define('NOCSRFCHECK', '1');
if (empty($_GET ['keysearch']) && ! defined('NOREQUIREHTML'))
define('NOREQUIREHTML', '1');
require '../../main.inc.php';
$htmlname=GETPOST('htmlname','alpha');
$socid=GETPOST('socid','int');
$type=GETPOST('type','int');
$mode=GETPOST('mode','int');
$status=((GETPOST('status','int') >= 0) ? GETPOST('status','int') : -1);
$outjson=(GETPOST('outjson','int') ? GETPOST('outjson','int') : 0);
$price_level=GETPOST('price_level','int');
$action=GETPOST('action', 'alpha');
$id=GETPOST('id', 'int');
$price_by_qty_rowid=GETPOST('pbq', 'int');
$htmlname = GETPOST('htmlname', 'alpha');
$socid = GETPOST('socid', 'int');
$type = GETPOST('type', 'int');
$mode = GETPOST('mode', 'int');
$status = ((GETPOST('status', 'int') >= 0) ? GETPOST('status', 'int') : - 1);
$outjson = (GETPOST('outjson', 'int') ? GETPOST('outjson', 'int') : 0);
$price_level = GETPOST('price_level', 'int');
$action = GETPOST('action', 'alpha');
$id = GETPOST('id', 'int');
$price_by_qty_rowid = GETPOST('pbq', 'int');
/*
* View
*/
//print '<!-- Ajax page called with url '.$_SERVER["PHP_SELF"].'?'.$_SERVER["QUERY_STRING"].' -->'."\n";
// print '<!-- Ajax page called with url '.$_SERVER["PHP_SELF"].'?'.$_SERVER["QUERY_STRING"].' -->'."\n";
dol_syslog(join(',',$_GET));
//print_r($_GET);
dol_syslog(join(',', $_GET));
// print_r($_GET);
if (! empty($action) && $action == 'fetch' && ! empty($id))
{
if (! empty($action) && $action == 'fetch' && ! empty($id)) {
require DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
$outjson=array();
$outjson = array();
$object = new Product($db);
$ret=$object->fetch($id);
if ($ret > 0)
{
$outref=$object->ref;
$outlabel=$object->label;
$outdesc=$object->description;
$outtype=$object->type;
$outqty=1;
$outdiscount=0;
$found=false;
$ret = $object->fetch($id);
if ($ret > 0) {
$outref = $object->ref;
$outlabel = $object->label;
$outdesc = $object->description;
$outtype = $object->type;
$outqty = 1;
$outdiscount = 0;
$found = false;
// Price by qty
if (!empty($price_by_qty_rowid) && $price_by_qty_rowid >= 1) // If we need a particular price related to qty
if (! empty($price_by_qty_rowid) && $price_by_qty_rowid >= 1 && (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY))) // If we need a
// particular price related
// to qty
{
$sql = "SELECT price, unitprice, quantity, remise_percent";
$sql.= " FROM ".MAIN_DB_PREFIX."product_price_by_qty ";
$sql.= " WHERE rowid=".$price_by_qty_rowid."";
$sql .= " FROM " . MAIN_DB_PREFIX . "product_price_by_qty ";
$sql .= " WHERE rowid=" . $price_by_qty_rowid . "";
$result = $db->query($sql);
if ($result)
{
if ($result) {
$objp = $db->fetch_object($result);
if ($objp)
{
$found=true;
$outprice_ht=price($objp->unitprice);
$outprice_ttc=price($objp->unitprice * (1 + ($object->tva_tx / 100)));
$outpricebasetype=$object->price_base_type;
$outtva_tx=$object->tva_tx;
$outqty=$objp->quantity;
$outdiscount=$objp->remise_percent;
if ($objp) {
$found = true;
$outprice_ht = price($objp->unitprice);
$outprice_ttc = price($objp->unitprice * (1 + ($object->tva_tx / 100)));
$outpricebasetype = $object->price_base_type;
$outtva_tx = $object->tva_tx;
$outqty = $objp->quantity;
$outdiscount = $objp->remise_percent;
}
}
}
// Multiprice
if (! $found && isset($price_level) && $price_level >= 1) // If we need a particular price level (from 1 to 6)
if (! $found && isset($price_level) && $price_level >= 1 && (! empty($conf->global->PRODUIT_MULTIPRICES))) // If we need a particular price
// level (from 1 to 6)
{
$sql = "SELECT price, price_ttc, price_base_type, tva_tx";
$sql.= " FROM ".MAIN_DB_PREFIX."product_price ";
$sql.= " WHERE fk_product='".$id."'";
$sql.= " AND entity IN (".getEntity('productprice', 1).")";
$sql.= " AND price_level=".$price_level;
$sql.= " ORDER BY date_price";
$sql.= " DESC LIMIT 1";
$sql .= " FROM " . MAIN_DB_PREFIX . "product_price ";
$sql .= " WHERE fk_product='" . $id . "'";
$sql .= " AND entity IN (" . getEntity('productprice', 1) . ")";
$sql .= " AND price_level=" . $price_level;
$sql .= " ORDER BY date_price";
$sql .= " DESC LIMIT 1";
$result = $db->query($sql);
if ($result)
{
if ($result) {
$objp = $db->fetch_object($result);
if ($objp)
{
$found=true;
$outprice_ht=price($objp->price);
$outprice_ttc=price($objp->price_ttc);
$outpricebasetype=$objp->price_base_type;
$outtva_tx=$objp->tva_tx;
if ($objp) {
$found = true;
$outprice_ht = price($objp->price);
$outprice_ttc = price($objp->price_ttc);
$outpricebasetype = $objp->price_base_type;
$outtva_tx = $objp->tva_tx;
}
}
}
if (! $found)
{
$outprice_ht=price($object->price);
$outprice_ttc=price($object->price_ttc);
$outpricebasetype=$object->price_base_type;
$outtva_tx=$object->tva_tx;
// Price by customer
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && ! empty($socid)) {
require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
$prodcustprice = new Productcustomerprice($db);
$filter = array('t.fk_product' => $object->id,'t.fk_soc' => $socid);
$result = $prodcustprice->fetch_all('', '', 0, 0, $filter);
if ($result) {
if (count($prodcustprice->lines) > 0) {
$found = true;
$outprice_ht = price($prodcustprice->lines [0]->price);
$outprice_ttc = price($prodcustprice->lines [0]->price_ttc);
$outpricebasetype = $prodcustprice->lines [0]->price_base_type;
$outtva_tx = $prodcustprice->lines [0]->tva_tx;
}
}
}
$outjson = array('ref'=>$outref, 'label'=>$outlabel, 'desc'=>$outdesc, 'type'=>$outtype, 'price_ht'=>$outprice_ht, 'price_ttc'=>$outprice_ttc, 'pricebasetype'=>$outpricebasetype, 'tva_tx'=>$outtva_tx, 'qty'=>$outqty, 'discount'=>$outdiscount);
if (! $found) {
$outprice_ht = price($object->price);
$outprice_ttc = price($object->price_ttc);
$outpricebasetype = $object->price_base_type;
$outtva_tx = $object->tva_tx;
}
$outjson = array('ref' => $outref,'label' => $outlabel,'desc' => $outdesc,'type' => $outtype,'price_ht' => $outprice_ht,'price_ttc' => $outprice_ttc,'pricebasetype' => $outpricebasetype,'tva_tx' => $outtva_tx,'qty' => $outqty,'discount' => $outdiscount);
}
echo json_encode($outjson);
}
else
{
require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
} else {
require_once DOL_DOCUMENT_ROOT . '/core/class/html.form.class.php';
$langs->load("products");
$langs->load("main");
top_httphead();
if (empty($htmlname)) return;
$match = preg_grep('/('.$htmlname.'[0-9]+)/',array_keys($_GET));
if (empty($htmlname))
return;
$match = preg_grep('/(' . $htmlname . '[0-9]+)/', array_keys($_GET));
sort($match);
$idprod = (! empty($match[0]) ? $match[0] : '');
if (! GETPOST($htmlname) && ! GETPOST($idprod)) return;
// When used from jQuery, the search term is added as GET param "term".
$searchkey=(GETPOST($idprod)?GETPOST($idprod):(GETPOST($htmlname)?GETPOST($htmlname):''));
$idprod = (! empty($match [0]) ? $match [0] : '');
if (! GETPOST($htmlname) && ! GETPOST($idprod))
return;
// When used from jQuery, the search term is added as GET param "term".
$searchkey = (GETPOST($idprod) ? GETPOST($idprod) : (GETPOST($htmlname) ? GETPOST($htmlname) : ''));
$form = new Form($db);
if (empty($mode) || $mode == 1)
{
$arrayresult=$form->select_produits_list("",$htmlname,$type,"",$price_level,$searchkey,$status,2,$outjson);
if (empty($mode) || $mode == 1) {
$arrayresult = $form->select_produits_list("", $htmlname, $type, "", $price_level, $searchkey, $status, 2, $outjson, $socid);
} elseif ($mode == 2) {
$arrayresult = $form->select_produits_fournisseurs_list($socid, "", $htmlname, $type, "", $searchkey, $status, $outjson, $socid);
}
elseif ($mode == 2)
{
$arrayresult=$form->select_produits_fournisseurs_list($socid,"",$htmlname,$type,"",$searchkey,$status,$outjson);
}
$db->close();
if ($outjson) print json_encode($arrayresult);
if ($outjson)
print json_encode($arrayresult);
}
?>

View File

@ -1183,6 +1183,7 @@ class Product extends CommonObject
}
//print 'x'.$id.'-'.$newprice.'-'.$newpricebase.'-'.$price.'-'.$price_ttc.'-'.$price_min.'-'.$price_min_ttc;
//Local taxes
$localtax1=get_localtax($newvat,1);
$localtax2=get_localtax($newvat,2);

View File

@ -0,0 +1,946 @@
<?php
/* Copyright (C) 2007-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2014 Florian Henry <florian.henry@open-concept.pro>
*
* 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/product/class/productcustomerprice.class.php
* \ingroup produit
* \brief File of class to manage predefined price products or services by customer
*/
require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php';
/**
* File of class to manage predefined price products or services by customer
*/
class Productcustomerprice extends CommonObject
{
var $db; // !< To store db handler
var $error; // !< To return error code (or message)
var $errors = array (); // !< To return several error codes (or messages)
var $element = 'product_customer_price'; // !< Id that identify managed objects
var $table_element = 'product_customer_price'; // !< Name of table without prefix where object is stored
var $id;
var $entity;
var $datec = '';
var $tms = '';
var $fk_product;
var $fk_soc;
var $price;
var $price_ttc;
var $price_min;
var $price_min_ttc;
var $price_base_type;
var $tva_tx;
var $recuperableonly;
var $localtax1_tx;
var $localtax2_tx;
var $fk_user;
var $import_key;
var $lines = array ();
/**
* Constructor
*
* @param DoliDb $db handler
*/
function __construct($db) {
$this->db = $db;
return 1;
}
/**
* Create object into database
*
* @param User $user that creates
* @param int $notrigger triggers after, 1=disable triggers
* @param int $forceupdateaffiliate update price on each soc child
* @return int <0 if KO, Id of created object if OK
*/
function create($user, $notrigger = 0, $forceupdateaffiliate = 0) {
global $conf, $langs;
$error = 0;
// Clean parameters
if (isset($this->entity))
$this->entity = trim($this->entity);
if (isset($this->fk_product))
$this->fk_product = trim($this->fk_product);
if (isset($this->fk_soc))
$this->fk_soc = trim($this->fk_soc);
if (isset($this->price))
$this->price = trim($this->price);
if (isset($this->price_ttc))
$this->price_ttc = trim($this->price_ttc);
if (isset($this->price_min))
$this->price_min = trim($this->price_min);
if (isset($this->price_min_ttc))
$this->price_min_ttc = trim($this->price_min_ttc);
if (isset($this->price_base_type))
$this->price_base_type = trim($this->price_base_type);
if (isset($this->tva_tx))
$this->tva_tx = trim($this->tva_tx);
if (isset($this->recuperableonly))
$this->recuperableonly = trim($this->recuperableonly);
if (isset($this->localtax1_tx))
$this->localtax1_tx = trim($this->localtax1_tx);
if (isset($this->localtax2_tx))
$this->localtax2_tx = trim($this->localtax2_tx);
if (isset($this->fk_user))
$this->fk_user = trim($this->fk_user);
if (isset($this->import_key))
$this->import_key = trim($this->import_key);
// Check parameters
// Put here code to add control on parameters values
if ($this->price != '' || $this->price == 0) {
if ($this->price_base_type == 'TTC') {
$this->price_ttc = price2num($this->price, 'MU');
$this->price = price2num($this->price) / (1 + ($this->tva_tx / 100));
$this->price = price2num($this->price, 'MU');
if ($this->price_min != '' || $this->price_min == 0) {
$this->price_min_ttc = price2num($this->price_min, 'MU');
$this->price_min = price2num($this->price_min) / (1 + ($this->tva_tx / 100));
$this->price_min = price2num($this->price_min, 'MU');
} else {
$this->price_min = 0;
$this->price_min_ttc = 0;
}
} else {
$this->price = price2num($this->price, 'MU');
$this->price_ttc = ($this->recuperableonly != 1) ? price2num($this->price) * (1 + ($this->tva_tx / 100)) : $this->price;
$this->price_ttc = price2num($this->price_ttc, 'MU');
if ($this->price_min != '' || $this->price_min == 0) {
$this->price_min = price2num($this->price_min, 'MU');
$this->price_min_ttc = price2num($this->price_min) * (1 + ($this->tva_tx / 100));
$this->price_min_ttc = price2num($this->price_min_ttc, 'MU');
// print 'X'.$newminprice.'-'.$price_min;
} else {
$this->price_min = 0;
$this->price_min_ttc = 0;
}
}
}
// Insert request
$sql = "INSERT INTO " . MAIN_DB_PREFIX . "product_customer_price(";
$sql .= "entity,";
$sql .= "datec,";
$sql .= "fk_product,";
$sql .= "fk_soc,";
$sql .= "price,";
$sql .= "price_ttc,";
$sql .= "price_min,";
$sql .= "price_min_ttc,";
$sql .= "price_base_type,";
$sql .= "tva_tx,";
$sql .= "recuperableonly,";
$sql .= "localtax1_tx,";
$sql .= "localtax2_tx,";
$sql .= "fk_user,";
$sql .= "import_key";
$sql .= ") VALUES (";
$sql .= " " . $conf->entity . ",";
$sql .= " '" . $this->db->idate(dol_now()) . "',";
$sql .= " " . (! isset($this->fk_product) ? 'NULL' : "'" . $this->fk_product . "'") . ",";
$sql .= " " . (! isset($this->fk_soc) ? 'NULL' : "'" . $this->fk_soc . "'") . ",";
$sql .= " " . (empty($this->price) ? '0' : "'" . $this->price . "'") . ",";
$sql .= " " . (empty($this->price_ttc) ? '0' : "'" . $this->price_ttc . "'") . ",";
$sql .= " " . (empty($this->price_min) ? '0' : "'" . $this->price_min . "'") . ",";
$sql .= " " . (empty($this->price_min_ttc) ? '0' : "'" . $this->price_min_ttc . "'") . ",";
$sql .= " " . (! isset($this->price_base_type) ? 'NULL' : "'" . $this->db->escape($this->price_base_type) . "'") . ",";
$sql .= " " . (! isset($this->tva_tx) ? 'NULL' : "'" . $this->tva_tx . "'") . ",";
$sql .= " " . (! isset($this->recuperableonly) ? 'NULL' : "'" . $this->recuperableonly . "'") . ",";
$sql .= " " . (! isset($this->localtax1_tx) ? 'NULL' : "'" . $this->localtax1_tx . "'") . ",";
$sql .= " " . (! isset($this->localtax2_tx) ? 'NULL' : "'" . $this->localtax2_tx . "'") . ",";
$sql .= " " . $user->id . ",";
$sql .= " " . (! isset($this->import_key) ? 'NULL' : "'" . $this->db->escape($this->import_key) . "'") . "";
$sql .= ")";
$this->db->begin();
dol_syslog(get_class($this) . "::create sql=" . $sql, LOG_DEBUG);
$resql = $this->db->query($sql);
if (! $resql) {
$error ++;
$this->errors [] = "Error " . $this->db->lasterror();
}
if (! $error) {
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "product_customer_price");
if (! $notrigger) {
// Uncomment this and change MYOBJECT to your own tag if you
// want this action calls a trigger.
// // Call triggers
// include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
// $interface=new Interfaces($this->db);
// $result=$interface->run_triggers('MYOBJECT_CREATE',$this,$user,$langs,$conf);
// if ($result < 0) { $error++; $this->errors=$interface->errors; }
// // End call triggers
}
}
if (! $error) {
$result = $this->setPriceOnAffiliateThirdparty($user, $forceupdateaffiliate);
if ($result < 0) {
$error ++;
}
}
// Commit or rollback
if ($error) {
foreach ( $this->errors as $errmsg ) {
dol_syslog(get_class($this) . "::create " . $errmsg, LOG_ERR);
$this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
}
$this->db->rollback();
return - 1 * $error;
} else {
$this->db->commit();
return $this->id;
}
}
/**
* Load object in memory from the database
*
* @param int $id object
* @return int <0 if KO, >0 if OK
*/
function fetch($id) {
global $langs;
$sql = "SELECT";
$sql .= " t.rowid,";
$sql .= " t.entity,";
$sql .= " t.datec,";
$sql .= " t.tms,";
$sql .= " t.fk_product,";
$sql .= " t.fk_soc,";
$sql .= " t.price,";
$sql .= " t.price_ttc,";
$sql .= " t.price_min,";
$sql .= " t.price_min_ttc,";
$sql .= " t.price_base_type,";
$sql .= " t.tva_tx,";
$sql .= " t.recuperableonly,";
$sql .= " t.localtax1_tx,";
$sql .= " t.localtax2_tx,";
$sql .= " t.fk_user,";
$sql .= " t.import_key";
$sql .= " FROM " . MAIN_DB_PREFIX . "product_customer_price as t";
$sql .= " WHERE t.rowid = " . $id;
dol_syslog(get_class($this) . "::fetch sql=" . $sql, LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
if ($this->db->num_rows($resql)) {
$obj = $this->db->fetch_object($resql);
$this->id = $obj->rowid;
$this->entity = $obj->entity;
$this->datec = $this->db->jdate($obj->datec);
$this->tms = $this->db->jdate($obj->tms);
$this->fk_product = $obj->fk_product;
$this->fk_soc = $obj->fk_soc;
$this->price = $obj->price;
$this->price_ttc = $obj->price_ttc;
$this->price_min = $obj->price_min;
$this->price_min_ttc = $obj->price_min_ttc;
$this->price_base_type = $obj->price_base_type;
$this->tva_tx = $obj->tva_tx;
$this->recuperableonly = $obj->recuperableonly;
$this->localtax1_tx = $obj->localtax1_tx;
$this->localtax2_tx = $obj->localtax2_tx;
$this->fk_user = $obj->fk_user;
$this->import_key = $obj->import_key;
}
$this->db->free($resql);
return 1;
} else {
$this->error = "Error " . $this->db->lasterror();
dol_syslog(get_class($this) . "::fetch " . $this->error, LOG_ERR);
return - 1;
}
}
/**
* Load all objects in memory from database
*
* @param string $sortorder order
* @param string $sortfield field
* @param int $limit page
* @param int $offset offset
* @param array $filter output
* @return int <0 if KO, >0 if OK
*/
function fetch_all($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = array()) {
global $langs;
$sql = "SELECT";
$sql .= " t.rowid,";
$sql .= " t.entity,";
$sql .= " t.datec,";
$sql .= " t.tms,";
$sql .= " t.fk_product,";
$sql .= " t.fk_soc,";
$sql .= " t.price,";
$sql .= " t.price_ttc,";
$sql .= " t.price_min,";
$sql .= " t.price_min_ttc,";
$sql .= " t.price_base_type,";
$sql .= " t.tva_tx,";
$sql .= " t.recuperableonly,";
$sql .= " t.localtax1_tx,";
$sql .= " t.localtax2_tx,";
$sql .= " t.fk_user,";
$sql .= " t.import_key,";
$sql .= " soc.nom as socname,";
$sql .= " prod.ref as prodref";
$sql .= " FROM " . MAIN_DB_PREFIX . "product_customer_price as t ";
$sql .= " ," . MAIN_DB_PREFIX . "product as prod ";
$sql .= " ," . MAIN_DB_PREFIX . "societe as soc ";
$sql .= " WHERE soc.rowid=t.fk_soc ";
$sql .= " AND prod.rowid=t.fk_product ";
$sql .= " AND prod.entity IN (" . getEntity('product', 1) . ")";
// Manage filter
if (count($filter) > 0) {
foreach ( $filter as $key => $value ) {
if (strpos($key, 'date')) // To allow $filter['YEAR(s.dated)']=>$year
{
$sql .= ' AND ' . $key . ' = \'' . $value . '\'';
} elseif ($key == 'soc.nom') {
$sql .= ' AND ' . $key . ' LIKE \'%' . $value . '%\'';
} else {
$sql .= ' AND ' . $key . ' = ' . $value;
}
}
}
if (! empty($sortfield)) {
$sql .= " ORDER BY " . $sortfield . ' ' . $sortorder;
}
if (! empty($limit)) {
$sql .= ' ' . $this->db->plimit($limit + 1, $offset);
}
dol_syslog(get_class($this) . "::fetch_all sql=" . $sql, LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
$this->lines = array ();
$num = $this->db->num_rows($resql);
while ( $obj = $this->db->fetch_object($resql) ) {
$line = new PriceByCustomerLine();
$line->id = $obj->rowid;
$line->entity = $obj->entity;
$line->datec = $this->db->jdate($obj->datec);
$line->tms = $this->db->jdate($obj->tms);
$line->fk_product = $obj->fk_product;
$line->fk_soc = $obj->fk_soc;
$line->price = $obj->price;
$line->price_ttc = $obj->price_ttc;
$line->price_min = $obj->price_min;
$line->price_min_ttc = $obj->price_min_ttc;
$line->price_base_type = $obj->price_base_type;
$line->tva_tx = $obj->tva_tx;
$line->recuperableonly = $obj->recuperableonly;
$line->localtax1_tx = $obj->localtax1_tx;
$line->localtax2_tx = $obj->localtax2_tx;
$line->fk_user = $obj->fk_user;
$line->import_key = $obj->import_key;
$line->socname = $obj->socname;
$line->prodref = $obj->prodref;
$this->lines [] = $line;
}
$this->db->free($resql);
return $num;
} else {
$this->error = "Error " . $this->db->lasterror();
dol_syslog(get_class($this) . "::fetch_all " . $this->error, LOG_ERR);
return - 1;
}
}
/**
* Load all objects in memory from database
*
* @param string $sortorder order
* @param string $sortfield field
* @param int $limit page
* @param int $offset offset
* @param array $filter output
* @return int <0 if KO, >0 if OK
*/
function fetch_all_log($sortorder, $sortfield, $limit, $offset, $filter = array()) {
global $langs;
$sql = "SELECT";
$sql .= " t.rowid,";
$sql .= " t.entity,";
$sql .= " t.datec,";
$sql .= " t.fk_product,";
$sql .= " t.fk_soc,";
$sql .= " t.price,";
$sql .= " t.price_ttc,";
$sql .= " t.price_min,";
$sql .= " t.price_min_ttc,";
$sql .= " t.price_base_type,";
$sql .= " t.tva_tx,";
$sql .= " t.recuperableonly,";
$sql .= " t.localtax1_tx,";
$sql .= " t.localtax2_tx,";
$sql .= " t.fk_user,";
$sql .= " t.import_key,";
$sql .= " soc.nom as socname,";
$sql .= " prod.ref as prodref";
$sql .= " FROM " . MAIN_DB_PREFIX . "product_customer_price_log as t ";
$sql .= " ," . MAIN_DB_PREFIX . "product as prod ";
$sql .= " ," . MAIN_DB_PREFIX . "societe as soc ";
$sql .= " WHERE soc.rowid=t.fk_soc ";
$sql .= " AND prod.rowid=t.fk_product ";
$sql .= " AND prod.entity IN (" . getEntity('product', 1) . ")";
// Manage filter
if (count($filter) > 0) {
foreach ( $filter as $key => $value ) {
if (strpos($key, 'date')) // To allow $filter['YEAR(s.dated)']=>$year
{
$sql .= ' AND ' . $key . ' = \'' . $value . '\'';
} elseif ($key == 'soc.nom') {
$sql .= ' AND ' . $key . ' LIKE \'%' . $value . '%\'';
} else {
$sql .= ' AND ' . $key . ' = ' . $value;
}
}
}
if (! empty($sortfield)) {
$sql .= " ORDER BY " . $sortfield . ' ' . $sortorder;
}
if (! empty($limit)) {
$sql .= ' ' . $this->db->plimit($limit + 1, $offset);
}
dol_syslog(get_class($this) . "::fetch_all_log sql=" . $sql, LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
$this->lines = array ();
$num = $this->db->num_rows($resql);
while ( $obj = $this->db->fetch_object($resql) ) {
$line = new PriceByCustomerLine();
$line->id = $obj->rowid;
$line->entity = $obj->entity;
$line->datec = $this->db->jdate($obj->datec);
$line->tms = $this->db->jdate($obj->tms);
$line->fk_product = $obj->fk_product;
$line->fk_soc = $obj->fk_soc;
$line->price = $obj->price;
$line->price_ttc = $obj->price_ttc;
$line->price_min = $obj->price_min;
$line->price_min_ttc = $obj->price_min_ttc;
$line->price_base_type = $obj->price_base_type;
$line->tva_tx = $obj->tva_tx;
$line->recuperableonly = $obj->recuperableonly;
$line->localtax1_tx = $obj->localtax1_tx;
$line->localtax2_tx = $obj->localtax2_tx;
$line->fk_user = $obj->fk_user;
$line->import_key = $obj->import_key;
$line->socname = $obj->socname;
$line->prodref = $obj->prodref;
$this->lines [] = $line;
}
$this->db->free($resql);
return $num;
} else {
$this->error = "Error " . $this->db->lasterror();
dol_syslog(get_class($this) . "::fetch_all_log " . $this->error, LOG_ERR);
return - 1;
}
}
/**
* Update object into database
*
* @param User $user that modifies
* @param int $notrigger triggers after, 1=disable triggers
* @param int $forceupdateaffiliate update price on each soc child
* @return int <0 if KO, >0 if OK
*/
function update($user = 0, $notrigger = 0, $forceupdateaffiliate = 0) {
global $conf, $langs;
$error = 0;
// Clean parameters
if (isset($this->entity))
$this->entity = trim($this->entity);
if (isset($this->fk_product))
$this->fk_product = trim($this->fk_product);
if (isset($this->fk_soc))
$this->fk_soc = trim($this->fk_soc);
if (isset($this->price))
$this->price = trim($this->price);
if (isset($this->price_ttc))
$this->price_ttc = trim($this->price_ttc);
if (isset($this->price_min))
$this->price_min = trim($this->price_min);
if (isset($this->price_min_ttc))
$this->price_min_ttc = trim($this->price_min_ttc);
if (isset($this->price_base_type))
$this->price_base_type = trim($this->price_base_type);
if (isset($this->tva_tx))
$this->tva_tx = trim($this->tva_tx);
if (isset($this->recuperableonly))
$this->recuperableonly = trim($this->recuperableonly);
if (isset($this->localtax1_tx))
$this->localtax1_tx = trim($this->localtax1_tx);
if (isset($this->localtax2_tx))
$this->localtax2_tx = trim($this->localtax2_tx);
if (isset($this->fk_user))
$this->fk_user = trim($this->fk_user);
if (isset($this->import_key))
$this->import_key = trim($this->import_key);
// Check parameters
// Put here code to add a control on parameters values
if ($this->price != '' || $this->price == 0) {
if ($this->price_base_type == 'TTC') {
$this->price_ttc = price2num($this->price, 'MU');
$this->price = price2num($this->price) / (1 + ($this->tva_tx / 100));
$this->price = price2num($this->price, 'MU');
if ($this->price_min != '' || $this->price_min == 0) {
$this->price_min_ttc = price2num($this->price_min, 'MU');
$this->price_min = price2num($this->price_min) / (1 + ($this->tva_tx / 100));
$this->price_min = price2num($this->price_min, 'MU');
} else {
$this->price_min = 0;
$this->price_min_ttc = 0;
}
} else {
$this->price = price2num($this->price, 'MU');
$this->price_ttc = ($this->recuperableonly != 1) ? price2num($this->price) * (1 + ($this->tva_tx / 100)) : $this->price;
$this->price_ttc = price2num($this->price_ttc, 'MU');
if ($this->price_min != '' || $this->price_min == 0) {
$this->price_min = price2num($this->price_min, 'MU');
$this->price_min_ttc = price2num($this->price_min) * (1 + ($this->tva_tx / 100));
$this->price_min_ttc = price2num($this->price_min_ttc, 'MU');
// print 'X'.$newminprice.'-'.$price_min;
} else {
$this->price_min = 0;
$this->price_min_ttc = 0;
}
}
}
// Do a copy of current record into log table
// Insert request
$sql = "INSERT INTO " . MAIN_DB_PREFIX . "product_customer_price_log(";
$sql .= "entity,";
$sql .= "datec,";
$sql .= "fk_product,";
$sql .= "fk_soc,";
$sql .= "price,";
$sql .= "price_ttc,";
$sql .= "price_min,";
$sql .= "price_min_ttc,";
$sql .= "price_base_type,";
$sql .= "tva_tx,";
$sql .= "recuperableonly,";
$sql .= "localtax1_tx,";
$sql .= "localtax2_tx,";
$sql .= "fk_user,";
$sql .= "import_key";
$sql .= ") ";
$sql .= "SELECT";
$sql .= " t.entity,";
$sql .= " t.datec,";
$sql .= " t.fk_product,";
$sql .= " t.fk_soc,";
$sql .= " t.price,";
$sql .= " t.price_ttc,";
$sql .= " t.price_min,";
$sql .= " t.price_min_ttc,";
$sql .= " t.price_base_type,";
$sql .= " t.tva_tx,";
$sql .= " t.recuperableonly,";
$sql .= " t.localtax1_tx,";
$sql .= " t.localtax2_tx,";
$sql .= " t.fk_user,";
$sql .= " t.import_key";
$sql .= " FROM " . MAIN_DB_PREFIX . "product_customer_price as t";
$sql .= " WHERE t.rowid = " . $this->id;
$this->db->begin();
dol_syslog(get_class($this) . "::update sql=" . $sql, LOG_DEBUG);
$resql = $this->db->query($sql);
if (! $resql) {
$error ++;
$this->errors [] = "Error " . $this->db->lasterror();
}
// Update request
$sql = "UPDATE " . MAIN_DB_PREFIX . "product_customer_price SET";
$sql .= " entity=" . $conf->entity . ",";
$sql .= " datec='" . $this->db->idate(dol_now()) . "',";
$sql .= " tms=" . (dol_strlen($this->tms) != 0 ? "'" . $this->db->idate($this->tms) . "'" : 'null') . ",";
$sql .= " fk_product=" . (isset($this->fk_product) ? $this->fk_product : "null") . ",";
$sql .= " fk_soc=" . (isset($this->fk_soc) ? $this->fk_soc : "null") . ",";
$sql .= " price=" . (isset($this->price) ? $this->price : "null") . ",";
$sql .= " price_ttc=" . (isset($this->price_ttc) ? $this->price_ttc : "null") . ",";
$sql .= " price_min=" . (isset($this->price_min) ? $this->price_min : "null") . ",";
$sql .= " price_min_ttc=" . (isset($this->price_min_ttc) ? $this->price_min_ttc : "null") . ",";
$sql .= " price_base_type=" . (isset($this->price_base_type) ? "'" . $this->db->escape($this->price_base_type) . "'" : "null") . ",";
$sql .= " tva_tx=" . (isset($this->tva_tx) ? $this->tva_tx : "null") . ",";
$sql .= " recuperableonly=" . (isset($this->recuperableonly) ? $this->recuperableonly : "null") . ",";
$sql .= " localtax1_tx=" . (isset($this->localtax1_tx) ? $this->localtax1_tx : "null") . ",";
$sql .= " localtax2_tx=" . (isset($this->localtax2_tx) ? $this->localtax2_tx : "null") . ",";
$sql .= " fk_user=" . $user->id . ",";
$sql .= " import_key=" . (isset($this->import_key) ? "'" . $this->db->escape($this->import_key) . "'" : "null") . "";
$sql .= " WHERE rowid=" . $this->id;
dol_syslog(get_class($this) . "::update sql=" . $sql, LOG_DEBUG);
$resql = $this->db->query($sql);
if (! $resql) {
$error ++;
$this->errors [] = "Error " . $this->db->lasterror();
}
if (! $error) {
if (! $notrigger) {
// Uncomment this and change MYOBJECT to your own tag if you
// want this action calls a trigger.
// // Call triggers
// include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
// $interface=new Interfaces($this->db);
// $result=$interface->run_triggers('MYOBJECT_MODIFY',$this,$user,$langs,$conf);
// if ($result < 0) { $error++; $this->errors=$interface->errors; }
// // End call triggers
}
}
if (! $error) {
$result = $this->setPriceOnAffiliateThirdparty($user, $forceupdateaffiliate);
if ($result < 0) {
$error ++;
}
}
// Commit or rollback
if ($error) {
foreach ( $this->errors as $errmsg ) {
dol_syslog(get_class($this) . "::update " . $errmsg, LOG_ERR);
$this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
}
$this->db->rollback();
return - 1 * $error;
} else {
$this->db->commit();
return 1;
}
}
/**
* Force update price on child price
*
* @param User $user that modifies
* @param int $forceupdateaffiliate update price on each soc child
* @return int <0 if KO, >0 if OK
*/
function setPriceOnAffiliateThirdparty($user, $forceupdateaffiliate) {
$error = 0;
// Find all susidiaries
$sql = "SELECT s.rowid";
$sql .= " FROM " . MAIN_DB_PREFIX . "societe as s";
$sql .= " WHERE s.parent = " . $this->fk_soc;
$sql .= " AND s.entity IN (" . getEntity('societe', 1) . ")";
dol_syslog(get_class($this) . "::setPriceOnAffiliateThirdparty sql=" . $sql, LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
$this->lines = array ();
$num = $this->db->num_rows($resql);
while ( ($obj = $this->db->fetch_object($resql)) && (empty($error)) ) {
// find if there is an existing line for the product and the subsidiaries
$prodsocprice = new Productcustomerprice($this->db);
$filter = array (
't.fk_product' => $this->fk_product,'t.fk_soc' => $obj->rowid
);
$result = $prodsocprice->fetch_all('', '', 0, 0, $filter);
if ($result < 0) {
$error ++;
$this->error = $prodsocprice->error;
} else {
// There is one line
if (count($prodsocprice->lines) > 0) {
// If force update => Update
if (! empty($forceupdateaffiliate)) {
$prodsocpriceupd = new Productcustomerprice($this->db);
$prodsocpriceupd->fetch($prodsocprice->lines [0]->id);
$prodsocpriceupd->price = $this->price;
$prodsocpriceupd->price_min = $this->price_min;
$prodsocpriceupd->price_base_type = $this->price_base_type;
$prodsocpriceupd->tva_tx = $this->tva_tx;
$prodsocpriceupd->recuperableonly = $this->recuperableonly;
$resultupd = $prodsocpriceupd->update($user, 0, $forceupdateaffiliate);
if ($result < 0) {
$error ++;
$this->error = $prodsocpriceupd->error;
}
}
} else {
// If line do not exits then create it
$prodsocpricenew = new Productcustomerprice($this->db);
$prodsocpricenew->fk_soc = $obj->rowid;
$prodsocpricenew->fk_product = $this->fk_product;
$prodsocpricenew->price = $this->price;
$prodsocpricenew->price_min = $this->price_min;
$prodsocpricenew->price_base_type = $this->price_base_type;
$prodsocpricenew->tva_tx = $this->tva_tx;
$prodsocpricenew->recuperableonly = $this->recuperableonly;
$resultupd = $prodsocpricenew->create($user, 0, $forceupdateaffiliate);
if ($result < 0) {
$error ++;
$this->error = $prodsocpriceupd->error;
}
}
}
}
$this->db->free($resql);
if (empty($error)) {
return 1;
} else {
return - 1;
}
} else {
$this->error = "Error " . $this->db->lasterror();
dol_syslog(get_class($this) . "::setPriceOnAffiliateThirdparty " . $this->error, LOG_ERR);
return - 1;
}
}
/**
* Delete object in database
*
* @param User $user that deletes
* @param int $notrigger triggers after, 1=disable triggers
* @return int <0 if KO, >0 if OK
*/
function delete($user, $notrigger = 0) {
global $conf, $langs;
$error = 0;
$this->db->begin();
if (! $error) {
if (! $notrigger) {
// Uncomment this and change MYOBJECT to your own tag if you
// want this action calls a trigger.
// // Call triggers
// include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
// $interface=new Interfaces($this->db);
// $result=$interface->run_triggers('MYOBJECT_DELETE',$this,$user,$langs,$conf);
// if ($result < 0) { $error++; $this->errors=$interface->errors; }
// // End call triggers
}
}
if (! $error) {
$sql = "DELETE FROM " . MAIN_DB_PREFIX . "product_customer_price";
$sql .= " WHERE rowid=" . $this->id;
dol_syslog(get_class($this) . "::delete sql=" . $sql);
$resql = $this->db->query($sql);
if (! $resql) {
$error ++;
$this->errors [] = "Error " . $this->db->lasterror();
}
}
// Commit or rollback
if ($error) {
foreach ( $this->errors as $errmsg ) {
dol_syslog(get_class($this) . "::delete " . $errmsg, LOG_ERR);
$this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
}
$this->db->rollback();
return - 1 * $error;
} else {
$this->db->commit();
return 1;
}
}
/**
* Load an object from its id and create a new one in database
*
* @param int $fromid of object to clone
* @return int id of clone
*/
function createFromClone($fromid) {
global $user, $langs;
$error = 0;
$object = new Productcustomerprice($this->db);
$this->db->begin();
// Load source object
$object->fetch($fromid);
$object->id = 0;
$object->statut = 0;
// Clear fields
// ...
// Create clone
$result = $object->create($user);
// Other options
if ($result < 0) {
$this->error = $object->error;
$error ++;
}
if (! $error) {
}
// End
if (! $error) {
$this->db->commit();
return $object->id;
} else {
$this->db->rollback();
return - 1;
}
}
/**
* Initialise object with example values
* Id must be 0 if object instance is a specimen
*
* @return void
*/
function initAsSpecimen() {
$this->id = 0;
$this->entity = '';
$this->datec = '';
$this->tms = '';
$this->fk_product = '';
$this->fk_soc = '';
$this->price = '';
$this->price_ttc = '';
$this->price_min = '';
$this->price_min_ttc = '';
$this->price_base_type = '';
$this->tva_tx = '';
$this->recuperableonly = '';
$this->localtax1_tx = '';
$this->localtax2_tx = '';
$this->fk_user = '';
$this->import_key = '';
}
}
/**
* File of class to manage predefined price products or services by customer lines
*/
class PriceByCustomerLine
{
var $id;
var $entity;
var $datec = '';
var $tms = '';
var $fk_product;
var $fk_soc;
var $price;
var $price_ttc;
var $price_min;
var $price_min_ttc;
var $price_base_type;
var $tva_tx;
var $recuperableonly;
var $localtax1_tx;
var $localtax2_tx;
var $fk_user;
var $import_key;
var $socname;
var $prodref;
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -198,7 +198,7 @@ class Project extends CommonObject
if (dol_strlen(trim($this->ref)) > 0)
{
$sql = "UPDATE " . MAIN_DB_PREFIX . "projet SET";
$sql.= " ref='" . $this->ref . "'";
$sql.= " ref='" . $this->db->escape($this->ref) . "'";
$sql.= ", title = '" . $this->db->escape($this->title) . "'";
$sql.= ", description = '" . $this->db->escape($this->description) . "'";
$sql.= ", fk_soc = " . ($this->socid > 0 ? $this->socid : "null");

565
htdocs/societe/price.php Normal file
View File

@ -0,0 +1,565 @@
<?php
/* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2005 Eric Seigne <eric.seigne@ryxeo.com>
* Copyright (C) 2005-2013 Regis Houssin <regis.houssin@capnetworks.com>
* Copyright (C) 2006 Andre Cianfarani <acianfa@free.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/societe/price.php
* \ingroup product
* \brief Page to show product prices by customer
*/
require '../main.inc.php';
require_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php';
require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
$prodcustprice = new Productcustomerprice($db);
}
$langs->load("products");
$langs->load("companies");
$langs->load("bills");
$action = GETPOST('action', 'alpha');
// Security check
$socid = GETPOST('socid', 'int');
if ($user->societe_id)
$socid = $user->societe_id;
$result = restrictedArea($user, 'societe', $socid, '&societe');
/**
* ***************************************************
* Price by customer
* ****************************************************
*/
if ($action == 'add_customer_price_confirm' && ! $_POST ["cancel"] && ($user->rights->produit->creer || $user->rights->service->creer)) {
$update_child_soc = GETPOST('updatechildprice');
// add price by customer
$prodcustprice->fk_soc = $socid;
$prodcustprice->fk_product = GETPOST('prodid', 'int');
$prodcustprice->price = price2num(GETPOST("price"), 'MU');
$prodcustprice->price_min = price2num(GETPOST("price_min"), 'MU');
$prodcustprice->price_base_type = GETPOST("price_base_type", 'alpha');
$prodcustprice->tva_tx = str_replace('*', '', GETPOST("tva_tx"));
$prodcustprice->recuperableonly = (preg_match('/\*/', GETPOST("tva_tx")) ? 1 : 0);
$result = $prodcustprice->create($user, 0, $update_child_soc);
if ($result < 0) {
setEventMessage($prodcustprice->error, 'errors');
} else {
setEventMessage($langs->trans('Save'), 'mesgs');
}
$action = '';
}
if ($action == 'delete_customer_price' && ($user->rights->produit->creer || $user->rights->service->creer)) {
// Delete price by customer
$prodcustprice->id = GETPOST('lineid');
$result = $prodcustprice->delete($user);
if ($result < 0) {
setEventMessage($prodcustprice->error, 'mesgs');
} else {
setEventMessage($langs->trans('Delete'), 'errors');
}
$action = '';
}
if ($action == 'update_customer_price_confirm' && ! $_POST ["cancel"] && ($user->rights->produit->creer || $user->rights->service->creer)) {
$prodcustprice->fetch(GETPOST('lineid', 'int'));
$update_child_soc = GETPOST('updatechildprice');
// update price by customer
$prodcustprice->price = price2num(GETPOST("price"), 'MU');
$prodcustprice->price_min = price2num(GETPOST("price_min"), 'MU');
$prodcustprice->price_base_type = GETPOST("price_base_type", 'alpha');
$prodcustprice->tva_tx = str_replace('*', '', GETPOST("tva_tx"));
$prodcustprice->recuperableonly = (preg_match('/\*/', GETPOST("tva_tx")) ? 1 : 0);
$result = $prodcustprice->update($user, 0, $update_child_soc);
if ($result < 0) {
setEventMessage($prodcustprice->error, 'errors');
} else {
setEventMessage($langs->trans('Save'), 'mesgs');
}
$action = '';
}
/*
* View
*/
$form = new Form($db);
$soc = new Societe($db);
$result = $soc->fetch($socid);
llxHeader("", $langs->trans("ThirdParty") . '-' . $langs->trans('PriceByCustomer'));
if (! empty($conf->notification->enabled))
$langs->load("mails");
$head = societe_prepare_head($soc);
dol_fiche_head($head, 'price', $langs->trans("ThirdParty"), 0, 'company');
print '<table class="border" width="100%">';
print '<tr><td width="25%">' . $langs->trans("ThirdPartyName") . '</td><td colspan="3">';
print $form->showrefnav($soc, 'socid', '', ($user->societe_id ? 0 : 1), 'rowid', 'nom');
print '</td></tr>';
if (! empty($conf->global->SOCIETE_USEPREFIX)) // Old not used prefix field
{
print '<tr><td>' . $langs->trans('Prefix') . '</td><td colspan="3">' . $soc->prefix_comm . '</td></tr>';
}
if ($soc->client) {
print '<tr><td>';
print $langs->trans('CustomerCode') . '</td><td colspan="3">';
print $soc->code_client;
if ($soc->check_codeclient() != 0)
print ' <font class="error">(' . $langs->trans("WrongCustomerCode") . ')</font>';
print '</td></tr>';
}
if ($soc->fournisseur) {
print '<tr><td>';
print $langs->trans('SupplierCode') . '</td><td colspan="3">';
print $soc->code_fournisseur;
if ($soc->check_codefournisseur() != 0)
print ' <font class="error">(' . $langs->trans("WrongSupplierCode") . ')</font>';
print '</td></tr>';
}
if (! empty($conf->barcode->enabled)) {
print '<tr><td>' . $langs->trans('Gencod') . '</td><td colspan="3">' . $soc->barcode . '</td></tr>';
}
print "<tr><td valign=\"top\">" . $langs->trans('Address') . "</td><td colspan=\"3\">";
dol_print_address($soc->address, 'gmap', 'thirdparty', $soc->id);
print "</td></tr>";
// Zip / Town
print '<tr><td width="25%">' . $langs->trans('Zip') . '</td><td width="25%">' . $soc->zip . "</td>";
print '<td width="25%">' . $langs->trans('Town') . '</td><td width="25%">' . $soc->town . "</td></tr>";
// Country
if ($soc->country) {
print '<tr><td>' . $langs->trans('Country') . '</td><td colspan="3">';
$img = picto_from_langcode($soc->country_code);
print($img ? $img . ' ' : '');
print $soc->country;
print '</td></tr>';
}
// EMail
print '<tr><td>' . $langs->trans('EMail') . '</td><td colspan="3">';
print dol_print_email($soc->email, 0, $soc->id, 'AC_EMAIL');
print '</td></tr>';
// Web
print '<tr><td>' . $langs->trans('Web') . '</td><td colspan="3">';
print dol_print_url($soc->url);
print '</td></tr>';
// Phone / Fax
print '<tr><td>' . $langs->trans('Phone') . '</td><td>' . dol_print_phone($soc->tel, $soc->country_code, 0, $soc->id, 'AC_TEL') . '</td>';
print '<td>' . $langs->trans('Fax') . '</td><td>' . dol_print_phone($soc->fax, $soc->country_code, 0, $soc->id, 'AC_FAX') . '</td></tr>';
print '</table>';
print '</div>';
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
$prodcustprice = new Productcustomerprice($db);
$sortfield = GETPOST("sortfield", 'alpha');
$sortorder = GETPOST("sortorder", 'alpha');
$page = GETPOST("page", 'int');
if ($page == - 1) {
$page = 0;
}
$offset = $conf->liste_limit * $page;
$pageprev = $page - 1;
$pagenext = $page + 1;
if (! $sortorder)
$sortorder = "ASC";
if (! $sortfield)
$sortfield = "soc.nom";
// Build filter to diplay only concerned lines
$filter = array (
't.fk_soc' => $soc->id
);
$search_soc = GETPOST('search_soc');
if (! empty($search_soc)) {
$filter ['soc.nom'] = $search_soc;
}
if ($action == 'add_customer_price') {
// Create mode
print_fiche_titre($langs->trans('PriceByCustomer'));
print '<form action="' . $_SERVER ["PHP_SELF"] . '?socid=' . $soc->id . '" method="POST">';
print '<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">';
print '<input type="hidden" name="action" value="add_customer_price_confirm">';
print '<input type="hidden" name="socid" value="' . $soc->id . '">';
print '<table class="border" width="100%">';
print '<tr>';
print '<td>' . $langs->trans('Product') . '</td>';
print '<td>';
print $form->select_produits('', 'prodid', '', 0);
print '</td>';
print '</tr>';
// VAT
print '<tr><td>' . $langs->trans("VATRate") . '</td><td>';
print $form->load_tva("tva_tx", $object->tva_tx, $mysoc, '', $object->id, $object->tva_npr);
print '</td></tr>';
// Price base
print '<tr><td width="15%">';
print $langs->trans('PriceBase');
print '</td>';
print '<td>';
print $form->select_PriceBaseType($object->price_base_type, "price_base_type");
print '</td>';
print '</tr>';
// Price
print '<tr><td width="20%">';
$text = $langs->trans('SellingPrice');
print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1);
print '</td><td>';
if ($object->price_base_type == 'TTC') {
print '<input name="price" size="10" value="' . price($object->price_ttc) . '">';
} else {
print '<input name="price" size="10" value="' . price($object->price) . '">';
}
print '</td></tr>';
// Price minimum
print '<tr><td>';
$text = $langs->trans('MinPrice');
print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1);
if ($object->price_base_type == 'TTC') {
print '<td><input name="price_min" size="10" value="' . price($object->price_min_ttc) . '">';
} else {
print '<td><input name="price_min" size="10" value="' . price($object->price_min) . '">';
}
print '</td></tr>';
// Update all child soc
print '<tr><td width="15%">';
print $langs->trans('ForceUpdateChildPriceSoc');
print '</td>';
print '<td>';
print '<input type="checkbox" name="updatechildprice" value="1"/>';
print '</td>';
print '</tr>';
print '</table>';
print '<center><br><input type="submit" class="button" value="' . $langs->trans("Save") . '">&nbsp;';
print '<input type="submit" class="button" name="cancel" value="' . $langs->trans("Cancel") . '"></center>';
print '<br></form>';
} elseif ($action == 'edit_customer_price') {
// Edit mode
print_fiche_titre($langs->trans('PriceByCustomer'));
$result = $prodcustprice->fetch(GETPOST('lineid', 'int'));
if ($result < 0) {
setEventMessage($prodcustprice->error, 'errors');
}
print '<form action="' . $_SERVER ["PHP_SELF"] . '?socid=' . $soc->id . '" method="POST">';
print '<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">';
print '<input type="hidden" name="action" value="update_customer_price_confirm">';
print '<input type="hidden" name="lineid" value="' . $prodcustprice->id . '">';
print '<table class="border" width="100%">';
print '<tr>';
print '<td>' . $langs->trans('Product') . '</td>';
$staticprod = new Product($db);
$staticprod->fetch($prodcustprice->fk_product);
print "<td>" . $staticprod->getNomUrl(1) . "</td>";
print '</tr>';
// VAT
print '<tr><td>' . $langs->trans("VATRate") . '</td><td>';
print $form->load_tva("tva_tx", $prodcustprice->tva_tx, $mysoc, '', $staticprod->id, $prodcustprice->recuperableonly);
print '</td></tr>';
// Price base
print '<tr><td width="15%">';
print $langs->trans('PriceBase');
print '</td>';
print '<td>';
print $form->select_PriceBaseType($prodcustprice->price_base_type, "price_base_type");
print '</td>';
print '</tr>';
// Price
print '<tr><td width="20%">';
$text = $langs->trans('SellingPrice');
print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1);
print '</td><td>';
if ($prodcustprice->price_base_type == 'TTC') {
print '<input name="price" size="10" value="' . price($prodcustprice->price_ttc) . '">';
} else {
print '<input name="price" size="10" value="' . price($prodcustprice->price) . '">';
}
print '</td></tr>';
// Price minimum
print '<tr><td>';
$text = $langs->trans('MinPrice');
print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1);
if ($prodcustprice->price_base_type == 'TTC') {
print '<td><input name="price_min" size="10" value="' . price($prodcustprice->price_min_ttc) . '">';
} else {
print '<td><input name="price_min" size="10" value="' . price($prodcustprice->price_min) . '">';
}
print '</td></tr>';
// Update all child soc
print '<tr><td width="15%">';
print $langs->trans('ForceUpdateChildPriceSoc');
print '</td>';
print '<td>';
print '<input type="checkbox" name="updatechildprice" value="1">';
print '</td>';
print '</tr>';
print '</table>';
print '<center><br><input type="submit" class="button" value="' . $langs->trans("Save") . '">&nbsp;';
print '<input type="submit" class="button" name="cancel" value="' . $langs->trans("Cancel") . '"></center>';
print '<br></form>';
} elseif ($action == 'showlog_customer_price') {
$filter = array (
't.fk_product' => GETPOST('prodid', 'int'),'t.fk_soc' => $socid
);
// Count total nb of records
$nbtotalofrecords = 0;
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
$nbtotalofrecords = $prodcustprice->fetch_all_log($sortorder, $sortfield, $conf->liste_limit, $offset, $filter);
}
$result = $prodcustprice->fetch_all_log($sortorder, $sortfield, $conf->liste_limit, $offset, $filter);
if ($result < 0) {
setEventMessage($prodcustprice->error, 'errors');
}
$option = '&socid=' . GETPOST('socid', 'int') . '&prodid=' . GETPOST('prodid', 'int');
print_barre_liste($langs->trans('PriceByCustomerLog'), $page, $_SERVEUR ['PHP_SELF'], $option, $sortfield, $sortorder, '', count($prodcustprice->lines), $nbtotalofrecords);
if (count($prodcustprice->lines) > 0) {
print '<form action="' . $_SERVER ["PHP_SELF"] . '?id=' . $object->id . '" method="POST">';
print '<input type="hidden" name="id" value="' . $object->id . '">';
print '<table class="noborder" width="100%">';
print '<tr class="liste_titre">';
print '<td>' . $langs->trans("Product") . '</td>';
print '<td>' . $langs->trans("AppliedPricesFrom") . '</td>';
print '<td align="center">' . $langs->trans("PriceBase") . '</td>';
print '<td align="right">' . $langs->trans("VAT") . '</td>';
print '<td align="right">' . $langs->trans("HT") . '</td>';
print '<td align="right">' . $langs->trans("TTC") . '</td>';
print '<td align="right">' . $langs->trans("MinPrice") . ' ' . $langs->trans("HT") . '</td>';
print '<td align="right">' . $langs->trans("MinPrice") . ' ' . $langs->trans("TTC") . '</td>';
print '<td align="right">' . $langs->trans("ChangedBy") . '</td>';
print '<td>&nbsp;</td>';
print '</tr>';
$var = True;
foreach ( $prodcustprice->lines as $line ) {
print "<tr $bc[$var]>";
$staticprod = new Product($db);
$staticprod->fetch($line->fk_product);
print "<td>" . $staticprod->getNomUrl(1) . "</td>";
print "<td>" . dol_print_date($line->datec, "dayhour") . "</td>";
print '<td align="center">' . $langs->trans($line->price_base_type) . "</td>";
print '<td align="right">' . vatrate($line->tva_tx, true, $line->recuperableonly) . "</td>";
print '<td align="right">' . price($line->price) . "</td>";
print '<td align="right">' . price($line->price_ttc) . "</td>";
print '<td align="right">' . price($line->price_min) . '</td>';
print '<td align="right">' . price($line->price_min_ttc) . '</td>';
// User
$userstatic = new User($db);
$userstatic->fetch($line->fk_user);
print '<td align="right">';
print $userstatic->getLoginUrl(1);
print '</td>';
}
print "</table>";
} else {
print $langs->trans('None');
}
print "\n" . '<div class="tabsAction">' . "\n";
print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER ["PHP_SELF"] . '?socid=' . $soc->id . '">' . $langs->trans("Ok") . '</a></div>';
print "\n</div><br>\n";
} else {
// View mode
// Count total nb of records
$nbtotalofrecords = 0;
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
$nbtotalofrecords = $prodcustprice->fetch_all('', '', 0, 0, $filter);
}
$result = $prodcustprice->fetch_all($sortorder, $sortfield, $conf->liste_limit, $offset, $filter);
if ($result < 0) {
setEventMessage($prodcustprice->error, 'errors');
}
$option = '&search_soc=' . $search_soc . '&id=' . $object->id;
print_barre_liste($langs->trans('PriceByCustomer'), $page, $_SERVEUR ['PHP_SELF'], $option, $sortfield, $sortorder, '', count($prodcustprice->lines), $nbtotalofrecords);
if (count($prodcustprice->lines) > 0) {
print '<form action="' . $_SERVER ["PHP_SELF"] . '?id=' . $object->id . '" method="POST">';
print '<input type="hidden" name="id" value="' . $object->id . '">';
print '<table class="noborder" width="100%">';
print '<tr class="liste_titre">';
print '<td>' . $langs->trans("Product") . '</td>';
print '<td>' . $langs->trans("AppliedPricesFrom") . '</td>';
print '<td align="center">' . $langs->trans("PriceBase") . '</td>';
print '<td align="right">' . $langs->trans("VAT") . '</td>';
print '<td align="right">' . $langs->trans("HT") . '</td>';
print '<td align="right">' . $langs->trans("TTC") . '</td>';
print '<td align="right">' . $langs->trans("MinPrice") . ' ' . $langs->trans("HT") . '</td>';
print '<td align="right">' . $langs->trans("MinPrice") . ' ' . $langs->trans("TTC") . '</td>';
print '<td align="right">' . $langs->trans("ChangedBy") . '</td>';
print '<td>&nbsp;</td>';
print '</tr>';
print '<tr class="liste_titre">';
print '<td><input type="text" class="flat" name="search_soc" value="' . $search_soc . '" size="20"></td>';
print '<td colspan="8">&nbsp;</td>';
// Print the search button
print '<td class="liste_titre" align="right">';
print '<input class="liste_titre" name="button_search" type="image" src="' . DOL_URL_ROOT . '/theme/' . $conf->theme . '/img/search.png" value="' . dol_escape_htmltag($langs->trans("Search")) . '" title="' . dol_escape_htmltag($langs->trans("Search")) . '">';
print '</td>';
print '</tr>';
$var = True;
foreach ( $prodcustprice->lines as $line ) {
print "<tr $bc[$var]>";
$staticprod = new Product($db);
$staticprod->fetch($line->fk_product);
print "<td>" . $staticprod->getNomUrl(1) . "</td>";
print "<td>" . dol_print_date($line->datec, "dayhour") . "</td>";
print '<td align="center">' . $langs->trans($line->price_base_type) . "</td>";
print '<td align="right">' . vatrate($line->tva_tx, true, $line->recuperableonly) . "</td>";
print '<td align="right">' . price($line->price) . "</td>";
print '<td align="right">' . price($line->price_ttc) . "</td>";
print '<td align="right">' . price($line->price_min) . '</td>';
print '<td align="right">' . price($line->price_min_ttc) . '</td>';
// User
$userstatic = new User($db);
$userstatic->fetch($line->fk_user);
print '<td align="right">';
print $userstatic->getLoginUrl(1);
print '</td>';
// Todo Edit or delete button
// Action
if ($user->rights->produit->creer || $user->rights->service->creer) {
print '<td align="right">';
print '<a href="' . $_SERVER ["PHP_SELF"] . '?action=delete_customer_price&amp;socid=' . $soc->id . '&amp;lineid=' . $line->id . '">';
print img_delete();
print '</a>';
print '<a href="' . $_SERVER ["PHP_SELF"] . '?action=edit_customer_price&amp;socid=' . $soc->id . '&amp;lineid=' . $line->id . '">';
print img_edit();
print '</a>';
print '<a href="' . $_SERVER ["PHP_SELF"] . '?action=showlog_customer_price&amp;socid=' . $soc->id . '&amp;prodid=' . $line->fk_product . '">';
print img_info();
print '</a>';
print '</td>';
}
print "</tr>\n";
}
print "</table>";
print "</form>";
} else {
print $langs->trans('None');
}
/* ************************************************************************** */
/* */
/* Barre d'action */
/* */
/* ************************************************************************** */
print "\n" . '<div class="tabsAction">' . "\n";
if ($user->rights->produit->creer || $user->rights->service->creer) {
print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER ["PHP_SELF"] . '?action=add_customer_price&amp;socid=' . $soc->id . '">' . $langs->trans("AddCustomerPrice") . '</a></div>';
}
print "\n</div><br>\n";
}
}
llxFooter();
$db->close();
?>

View File

@ -229,7 +229,7 @@ $styleuse='encoded'; // encoded/literal/literal wrapped
$server->register(
'getProductOrService',
// Entry values
array('authentication'=>'tns:authentication','id'=>'xsd:string','ref'=>'xsd:string','ref_ext'=>'xsd:string'),
array('authentication'=>'tns:authentication','id'=>'xsd:string','ref'=>'xsd:string','ref_ext'=>'xsd:string','lang'=>'xsd:string'),
// Exit values
array('result'=>'tns:result','product'=>'tns:product'),
$ns,
@ -285,7 +285,7 @@ $server->register(
$server->register(
'getProductsForCategory',
// Entry values
array('authentication'=>'tns:authentication','id'=>'xsd:string'),
array('authentication'=>'tns:authentication','id'=>'xsd:string','lang'=>'xsd:string'),
// Exit values
array('result'=>'tns:result','products'=>'tns:ProductsArray2'),
$ns,
@ -303,9 +303,10 @@ $server->register(
* @param int $id Id of object
* @param string $ref Ref of object
* @param ref_ext $ref_ext Ref external of object
* @param $lang $lang Force lang
* @return mixed
*/
function getProductOrService($authentication,$id='',$ref='',$ref_ext='')
function getProductOrService($authentication,$id='',$ref='',$ref_ext='',$lang='')
{
global $db,$conf,$langs;
@ -327,6 +328,10 @@ function getProductOrService($authentication,$id='',$ref='',$ref_ext='')
if (! $error)
{
$langcode=($lang?$lang:(empty($conf->global->MAIN_LANG_DEFAULT)?'auto':$conf->global->MAIN_LANG_DEFAULT));
$langs->setDefaultLang($langcode);
$fuser->getrights();
if ($fuser->rights->produit->lire || $fuser->rights->service->lire)
@ -701,8 +706,14 @@ function getListOfProductsOrServices($authentication,$filterproduct)
}
// return category infos and children
function getProductsForCategory($authentication,$id)
/**
* getProductsForCategory
*
* @param array $authentication Array of authentication information
* @param array $id Category id
* @param $lang $lang Force lang
* @return array Array result
*/function getProductsForCategory($authentication,$id,$lang='')
{
global $db,$conf,$langs;
@ -726,6 +737,9 @@ function getProductsForCategory($authentication,$id)
if (! $error)
{
$langcode=($lang?$lang:(empty($conf->global->MAIN_LANG_DEFAULT)?'auto':$conf->global->MAIN_LANG_DEFAULT));
$langs->setDefaultLang($langcode);
$fuser->getrights();
if ($fuser->rights->produit->lire)