Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop

This commit is contained in:
Laurent Destailleur 2012-12-05 21:32:49 +01:00
commit 2cfd8fbd64
32 changed files with 1635 additions and 235 deletions

View File

@ -142,6 +142,27 @@ while($i<count($properties))
$targetcontent=preg_replace('/\'prop1\'=>\$'.$classmin.'->prop1,/', $varprop, $targetcontent);
$targetcontent=preg_replace('/\'prop2\'=>\$'.$classmin.'->prop2,/', '', $targetcontent);
// Substitute get method parameters
$varprop="\n\t\t";
$cleanparam='';
$i=0;
while($i<count($properties))
{
$varprop.='$newobject->'.$properties[$i].'=$'.$classmin.'->'.$properties[$i].';';
$i++;
if ($i == count($properties))
$varprop.="\n";
else
$varprop.="\n\t\t";
}
$targetcontent=preg_replace('/\$newobject->prop1=\$'.$classmin.'->prop1;/', $varprop, $targetcontent);
$targetcontent=preg_replace('/\$newobject->prop2=\$'.$classmin.'->prop2;/', '', $targetcontent);
// Build file
$fp=fopen($outfile,"w");
if ($fp)

View File

@ -118,11 +118,25 @@ $server->register(
'WS to get skeleton'
);
// Register WSDL
$server->register(
'createSkeleton',
// Entry values
array('authentication'=>'tns:authentication','skeleton'=>'tns:skeleton'),
// Exit values
array('result'=>'tns:result','id'=>'xsd:string'),
$ns,
$ns.'#createSkeleton',
$styledoc,
$styleuse,
'WS to create a skeleton'
);
/**
* Get produt or service
* Get Skeleton
*
* @param array $authentication Array of authentication information
* @param int $id Id of object
@ -192,6 +206,67 @@ function getSkeleton($authentication,$id,$ref='',$ref_ext='')
}
/**
* Create Skeleton
*
* @param array $authentication Array of authentication information
* @param Skeleton $skeleton $skeleton
* @return array Array result
*/
function createSkeleton($authentication,$skeleton)
{
global $db,$conf,$langs;
$now=dol_now();
dol_syslog("Function: createSkeleton login=".$authentication['login']);
if ($authentication['entity']) $conf->entity=$authentication['entity'];
// Init and check authentication
$objectresp=array();
$errorcode='';$errorlabel='';
$error=0;
$fuser=check_authentication($authentication,$error,$errorcode,$errorlabel);
// Check parameters
if (! $error)
{
$newobject=new Skeleton($db);
$newobject->prop1=$skeleton->prop1;
$newobject->prop2=$skeleton->prop2;
//...
$db->begin();
$result=$newobject->create($fuser);
if ($result <= 0)
{
$error++;
}
if (! $error)
{
$db->commit();
$objectresp=array('result'=>array('result_code'=>'OK', 'result_label'=>''),'id'=>$newobject->id,'ref'=>$newobject->ref);
}
else
{
$db->rollback();
$error++;
$errorcode='KO';
$errorlabel=$newobject->error;
}
}
if ($error)
{
$objectresp = array('result'=>array('result_code' => $errorcode, 'result_label' => $errorlabel));
}
return $objectresp;
}
// Return the results.
$server->service($HTTP_RAW_POST_DATA);

View File

@ -2221,6 +2221,24 @@ if ($action == 'send' && ! GETPOST('addfile') && ! GETPOST('removedfile') && ! G
}
}
// Create intervention
if ($conf->ficheinter->enabled)
{
$langs->load("interventions");
if ($object->statut > 0 && $object->statut < 3 && $object->getNbOfServicesLines() > 0)
{
if ($user->rights->ficheinter->creer)
{
print '<a class="butAction" href="'.DOL_URL_ROOT.'/fichinter/fiche.php?action=create&amp;origin='.$object->element.'&amp;originid='.$object->id.'&amp;socid='.$object->socid.'">'.$langs->trans('AddIntervention').'</a>';
}
else
{
print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'">'.$langs->trans('AddIntervention').'</a>';
}
}
}
// Reopen a closed order
if ($object->statut == 3)
{

View File

@ -79,6 +79,7 @@ if (! empty($field) && ! empty($element) && ! empty($table_element) && ! empty($
$newelement = 'fournisseur';
$subelement = 'facture';
}
else $newelement = $element;
if (! empty($user->rights->$newelement->creer) || ! empty($user->rights->$newelement->write)
|| (isset($subelement) && (! empty($user->rights->$newelement->$subelement->creer) || ! empty($user->rights->$newelement->$subelement->write)))

View File

@ -458,26 +458,26 @@ class Conf
if (is_object($mc)) $mc->setValues($this);
}
// We init log handlers
if (defined('SYSLOG_HANDLERS')) $handlers = json_decode(constant('SYSLOG_HANDLERS'));
else $handlers = array();
foreach ($handlers as $handler)
{
$file = DOL_DOCUMENT_ROOT.'/core/modules/syslog/'.$handler.'.php';
if (!file_exists($file))
{
throw new Exception('Missing log handler file '.$handler.'.php');
}
require_once $file;
$loghandlerinstance = new $handler();
if (!$loghandlerinstance instanceof LogHandlerInterface)
{
throw new Exception('Log handler does not extend LogHandlerInterface');
}
// We init log handlers
if (defined('SYSLOG_HANDLERS')) $handlers = json_decode(constant('SYSLOG_HANDLERS'));
else $handlers = array();
foreach ($handlers as $handler)
{
$file = DOL_DOCUMENT_ROOT.'/core/modules/syslog/'.$handler.'.php';
if (!file_exists($file))
{
throw new Exception('Missing log handler file '.$handler.'.php');
}
$this->loghandlers[]=$loghandlerinstance;
}
require_once $file;
$loghandlerinstance = new $handler();
if (!$loghandlerinstance instanceof LogHandlerInterface)
{
throw new Exception('Log handler does not extend LogHandlerInterface');
}
$this->loghandlers[]=$loghandlerinstance;
}
}
}

View File

@ -1153,6 +1153,18 @@ class Form
{
$sql.= ", pl.label as label_translated";
}
// Price by quantity
if (! empty($conf->global->PRODUIT_PRICE_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;
$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;
$sql.= " ORDER BY date_price";
$sql.= " DESC LIMIT 1) as price_by_qty";
}
$sql.= " FROM ".MAIN_DB_PREFIX."product as p";
// Multilang : we add translation
if (! empty($conf->global->MAIN_MULTILANGS))
@ -1214,137 +1226,51 @@ class Form
$i = 0;
while ($num && $i < $num)
{
$outkey='';
$outval='';
$outref='';
$outlabel='';
$outdesc='';
$outtype='';
$outprice_ht='';
$outprice_ttc='';
$outpricebasetype='';
$outtva_tx='';
$objp = $this->db->fetch_object($result);
$label=$objp->label;
if (! empty($objp->label_translated)) $label=$objp->label_translated;
if ($filterkey && $filterkey != '') $label=preg_replace('/('.preg_quote($filterkey).')/i','<strong>$1</strong>',$label,1);
$outkey=$objp->rowid;
$outref=$objp->ref;
$outlabel=$objp->label;
$outdesc=$objp->description;
$outtype=$objp->fk_product_type;
$opt = '<option value="'.$objp->rowid.'"';
$opt.= ($objp->rowid == $selected)?' selected="selected"':'';
if (! empty($conf->stock->enabled) && $objp->fk_product_type == 0 && isset($objp->stock))
{
if ($objp->stock > 0) $opt.= ' class="product_line_stock_ok"';
else if ($objp->stock <= 0) $opt.= ' class="product_line_stock_too_low"';
}
$opt.= '>';
$opt.= $objp->ref.' - '.dol_trunc($label,32).' - ';
$objRef = $objp->ref;
if ($filterkey && $filterkey != '') $objRef=preg_replace('/('.preg_quote($filterkey).')/i','<strong>$1</strong>',$objRef,1);
$outval.=$objRef.' - '.dol_trunc($label,32).' - ';
$found=0;
$currencytext=$langs->trans("Currency".$conf->currency);
$currencytextnoent=$langs->transnoentities("Currency".$conf->currency);
if (dol_strlen($currencytext) > 10) $currencytext=$conf->currency; // If text is too long, we use the short code
if (dol_strlen($currencytextnoent) > 10) $currencytextnoent=$conf->currency; // If text is too long, we use the short code
// Multiprice
if ($price_level >= 1) // 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='".$objp->rowid."'";
$sql.= " AND price_level=".$price_level;
$sql.= " ORDER BY date_price";
$sql.= " DESC LIMIT 1";
dol_syslog(get_class($this)."::select_produits_do search price for level '.$price_level.' sql=".$sql);
$result2 = $this->db->query($sql);
if ($result2)
{
$objp2 = $this->db->fetch_object($result2);
if ($objp2)
{
$found=1;
if ($objp2->price_base_type == 'HT')
{
$opt.= price($objp2->price,1).' '.$currencytext.' '.$langs->trans("HT");
$outval.= price($objp2->price,1).' '.$currencytextnoent.' '.$langs->transnoentities("HT");
}
else
{
$opt.= price($objp2->price_ttc,1).' '.$currencytext.' '.$langs->trans("TTC");
$outval.= price($objp2->price_ttc,1).' '.$currencytextnoent.' '.$langs->transnoentities("TTC");
}
$outprice_ht=price($objp2->price);
$outprice_ttc=price($objp2->price_ttc);
$outpricebasetype=$objp2->price_base_type;
$outtva_tx=$objp2->tva_tx;
}
}
else
{
dol_print_error($this->db);
}
}
// If level no defined or multiprice not found, we used the default price
if (! $found)
{
if ($objp->price_base_type == 'HT')
{
$opt.= price($objp->price,1).' '.$currencytext.' '.$langs->trans("HT");
$outval.= price($objp->price,1).' '.$currencytextnoent.' '.$langs->transnoentities("HT");
}
else
{
$opt.= price($objp->price_ttc,1).' '.$currencytext.' '.$langs->trans("TTC");
$outval.= price($objp->price_ttc,1).' '.$currencytextnoent.' '.$langs->transnoentities("TTC");
}
$outprice_ht=price($objp->price);
$outprice_ttc=price($objp->price_ttc);
$outpricebasetype=$objp->price_base_type;
$outtva_tx=$objp->tva_tx;
}
if (! empty($conf->stock->enabled) && isset($objp->stock) && $objp->fk_product_type == 0)
{
$opt.= ' - '.$langs->trans("Stock").':'.$objp->stock;
$outval.=' - '.$langs->transnoentities("Stock").':'.$objp->stock;
}
if ($objp->duration)
{
$duration_value = substr($objp->duration,0,dol_strlen($objp->duration)-1);
$duration_unit = substr($objp->duration,-1);
if ($duration_value > 1)
{
$dur=array("h"=>$langs->trans("Hours"),"d"=>$langs->trans("Days"),"w"=>$langs->trans("Weeks"),"m"=>$langs->trans("Months"),"y"=>$langs->trans("Years"));
}
else
{
$dur=array("h"=>$langs->trans("Hour"),"d"=>$langs->trans("Day"),"w"=>$langs->trans("Week"),"m"=>$langs->trans("Month"),"y"=>$langs->trans("Year"));
}
$opt.= ' - '.$duration_value.' '.$langs->trans($dur[$duration_unit]);
$outval.=' - '.$duration_value.' '.$langs->transnoentities($dur[$duration_unit]);
}
$opt.= "</option>\n";
// Add new entry
// "key" value of json key array is used by jQuery automatically as selected value
// "label" value of json key array is used by jQuery automatically as text for combo box
$outselect.=$opt;
array_push($outjson, array('key'=>$outkey, 'value'=>$outref, 'label'=>$outval, 'label2'=>$outlabel, 'desc'=>$outdesc, 'type'=>$outtype, 'price_ht'=>$outprice_ht, 'price_ttc'=>$outprice_ttc, 'pricebasetype'=>$outpricebasetype, 'tva_tx'=>$outtva_tx));
$opt = '';
$optJson = array();
$objp = $this->db->fetch_object($result);
if(!empty($objp->price_by_qty) && $objp->price_by_qty == 1) { // 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";
$sql.= " WHERE fk_product_price=".$objp->price_rowid;
$sql.= " ORDER BY quantity ASC";
dol_syslog(get_class($this)."::select_produits_do search price by qty sql=".$sql);
$result2 = $this->db->query($sql);
if ($result2)
{
$nb_prices = $this->db->num_rows($result2);
$j = 0;
while ($nb_prices && $j < $nb_prices) {
$objp2 = $this->db->fetch_object($result2);
$objp->quantity = $objp2->quantity;
$objp->price = $objp2->price;
$objp->unitprice = $objp2->unitprice;
$objp->remise_percent = $objp2->remise_percent;
$objp->remise = $objp2->remise;
$objp->price_by_qty_rowid = $objp2->rowid;
$this->_construct_product_list_option($objp, $opt, $optJson, 0, $selected);
$j++;
// Add new entry
// "key" value of json key array is used by jQuery automatically as selected value
// "label" value of json key array is used by jQuery automatically as text for combo box
$outselect.=$opt;
array_push($outjson, $optJson);
}
}
} else {
$this->_construct_product_list_option($objp, $opt, $optJson, $price_level, $selected);
// Add new entry
// "key" value of json key array is used by jQuery automatically as selected value
// "label" value of json key array is used by jQuery automatically as text for combo box
$outselect.=$opt;
array_push($outjson, $optJson);
}
$i++;
}
@ -1362,6 +1288,174 @@ class Form
}
}
function _construct_product_list_option(&$objp, &$opt, &$optJson, $price_level, $selected) {
global $langs,$conf,$user,$db;
$outkey='';
$outval='';
$outref='';
$outlabel='';
$outdesc='';
$outtype='';
$outprice_ht='';
$outprice_ttc='';
$outpricebasetype='';
$outtva_tx='';
$outqty=1;
$outdiscount=0;
$label=$objp->label;
if (! empty($objp->label_translated)) $label=$objp->label_translated;
if ($filterkey && $filterkey != '') $label=preg_replace('/('.preg_quote($filterkey).')/i','<strong>$1</strong>',$label,1);
$outkey=$objp->rowid;
$outref=$objp->ref;
$outlabel=$objp->label;
$outdesc=$objp->description;
$outtype=$objp->fk_product_type;
$opt = '<option value="'.$objp->rowid.'"';
$opt.= ($objp->rowid == $selected)?' selected="selected"':'';
$opt.= (!empty($objp->price_by_qty_rowid) && $objp->price_by_qty_rowid > 0)?' pbq="'.$objp->price_by_qty_rowid.'"':'';
if (! empty($conf->stock->enabled) && $objp->fk_product_type == 0 && isset($objp->stock))
{
if ($objp->stock > 0) $opt.= ' class="product_line_stock_ok"';
else if ($objp->stock <= 0) $opt.= ' class="product_line_stock_too_low"';
}
$opt.= '>';
$opt.= $objp->ref.' - '.dol_trunc($label,32).' - ';
$objRef = $objp->ref;
if ($filterkey && $filterkey != '') $objRef=preg_replace('/('.preg_quote($filterkey).')/i','<strong>$1</strong>',$objRef,1);
$outval.=$objRef.' - '.dol_trunc($label,32).' - ';
$found=0;
$currencytext=$langs->trans("Currency".$conf->currency);
$currencytextnoent=$langs->transnoentities("Currency".$conf->currency);
if (dol_strlen($currencytext) > 10) $currencytext=$conf->currency; // If text is too long, we use the short code
if (dol_strlen($currencytextnoent) > 10) $currencytextnoent=$conf->currency; // If text is too long, we use the short code
// Multiprice
if ($price_level >= 1) // 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='".$objp->rowid."'";
$sql.= " AND price_level=".$price_level;
$sql.= " ORDER BY date_price";
$sql.= " DESC LIMIT 1";
dol_syslog(get_class($this)."::select_produits_do search price for level '.$price_level.' sql=".$sql);
$result2 = $this->db->query($sql);
if ($result2)
{
$objp2 = $this->db->fetch_object($result2);
if ($objp2)
{
$found=1;
if ($objp2->price_base_type == 'HT')
{
$opt.= price($objp2->price,1).' '.$currencytext.' '.$langs->trans("HT");
$outval.= price($objp2->price,1).' '.$currencytextnoent.' '.$langs->transnoentities("HT");
}
else
{
$opt.= price($objp2->price_ttc,1).' '.$currencytext.' '.$langs->trans("TTC");
$outval.= price($objp2->price_ttc,1).' '.$currencytextnoent.' '.$langs->transnoentities("TTC");
}
$outprice_ht=price($objp2->price);
$outprice_ttc=price($objp2->price_ttc);
$outpricebasetype=$objp2->price_base_type;
$outtva_tx=$objp2->tva_tx;
}
}
else
{
dol_print_error($this->db);
}
}
// Price by quantity
if (!empty($objp->quantity) && $objp->quantity >= 1) {
$found = 1;
$outqty=$objp->quantity;
$outdiscount=$objp->remise_percent;
if ($objp->quantity == 1)
{
$opt.= price($objp->unitprice).' '.$currencytext."/";
$outval.= price($objp->unitprice).' '.$currencytextnoent."/";
$opt.= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
$outval.=$langs->transnoentities("Unit");
}
else
{
$opt.= price($objp->price).' '.$currencytext."/".$objp->quantity;
$outval.= price($objp->price).' '.$currencytextnoent."/".$objp->quantity;
$opt.= $langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
$outval.=$langs->transnoentities("Units");
}
$outprice_ht=price($objp->unitprice);
$outprice_ttc=price($objp->unitprice * (1 + ($objp->tva_tx / 100)));
$outpricebasetype=$objp->price_base_type;
$outtva_tx=$objp->tva_tx;
}
if (!empty($objp->quantity) && $objp->quantity >= 1)
{
$opt.=" (".price($objp->unitprice).' '.$currencytext."/".$langs->trans("Unit").")"; // Do not use strtolower because it breaks utf8 encoding
$outval.=" (".price($objp->unitprice).' '.$currencytextnoent."/".$langs->transnoentities("Unit").")"; // Do not use strtolower because it breaks utf8 encoding
}
if (!empty($objp->remise_percent) && $objp->remise_percent >= 1)
{
$opt.=" - ".$langs->trans("Discount")." : ".vatrate($objp->remise_percent).' %';
$outval.=" - ".$langs->transnoentities("Discount")." : ".vatrate($objp->remise_percent).' %';
}
// If level no defined or multiprice not found, we used the default price
if (! $found)
{
if ($objp->price_base_type == 'HT')
{
$opt.= price($objp->price,1).' '.$currencytext.' '.$langs->trans("HT");
$outval.= price($objp->price,1).' '.$currencytextnoent.' '.$langs->transnoentities("HT");
}
else
{
$opt.= price($objp->price_ttc,1).' '.$currencytext.' '.$langs->trans("TTC");
$outval.= price($objp->price_ttc,1).' '.$currencytextnoent.' '.$langs->transnoentities("TTC");
}
$outprice_ht=price($objp->price);
$outprice_ttc=price($objp->price_ttc);
$outpricebasetype=$objp->price_base_type;
$outtva_tx=$objp->tva_tx;
}
if (! empty($conf->stock->enabled) && isset($objp->stock) && $objp->fk_product_type == 0)
{
$opt.= ' - '.$langs->trans("Stock").':'.$objp->stock;
$outval.=' - '.$langs->transnoentities("Stock").':'.$objp->stock;
}
if ($objp->duration)
{
$duration_value = substr($objp->duration,0,dol_strlen($objp->duration)-1);
$duration_unit = substr($objp->duration,-1);
if ($duration_value > 1)
{
$dur=array("h"=>$langs->trans("Hours"),"d"=>$langs->trans("Days"),"w"=>$langs->trans("Weeks"),"m"=>$langs->trans("Months"),"y"=>$langs->trans("Years"));
}
else
{
$dur=array("h"=>$langs->trans("Hour"),"d"=>$langs->trans("Day"),"w"=>$langs->trans("Week"),"m"=>$langs->trans("Month"),"y"=>$langs->trans("Year"));
}
$opt.= ' - '.$duration_value.' '.$langs->trans($dur[$duration_unit]);
$outval.=' - '.$duration_value.' '.$langs->transnoentities($dur[$duration_unit]);
}
$opt.= "</option>\n";
$optJson = array('key'=>$outkey, 'value'=>$outref, 'label'=>$outval, 'label2'=>$outlabel, 'desc'=>$outdesc, 'type'=>$outtype, 'price_ht'=>$outprice_ht, 'price_ttc'=>$outprice_ttc, 'pricebasetype'=>$outpricebasetype, 'tva_tx'=>$outtva_tx, 'qty'=>$outqty, 'discount'=>$outdiscount);
}
/**
* Return list of products for customer (in Ajax if Ajax activated or go to select_produits_fournisseurs_do)
*
@ -1536,7 +1630,7 @@ class Form
}
}
else
{
{
$opt.= $langs->trans("NoPriceDefinedForThisSupplier");
$outval.=$langs->transnoentities("NoPriceDefinedForThisSupplier");
}

View File

@ -547,10 +547,10 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0)
if (! empty($ident))
{
foreach ($conf->loghandlers as $loghandlerinstance)
{
$loghandlerinstance->setIdent($ident);
}
foreach ($conf->loghandlers as $loghandlerinstance)
{
$loghandlerinstance->setIdent($ident);
}
}
}

View File

@ -607,6 +607,7 @@ function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$m
if ($maskraz > 0) // A reset is required
{
if ($maskraz == 99) $maskraz = date('m');
if ($maskraz > 12) return 'ErrorBadMaskBadRazMonth';
// Define posy, posm and reg

View File

@ -62,14 +62,14 @@ class LogHandler
return array();
}
/**
* Set current ident.
/**
* Set current ident.
*
* @param int $ident 1=Increase ident of 1, -1=Decrease ident of 1
* @return void
*/
public function setIdent($ident)
* @return void
*/
public function setIdent($ident)
{
$this->ident+=$ident;
}
}
}

View File

@ -79,7 +79,9 @@ if (! empty($conf->margin->enabled)) {
'price_ht' => 'price_ht',
'origin_price_ht_cache' => 'price_ht',
'origin_tva_tx_cache' => 'tva_tx',
'origin_price_ttc_cache' => 'price_ttc'
'origin_price_ttc_cache' => 'price_ttc',
'qty' => 'qty',
'remise_percent' => 'discount'
),
'update_textarea' => array(
'product_desc' => 'desc'
@ -158,7 +160,7 @@ if (! empty($conf->margin->enabled)) {
<input type="hidden" id="origin_price_ttc_cache" name="origin_price_ttc_cache" value="" />
</td>
<td align="right"><input type="text" size="3" id="qty" name="qty" value="<?php echo (GETPOST('qty')?GETPOST('qty'):1); ?>"></td>
<td align="right" nowrap="nowrap"><input type="text" size="1" value="<?php echo $buyer->remise_client; ?>" name="remise_percent">%</td>
<td align="right" nowrap="nowrap"><input type="text" size="1" value="<?php echo $buyer->remise_client; ?>" id="remise_percent" name="remise_percent">%</td>
<?php
$colspan = 4;
if (! empty($conf->margin->enabled)) {
@ -225,7 +227,9 @@ $(document).ready(function() {
$.post('<?php echo DOL_URL_ROOT; ?>/product/ajax/products.php', {
'action': 'fetch',
'id': $(this).val(),
'price_level': <?php echo empty($buyer->price_level)?1:$buyer->price_level; ?>},
'price_level': <?php echo empty($buyer->price_level)?1:$buyer->price_level; ?>,
'pbq': $("option:selected", this).attr('pbq')
},
function(data) {
if (typeof data != 'undefined') {
$('#product_ref').val(data.ref);
@ -237,6 +241,8 @@ $(document).ready(function() {
$('#origin_tva_tx_cache').val(data.tva_tx);
$('#select_type').val(data.type).attr('disabled','disabled').trigger('change');
//$('#price_base_type_area').show();
$('#qty').val(data.qty);
$('#remise_percent').val(data.discount);
if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined" && CKEDITOR.instances['product_desc'] != "undefined") {
CKEDITOR.instances['product_desc'].setData(data.desc).focus();

View File

@ -156,6 +156,14 @@ class Fichinter extends CommonObject
if ($result)
{
$this->id=$this->db->last_insert_id(MAIN_DB_PREFIX."fichinter");
// Add linked object
if (! $error && $this->origin && $this->origin_id)
{
$ret = $this->add_object_linked();
if (! $ret) dol_print_error($this->db);
}
$this->db->commit();
// Appel des triggers

View File

@ -141,16 +141,144 @@ else if ($action == 'add' && $user->rights->ficheinter->creer)
if ($object->socid > 0)
{
$result = $object->create();
if ($result > 0)
{
$id=$result; // Force raffraichissement sur fiche venant d'etre cree
}
else
{
$langs->load("errors");
$mesg='<div class="error">'.$langs->trans($object->error).'</div>';
$action = 'create';
// If creation from another object of another module (Example: origin=propal, originid=1)
if ($_POST['origin'] && $_POST['originid'])
{
// Parse element/subelement (ex: project_task)
$element = $subelement = $_POST['origin'];
if (preg_match('/^([^_]+)_([^_]+)/i',$_POST['origin'],$regs))
{
$element = $regs[1];
$subelement = $regs[2];
}
// For compatibility
if ($element == 'order') { $element = $subelement = 'commande'; }
if ($element == 'propal') { $element = 'comm/propal'; $subelement = 'propal'; }
if ($element == 'contract') { $element = $subelement = 'contrat'; }
$object->origin = $_POST['origin'];
$object->origin_id = $_POST['originid'];
// Possibility to add external linked objects with hooks
$object->linked_objects[$object->origin] = $object->origin_id;
if (is_array($_POST['other_linked_objects']) && ! empty($_POST['other_linked_objects']))
{
$object->linked_objects = array_merge($object->linked_objects, $_POST['other_linked_objects']);
}
$object_id = $object->create($user);
if ($object_id > 0)
{
dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
$classname = ucfirst($subelement);
$srcobject = new $classname($db);
dol_syslog("Try to find source object origin=".$object->origin." originid=".$object->origin_id." to add lines");
$result=$srcobject->fetch($object->origin_id);
if ($result > 0)
{
$srcobject->fetch_thirdparty();
$lines = $srcobject->lines;
if (empty($lines) && method_exists($srcobject,'fetch_lines')) $lines = $srcobject->fetch_lines();
$fk_parent_line=0;
$num=count($lines);
for ($i=0;$i<$num;$i++)
{
$product_type=($lines[$i]->product_type?$lines[$i]->product_type:0);
if ($product_type == 1) { //only services
// service prédéfini
if ($lines[$i]->fk_product > 0)
{
$product_static = new Product($db);
// Define output language
if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE))
{
$prod = new Product($db, $lines[$i]->fk_product);
$outputlangs = $langs;
$newlang='';
if (empty($newlang) && GETPOST('lang_id')) $newlang=GETPOST('lang_id');
if (empty($newlang)) $newlang=$srcobject->client->default_lang;
if (! empty($newlang))
{
$outputlangs = new Translate("",$conf);
$outputlangs->setDefaultLang($newlang);
}
$label = (! empty($prod->multilangs[$outputlangs->defaultlang]["libelle"])) ? $prod->multilangs[$outputlangs->defaultlang]["libelle"] : $lines[$i]->product_label;
}
else
{
$label = $lines[$i]->product_label;
}
$product_static->type=$lines[$i]->fk_product_type;
$product_static->id=$lines[$i]->fk_product;
$product_static->ref=$lines[$i]->ref;
$product_static->libelle=$label;
$desc=$product_static->getNomUrl(0);
$desc.= ' - '.$label;
$desc .= ' ('.$langs->trans('Quantity').': '.$lines[$i]->qty.')';
if ($conf->global->PRODUIT_DESC_IN_FORM)
$desc .= ($lines[$i]->desc && $lines[$i]->desc!=$lines[$i]->libelle)?'<br>'.dol_htmlentitiesbr($lines[$i]->desc):'';
}
else {
$desc = dol_htmlentitiesbr($lines[$i]->desc);
$desc .= ' ('.$langs->trans('Quantity').': '.$lines[$i]->qty.')';
}
$timearray=dol_getdate(mktime());
$date_intervention=dol_mktime(0,0,0,$timearray['mon'],$timearray['mday'],$timearray['year']);
$duration = 3600;
$result = $object->addline(
$object_id,
$desc,
$date_intervention,
$duration
);
if ($result < 0)
{
$error++;
break;
}
}
}
}
else
{
$mesg=$srcobject->error;
$error++;
}
}
else
{
$mesg=$object->error;
$error++;
}
}
else
{
$result = $object->create();
if ($result > 0)
{
$id=$result; // Force raffraichissement sur fiche venant d'etre cree
}
else
{
$langs->load("errors");
$mesg='<div class="error">'.$langs->trans($object->error).'</div>';
$action = 'create';
}
}
}
else
@ -732,6 +860,54 @@ if ($action == 'create')
dol_htmloutput_mesg($mesg);
if ($socid) $res=$soc->fetch($socid);
if (GETPOST('origin') && GETPOST('originid'))
{
// Parse element/subelement (ex: project_task)
$element = $subelement = GETPOST('origin');
if (preg_match('/^([^_]+)_([^_]+)/i',GETPOST('origin'),$regs))
{
$element = $regs[1];
$subelement = $regs[2];
}
if ($element == 'project')
{
$projectid=GETPOST('originid');
}
else
{
// For compatibility
if ($element == 'order' || $element == 'commande') { $element = $subelement = 'commande'; }
if ($element == 'propal') { $element = 'comm/propal'; $subelement = 'propal'; }
if ($element == 'contract') { $element = $subelement = 'contrat'; }
dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
$classname = ucfirst($subelement);
$objectsrc = new $classname($db);
$objectsrc->fetch(GETPOST('originid'));
if (empty($objectsrc->lines) && method_exists($objectsrc,'fetch_lines')) $objectsrc->fetch_lines();
$objectsrc->fetch_thirdparty();
$projectid = (!empty($objectsrc->fk_project)?$objectsrc->fk_project:'');
$soc = $objectsrc->client;
$note_private = (! empty($objectsrc->note) ? $objectsrc->note : (! empty($objectsrc->note_private) ? $objectsrc->note_private : ''));
$note_public = (! empty($objectsrc->note_public) ? $objectsrc->note_public : '');
// Object source contacts list
$srccontactslist = $objectsrc->liste_contact(-1,'external',1);
}
}
else {
$projectid = GETPOST('projectid','int');
$note_private = '';
$note_public = '';
}
if (! $conf->global->FICHEINTER_ADDON)
{
dol_print_error($db,$langs->trans("Error")." ".$langs->trans("Error_FICHEINTER_ADDON_NotDefined"));
@ -802,7 +978,7 @@ if ($action == 'create')
print '<tr>';
print '<td class="border" valign="top">'.$langs->trans('NotePublic').'</td>';
print '<td valign="top" colspan="2">';
print '<textarea name="note_public" cols="80" rows="'.ROWS_3.'"></textarea>';
print '<textarea name="note_public" cols="80" rows="'.ROWS_3.'">'.$note_public.'</textarea>';
print '</td></tr>';
// Private note
@ -811,7 +987,7 @@ if ($action == 'create')
print '<tr>';
print '<td class="border" valign="top">'.$langs->trans('NotePrivate').'</td>';
print '<td valign="top" colspan="2">';
print '<textarea name="note_private" cols="80" rows="'.ROWS_3.'"></textarea>';
print '<textarea name="note_private" cols="80" rows="'.ROWS_3.'">'.$note_private.'</textarea>';
print '</td></tr>';
}
@ -821,6 +997,12 @@ if ($action == 'create')
print '</table>';
if (is_object($objectsrc))
{
print '<input type="hidden" name="origin" value="'.$objectsrc->element.'">';
print '<input type="hidden" name="originid" value="'.$objectsrc->id.'">';
}
print '<center><br>';
print '<input type="submit" class="button" value="'.$langs->trans("CreateDraftIntervention").'">';
print '</center>';

View File

@ -1274,7 +1274,7 @@ else
//'text' => $langs->trans("ConfirmClone"),
//array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
//array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockDecrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse'),'idwarehouse','',1)));
array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockIncrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse'),'idwarehouse','',1)));
}
$ret=$form->form_confirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateBill'), $langs->trans('ConfirmValidateBill', $object->ref), 'confirm_valid', $formquestion, 1, 1, 240);

View File

@ -3,6 +3,7 @@
* Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2005-2007 Regis Houssin <regis@dolibarr.fr>
* Copyright (C) 2010 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.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
@ -99,6 +100,10 @@ if ($_POST["mode"] == 'search')
{
$sql .= " AND (p.ref LIKE '%".$_POST["sall"]."%'";
$sql .= " OR p.label LIKE '%".$_POST["sall"]."%')";
if ($sRefSupplier)
{
$sql .= " AND ppf.ref_fourn LIKE '%".$sRefSupplier."%'";
}
}
else
{

View File

@ -38,27 +38,27 @@ $langs->load("errors");
dolibarr_install_syslog("Fileconf: Entering fileconf.php page");
// You can force preselected values of the config step of Dolibarr by adding a file
// install.forced.php into directory htdocs/install (This is the case with some wizard
// installer like DoliWamp, DoliMamp or DoliBuntu).
// We first init "forced values" to nothing.
if (! isset($force_install_noedit)) $force_install_noedit=''; // 1=To block var specific to distrib, 2 to block all technical parameters
if (! isset($force_install_type)) $force_install_type='';
if (! isset($force_install_dbserver)) $force_install_dbserver='';
if (! isset($force_install_port)) $force_install_port='';
if (! isset($force_install_database)) $force_install_database='';
if (! isset($force_install_prefix)) $force_install_prefix='';
if (! isset($force_install_createdatabase)) $force_install_createdatabase='';
if (! isset($force_install_databaselogin)) $force_install_databaselogin='';
if (! isset($force_install_databasepass)) $force_install_databasepass='';
if (! isset($force_install_databaserootlogin)) $force_install_databaserootlogin='';
if (! isset($force_install_databaserootpass)) $force_install_databaserootpass='';
// Now we load forced value from install.forced.php file.
$useforcedwizard=false;
$forcedfile="./install.forced.php";
if ($conffile == "/etc/dolibarr/conf.php") $forcedfile="/etc/dolibarr/install.forced.php"; // Must be after inc.php
if (@file_exists($forcedfile)) {
$useforcedwizard=true; include_once $forcedfile;
// You can force preselected values of the config step of Dolibarr by adding a file
// install.forced.php into directory htdocs/install (This is the case with some wizard
// installer like DoliWamp, DoliMamp or DoliBuntu).
// We first init "forced values" to nothing.
if (! isset($force_install_noedit)) $force_install_noedit=''; // 1=To block var specific to distrib, 2 to block all technical parameters
if (! isset($force_install_type)) $force_install_type='';
if (! isset($force_install_dbserver)) $force_install_dbserver='';
if (! isset($force_install_port)) $force_install_port='';
if (! isset($force_install_database)) $force_install_database='';
if (! isset($force_install_prefix)) $force_install_prefix='';
if (! isset($force_install_createdatabase)) $force_install_createdatabase='';
if (! isset($force_install_databaselogin)) $force_install_databaselogin='';
if (! isset($force_install_databasepass)) $force_install_databasepass='';
if (! isset($force_install_databaserootlogin)) $force_install_databaserootlogin='';
if (! isset($force_install_databaserootpass)) $force_install_databaserootpass='';
// Now we load forced value from install.forced.php file.
$useforcedwizard=false;
$forcedfile="./install.forced.php";
if ($conffile == "/etc/dolibarr/conf.php") $forcedfile="/etc/dolibarr/install.forced.php"; // Must be after inc.php
if (@file_exists($forcedfile)) {
$useforcedwizard=true; include_once $forcedfile;
}
//$force_install_message='This is the message';

View File

@ -801,6 +801,28 @@ ALTER TABLE llx_categorie ADD UNIQUE INDEX uk_categorie_ref (entity, fk_parent,
ALTER TABLE llx_categorie ADD INDEX idx_categorie_type (type);
ALTER TABLE llx_categorie ADD INDEX idx_categorie_label (label);
-- [ task #559 ] Price by quantity management
CREATE TABLE llx_product_price_by_qty
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
fk_product_price integer NOT NULL,
date_price timestamp,
price double (24,8) DEFAULT 0,
price_ttc double (24,8) DEFAULT 0,
qty_min real DEFAULT 0
)ENGINE=innodb;
ALTER TABLE llx_product_price ADD price_by_qty INT NOT NULL DEFAULT 0;
ALTER TABLE llx_product_price_by_qty ADD UNIQUE INDEX uk_product_price_by_qty_level (fk_product_price, qty_min);
ALTER TABLE llx_product_price_by_qty ADD INDEX idx_product_price_by_qty_fk_product_price (fk_product_price);
ALTER TABLE llx_product_price_by_qty ADD CONSTRAINT fk_product_price_by_qty_fk_product_price FOREIGN KEY (fk_product_price) REFERENCES llx_product_price (rowid);
ALTER TABLE `llx_product_price_by_qty` ADD `remise_percent` DOUBLE NOT NULL DEFAULT '0' AFTER `price_ttc` ,
ADD `remise` DOUBLE NOT NULL DEFAULT '0' AFTER `remise_percent`;
-- Change index name to be compliant with SQL standard, index name must be unique in database schema
ALTER TABLE llx_c_actioncomm DROP INDEX code, ADD UNIQUE uk_c_actioncomm (code);
ALTER TABLE llx_c_civilite DROP INDEX code, ADD UNIQUE uk_c_civilite (code);
@ -811,13 +833,11 @@ ALTER TABLE llx_c_typent DROP INDEX code, ADD UNIQUE uk_c_typent (code);
ALTER TABLE llx_c_effectif DROP INDEX code, ADD UNIQUE uk_c_effectif (code);
ALTER TABLE llx_c_paiement DROP INDEX code, ADD UNIQUE uk_c_paiement (code);
delete from llx_c_actioncomm where id = 40;
INSERT INTO llx_c_actioncomm (id, code, type, libelle, module, position) values ( 40, 'AC_OTH_AUTO','systemauto', 'Other (automatically inserted events)' ,NULL, 20);
UPDATE llx_c_actioncomm SET libelle = 'Other (manually inserted events)' WHERE code = 'AC_OTH';
UPDATE llx_c_actioncomm SET active = 0 WHERE code in ('AC_PROP', 'AC_COM', 'AC_FAC', 'AC_SHIP', 'AC_SUP_ORD', 'AC_SUP_INV');
-- Update dictionnary of table llx_c_paper_format
DELETE FROM llx_c_paper_format;
@ -850,8 +870,6 @@ INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active)
-- increase field size
ALTER TABLE llx_bank_account MODIFY COLUMN code_banque varchar(8);
create table llx_user_extrafields
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
@ -860,5 +878,4 @@ create table llx_user_extrafields
import_key varchar(14) -- import key
)ENGINE=innodb;
ALTER TABLE llx_user_extrafields ADD INDEX idx_user_extrafields (fk_object);
ALTER TABLE llx_user_extrafields ADD INDEX idx_user_extrafields (fk_object);

View File

@ -31,6 +31,8 @@ create table llx_product_fournisseur_price
fk_availability integer,
price double(24,8) DEFAULT 0,
quantity double,
remise_percent double NOT NULL DEFAULT 0,
remise double NOT NULL DEFAULT 0,
unitprice double(24,8) DEFAULT 0,
charges double(24,8) DEFAULT 0,
unitcharges double(24,8) DEFAULT 0,

View File

@ -36,6 +36,7 @@ create table llx_product_price
localtax1_tx double(6,3) DEFAULT 0,
localtax2_tx double(6,3) DEFAULT 0,
fk_user_author integer,
tosell tinyint DEFAULT 1
tosell tinyint DEFAULT 1,
price_by_qty integer NOT NULL DEFAULT 0
)ENGINE=innodb;

View File

@ -0,0 +1,26 @@
-- ============================================================================
-- Copyright (C) 2002-2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
-- Copyright (C) 2005-2012 Regis Houssin <regis@dolibarr.fr>
-- Copyright (C) 2010 Juanjo Menent <jmenent@2byte.es>
-- Copyright (C) 2012 Maxime Kohlhaas <maxime.kohlhaas@atm-consulting.fr>
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 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_price_by_qty ADD UNIQUE INDEX uk_product_price_by_qty_level (fk_product_price, quantity);
ALTER TABLE llx_product_price_by_qty ADD INDEX idx_product_price_by_qty_fk_product_price (fk_product_price);
ALTER TABLE llx_product_price_by_qty ADD CONSTRAINT fk_product_price_by_qty_fk_product_price FOREIGN KEY (fk_product_price) REFERENCES llx_product_price (rowid);

View File

@ -0,0 +1,32 @@
-- ============================================================================
-- Copyright (C) 2002-2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
-- Copyright (C) 2005-2012 Regis Houssin <regis@dolibarr.fr>
-- Copyright (C) 2010 Juanjo Menent <jmenent@2byte.es>
-- Copyright (C) 2012 Maxime Kohlhaas <maxime.kohlhaas@atm-consulting.fr>
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 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_price_by_qty
(
rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY,
fk_product_price integer NOT NULL,
date_price timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
price double(24,8) DEFAULT 0,
quantity double DEFAULT NULL,
remise_percent double NOT NULL DEFAULT 0,
remise double NOT NULL DEFAULT 0,
unitprice double(24,8) DEFAULT 0
)ENGINE=innodb;

View File

@ -276,7 +276,7 @@ YouCanSubmitFile=Select module:
CurrentVersion=Dolibarr current version
CallUpdatePage=Go to the page that updates the database structure and datas: %s.
LastStableVersion=Last stable version
GenericMaskCodes=You may enter any numbering mask. In this mask, the following tags could be used:<br><b>{000000}</b> corresponds to a number which will be incremented on each %s. Enter as many zeros as the desired length of the counter. The counter will be completed by zeros from the left in order to have as many zeros as the mask. <br><b>{000000+000}</b> same as previous but an offset corresponding to the number to the right of the + sign is applied starting on first %s. <br><b>{000000@x}</b> same as previous but the counter is reset to zero when month x is reached (x between 1 and 12, or 0 to use the early months of fiscal year defined in your configuration). If this option is used and x is 2 or higher, then sequence {yy}{mm} or {yyyy}{mm} is also required. <br><b>{dd}</b> day (01 to 31).<br><b>{mm}</b> month (01 to 12).<br><b>{yy}</b>, <b>{yyyy}</b> or <b>{y}</b> year over 2, 4 or 1 numbers. <br>
GenericMaskCodes=You may enter any numbering mask. In this mask, the following tags could be used:<br><b>{000000}</b> corresponds to a number which will be incremented on each %s. Enter as many zeros as the desired length of the counter. The counter will be completed by zeros from the left in order to have as many zeros as the mask. <br><b>{000000+000}</b> same as previous but an offset corresponding to the number to the right of the + sign is applied starting on first %s. <br><b>{000000@x}</b> same as previous but the counter is reset to zero when month x is reached (x between 1 and 12, or 0 to use the early months of fiscal year defined in your configuration, or 99 to reset to zero every month). If this option is used and x is 2 or higher, then sequence {yy}{mm} or {yyyy}{mm} is also required. <br><b>{dd}</b> day (01 to 31).<br><b>{mm}</b> month (01 to 12).<br><b>{yy}</b>, <b>{yyyy}</b> or <b>{y}</b> year over 2, 4 or 1 numbers. <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 dictionnary-company types).<br>
GenericMaskCodes3=All other characters in the mask will remain intact.<br>Spaces are not allowed.<br>
GenericMaskCodes4a=<u>Example on the 99th %s of the third party TheCompany done 2007-01-31:</u><br>

View File

@ -180,4 +180,6 @@ AddThisServiceCard=Create service card
HelpAddThisServiceCard=This option allows you to create or clone a service if it does not exist.
CurrentProductPrice=Current price
AlwaysUseNewPrice=Always use current price of product/service
AlwaysUseFixedPrice=Use the fixed price
AlwaysUseFixedPrice=Use the fixed price
PriceByQuantity=Price by quantity
PriceByQuantityRange=Quantity range

View File

@ -276,7 +276,7 @@ YouCanSubmitFile=Sélectionner le module:
CurrentVersion= Version en cours de Dolibarr
CallUpdatePage= Appeler la page de l'outil de mise à jour de la structure et données de la base: %s.
LastStableVersion= Dernière version stable disponible
GenericMaskCodes= Vous pouvez saisir tout masque de numérotation. Dans ce masque, les balises suivantes peuvent être utilisées:<br><b>{000000}</b> correspond à un numéro qui sera incrémenté à chaque %s. Mettre autant de zéro que la longueur désirée du compteur. Le compteur sera complété par des 0 à gauche afin d'avoir autant de zéro que dans le masque.<br><b>{000000+000}</b> idem précédemment mais un offset correspondant au nombre à droite du + est appliqué dès la première %s.<br><b>{000000@x}</b> idem précédemment mais le compteur est remis à zéro le xème mois de l'année (x entre 1 et 12, ou 0 pour utiliser le mois de début d'exercice fiscal défini dans votre configuration). Si cette option est utilisée et x vaut 2 ou plus, alors la séquence {yy}{mm} ou {yyyy}{mm} est obligatoire. <br><b>{dd}</b> jour (01 à 31).<br><b>{mm}</b> mois (01 à 12).<br><b>{yy}</b>, <b>{yyyy}</b> ou <b>{y}</b> année sur 2, 4 ou 1 chiffres.<br>
GenericMaskCodes= Vous pouvez saisir tout masque de numérotation. Dans ce masque, les balises suivantes peuvent être utilisées:<br><b>{000000}</b> correspond à un numéro qui sera incrémenté à chaque %s. Mettre autant de zéro que la longueur désirée du compteur. Le compteur sera complété par des 0 à gauche afin d'avoir autant de zéro que dans le masque.<br><b>{000000+000}</b> idem précédemment mais un offset correspondant au nombre à droite du + est appliqué dès la première %s.<br><b>{000000@x}</b> idem précédemment mais le compteur est remis à zéro le xème mois de l'année (x entre 1 et 12, ou 0 pour utiliser le mois de début d'exercice fiscal défini dans votre configuration, ou 99 pour remise à zéro chaque mois). Si cette option est utilisée et x vaut 2 ou plus, alors la séquence {yy}{mm} ou {yyyy}{mm} est obligatoire. <br><b>{dd}</b> jour (01 à 31).<br><b>{mm}</b> mois (01 à 12).<br><b>{yy}</b>, <b>{yyyy}</b> ou <b>{y}</b> année sur 2, 4 ou 1 chiffres.<br>
GenericMaskCodes2= <b>{cccc}</b> le code client sur n lettres<br><b>{cccc000}</b> le code client sur n lettres est suivi d'un compteur propre au client sans offset, complété par des zéros pour en avoir autant que dans le masque, et remis à zéro en même temps que le compteur global.<br><b>{tttt}</b> Le code type entreprise sur n caractères (voir dictionnaires-types de sociétés).<br>
GenericMaskCodes3= Tout autre caractère dans le masque sera laissé inchangé.<br>Les espaces ne sont pas permis.<br>
GenericMaskCodes4a= <u>Exemple sur la 99eme %s du tiers LaCompanie faite le 31/03/2007:</u><br>

View File

@ -180,4 +180,6 @@ AddThisServiceCard=Créer fiche service
HelpAddThisServiceCard=Cette option permet de créer ou de cloner une fiche service si elle n'existe pas.
CurrentProductPrice=Prix actuel
AlwaysUseNewPrice=Toujours utiliser le prix du jour
AlwaysUseFixedPrice=Utiliser le prix fixé
AlwaysUseFixedPrice=Utiliser le prix fixé
PriceByQuantity=Prix par quantité
PriceByQuantityRange=Grille de quantités

View File

@ -8,6 +8,7 @@
* Copyright (C) 2011 Philippe Grand <philippe.grand@atoo-net.com>
* Copyright (C) 2008 Matteli
* Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.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
@ -1419,6 +1420,13 @@ function left_menu($menu_array_before, $helppagename='', $moresearchform='', $me
$searchform.=printSearchForm(DOL_URL_ROOT.'/product/liste.php', DOL_URL_ROOT.'/product/liste.php', img_object('','product').' '.$langs->trans("Products")."/".$langs->trans("Services"), 'products', 'sall');
}
if (((! empty($conf->product->enabled) && $user->rights->produit->lire) || (! empty($conf->service->enabled) && $user->rights->service->lire))
&& ! empty($conf->global->MAIN_SEARCHFORM_PRODUITSERVICE))
{
$langs->load("products");
$searchform.=printSearchForm(DOL_URL_ROOT.'/fourn/product/liste.php', DOL_URL_ROOT.'/fourn/product/liste.php', img_object('','product').' '.$langs->trans("SupplierRef"), 'products', 'srefsupplier');
}
if (! empty($conf->adherent->enabled) && ! empty($conf->global->MAIN_SEARCHFORM_ADHERENT) && $user->rights->adherent->lire)
{
$langs->load("members");

View File

@ -38,9 +38,10 @@ $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);
$pricelevel=GETPOST('price_level','int');
$price_level=GETPOST('price_level','int');
$action=GETPOST('action', 'alpha');
$id=GETPOST('id', 'int');
$price_by_qty_rowid=GETPOST('pbq', 'int');
/*
* View
@ -65,11 +66,37 @@ if (! empty($action) && $action == 'fetch' && ! empty($id))
$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
{
$sql = "SELECT price, unitprice, quantity, remise_percent";
$sql.= " FROM ".MAIN_DB_PREFIX."product_price_by_qty ";
$sql.= " WHERE rowid=".$price_by_qty_rowid."";
$result = $db->query($sql);
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;
}
}
}
// Multiprice
if (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) // 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 ";
@ -78,10 +105,10 @@ if (! empty($action) && $action == 'fetch' && ! empty($id))
$sql.= " ORDER BY date_price";
$sql.= " DESC LIMIT 1";
$result = $this->db->query($sql);
$result = $db->query($sql);
if ($result)
{
$objp = $this->db->fetch_object($result);
$objp = $db->fetch_object($result);
if ($objp)
{
$found=true;
@ -101,7 +128,7 @@ if (! empty($action) && $action == 'fetch' && ! empty($id))
$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);
$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);

View File

@ -61,6 +61,11 @@ class Product extends CommonObject
var $multiprices_ttc=array();
var $multiprices_base_type=array();
var $multiprices_tva_tx=array();
//! Price by quantity arrays
var $price_by_qty;
var $prices_by_qty=array();
var $prices_by_qty_id=array();
var $prices_by_qty_list=array();
//! Default VAT rate of product
var $tva_tx;
//! French VAT NPR (0 or 1)
@ -214,6 +219,10 @@ class Product extends CommonObject
if (empty($this->price)) $this->price = 0;
if (empty($this->price_min)) $this->price_min = 0;
// Price by quantity
if (empty($this->price_by_qty)) $this->price_by_qty = 0;
if (empty($this->status)) $this->status = 0;
if (empty($this->status_buy)) $this->status_buy = 0;
if (empty($this->finished)) $this->finished = 0;
@ -806,9 +815,9 @@ class Product extends CommonObject
// Add new price
$sql = "INSERT INTO ".MAIN_DB_PREFIX."product_price(price_level,date_price,fk_product,fk_user_author,price,price_ttc,price_base_type,tosell,tva_tx,recuperableonly,";
$sql.= " localtax1_tx, localtax2_tx, price_min,price_min_ttc) ";
$sql.= " localtax1_tx, localtax2_tx, price_min,price_min_ttc,price_by_qty) ";
$sql.= " VALUES(".($level?$level:1).", '".$this->db->idate($now)."',".$this->id.",".$user->id.",".$this->price.",".$this->price_ttc.",'".$this->price_base_type."',".$this->status.",".$this->tva_tx.",".$this->tva_npr.",";
$sql.= " ".$this->localtax1_tx.",".$this->localtax2_tx.",".$this->price_min.",".$this->price_min_ttc;
$sql.= " ".$this->localtax1_tx.",".$this->localtax2_tx.",".$this->price_min.",".$this->price_min_ttc.",".$this->price_by_qty;
$sql.= ")";
dol_syslog(get_class($this)."_log_price sql=".$sql);
@ -945,9 +954,10 @@ class Product extends CommonObject
* @param double $newminprice New price min
* @param int $level 0=standard, >0 = level if multilevel prices
* @param int $newnpr 0=Standard vat rate, 1=Special vat rate for French NPR VAT
* @param int $newpsq 1 if it has price by quantity
* @return int <0 if KO, >0 if OK
*/
function updatePrice($id, $newprice, $newpricebase, $user, $newvat='',$newminprice='', $level=0, $newnpr=0)
function updatePrice($id, $newprice, $newpricebase, $user, $newvat='',$newminprice='', $level=0, $newnpr=0, $newpsq=0)
{
global $conf,$langs;
@ -1036,6 +1046,9 @@ class Product extends CommonObject
$this->localtax1_tx = $localtax1;
$this->localtax2_tx = $localtax2;
// Price by quantity
$this->price_by_qty = $newpsq;
$this->_log_price($user,$level);
// Appel des triggers
@ -1170,7 +1183,7 @@ class Product extends CommonObject
for ($i=1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++)
{
$sql = "SELECT price, price_ttc, price_min, price_min_ttc,";
$sql.= " price_base_type, tva_tx, tosell";
$sql.= " price_base_type, tva_tx, tosell, price_by_qty, rowid";
$sql.= " FROM ".MAIN_DB_PREFIX."product_price";
$sql.= " WHERE price_level=".$i;
$sql.= " AND fk_product = '".$this->id."'";
@ -1187,6 +1200,40 @@ class Product extends CommonObject
$this->multiprices_min_ttc[$i]=$result["price_min_ttc"];
$this->multiprices_base_type[$i]=$result["price_base_type"];
$this->multiprices_tva_tx[$i]=$result["tva_tx"];
// Price by quantity
$this->prices_by_qty[$i]=$result["price_by_qty"];
$this->prices_by_qty_id[$i]=$result["rowid"];
// Récuperation de la liste des prix selon qty si flag positionné
if ($this->prices_by_qty[$i] == 1)
{
$sql = "SELECT rowid,price, unitprice, quantity, remise_percent, remise";
$sql.= " FROM ".MAIN_DB_PREFIX."product_price_by_qty";
$sql.= " WHERE fk_product_price = '".$this->prices_by_qty_id[$i]."'";
$sql.= " ORDER BY quantity ASC";
$resultat=array();
$resql = $this->db->query($sql) ;
if ($resql)
{
$ii=0;
while ($result= $this->db->fetch_array($resql)) {
$resultat[$ii]=array();
$resultat[$ii]["rowid"]=$result["rowid"];
$resultat[$ii]["price"]= $result["price"];
$resultat[$ii]["unitprice"]= $result["unitprice"];
$resultat[$ii]["quantity"]= $result["quantity"];
$resultat[$ii]["remise_percent"]= $result["remise_percent"];
$resultat[$ii]["remise"]= $result["remise"];
$ii++;
}
$this->prices_by_qty_list[$i]=$resultat;
}
else
{
dol_print_error($this->db);
return -1;
}
}
}
else
{
@ -1194,6 +1241,58 @@ class Product extends CommonObject
return -1;
}
}
} else if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY))
{
$sql = "SELECT price, price_ttc, price_min, price_min_ttc,";
$sql.= " price_base_type, tva_tx, tosell, price_by_qty, rowid";
$sql.= " FROM ".MAIN_DB_PREFIX."product_price";
$sql.= " WHERE fk_product = '".$this->id."'";
$sql.= " ORDER BY date_price DESC";
$sql.= " LIMIT 1";
$resql = $this->db->query($sql);
if ($resql)
{
$result = $this->db->fetch_array($resql);
// Price by quantity
$this->prices_by_qty[0]=$result["price_by_qty"];
$this->prices_by_qty_id[0]=$result["rowid"];
// Récuperation de la liste des prix selon qty si flag positionné
if ($this->prices_by_qty[0] == 1)
{
$sql = "SELECT rowid,price, unitprice, quantity, remise_percent, remise";
$sql.= " FROM ".MAIN_DB_PREFIX."product_price_by_qty";
$sql.= " WHERE fk_product_price = '".$this->prices_by_qty_id[0]."'";
$sql.= " ORDER BY quantity ASC";
$resultat=array();
$resql = $this->db->query($sql) ;
if ($resql)
{
$ii=0;
while ($result= $this->db->fetch_array($resql)) {
$resultat[$ii]=array();
$resultat[$ii]["rowid"]=$result["rowid"];
$resultat[$ii]["price"]= $result["price"];
$resultat[$ii]["unitprice"]= $result["unitprice"];
$resultat[$ii]["quantity"]= $result["quantity"];
$resultat[$ii]["remise_percent"]= $result["remise_percent"];
$resultat[$ii]["remise"]= $result["remise"];
$ii++;
}
$this->prices_by_qty_list[0]=$resultat;
}
else
{
dol_print_error($this->db);
return -1;
}
}
}
else
{
dol_print_error($this->db);
return -1;
}
}
$res=$this->load_stock();

View File

@ -51,7 +51,7 @@ $object = new Product($db);
if ($action == 'update_price' && ! $_POST["cancel"] && ($user->rights->produit->creer || $user->rights->service->creer))
{
$result = $object->fetch($id);
// MultiPrix
if (! empty($conf->global->PRODUIT_MULTIPRICES))
{
@ -70,6 +70,8 @@ if ($action == 'update_price' && ! $_POST["cancel"] && ($user->rights->produit->
$newpricebase=$_POST["multiprices_base_type_".$i];
$newnpr=(preg_match('/\*/',$_POST["tva_tx_".$i]) ? 1 : 0);
$newvat=str_replace('*','',$_POST["tva_tx_".$i]);
$newpsq=GETPOST('psqflag');
$newpsq = empty($newpsq) ? 0 : $newpsq;
break; // We found submited price
}
}
@ -82,9 +84,11 @@ if ($action == 'update_price' && ! $_POST["cancel"] && ($user->rights->produit->
$newpricebase=$_POST["price_base_type"];
$newnpr=(preg_match('/\*/',$_POST["tva_tx"]) ? 1 : 0);
$newvat=str_replace('*','',$_POST["tva_tx"]);
$newpsq=GETPOST('psqflag');
$newpsq = empty($newpsq) ? 0 : $newpsq;
}
if ($object->updatePrice($object->id, $newprice, $newpricebase, $user, $newvat, $newprice_min, $level, $newnpr) > 0)
if ($object->updatePrice($object->id, $newprice, $newpricebase, $user, $newvat, $newprice_min, $level, $newnpr, $newpsq) > 0)
{
$action = '';
$mesg = '<div class="ok">'.$langs->trans("RecordSaved").'</div>';
@ -101,6 +105,92 @@ else if ($action == 'delete' && $user->rights->produit->supprimer)
if ($result < 0) $mesg='<div class="error">'.$object->error.'</div>';
}
/*****************************************************
* Price by quantity
*****************************************************/
$error=0;
if ($action == 'activate_price_by_qty') { // Activating product price by quantity add a new price, specified as by quantity
$result = $object->fetch($id);
$level=GETPOST('level');
$object->updatePrice($object->id, 0, $object->price_base_type, $user, $object->tva_tx, 0, $level, $object->tva_npr, 1);
}
if ($action == 'edit_price_by_qty') { // Edition d'un prix par quantité
$rowid = GETPOST('rowid');
}
if ($action == 'update_price_by_qty') { // Ajout / Mise à jour d'un prix par quantité
$result = $object->fetch($id);
// Récupération des variables
$rowid = GETPOST('rowid');
$priceid=GETPOST('priceid');
$newprice=price2num(GETPOST("price"),'MU');
//$newminprice=price2num(GETPOST("price_min"),'MU'); // TODO : Add min price management
$quantity=GETPOST('quantity');
$remise_percent=price2num(GETPOST('remise_percent'));
$remise=0; // TODO : allow dicsount by amount when available on documents
if (empty($quantity))
{
$error++;
$mesg='<div class="error">'.$langs->trans("ErrorFieldRequired",$langs->transnoentities("Qty")).'</div>';
}
if (empty($newprice))
{
$error++;
$mesg='<div class="error">'.$langs->trans("ErrorFieldRequired",$langs->transnoentities("Price")).'</div>';
}
if(!$error) {
// Calcul du prix HT et du prix unitaire
if ($object->price_base_type == 'TTC')
{
$price = price2num($newprice) / (1 + ($object->tva_tx / 100));
}
$price = price2num($newprice,'MU');
$unitPrice = price2num($price/$quantity,'MU');
// Ajout / mise à jour
if($rowid > 0) {
$sql = "UPDATE ".MAIN_DB_PREFIX."product_price_by_qty SET";
$sql.= " price='".$price."',";
$sql.= " unitprice=".$unitPrice.",";
$sql.= " quantity=".$quantity.",";
$sql.= " remise_percent=".$remise_percent.",";
$sql.= " remise=".$remise;
$sql.= " WHERE rowid = ".GETPOST('rowid');
$result = $db->query($sql);
} else {
$sql = "INSERT INTO ".MAIN_DB_PREFIX."product_price_by_qty (fk_product_price,price,unitprice,quantity,remise_percent,remise) values (";
$sql.= $priceid.','.$price.','.$unitPrice.','.$quantity.','.$remise_percent.','.$remise.')';
$result = $db->query($sql);
}
}
}
if ($action == 'delete_price_by_qty') {
$rowid = GETPOST('rowid');
$sql = "DELETE FROM ".MAIN_DB_PREFIX."product_price_by_qty";
$sql.= " WHERE rowid = ".GETPOST('rowid');
$result = $db->query($sql);
}
if ($action == 'delete_all_price_by_qty') {
$priceid=GETPOST('priceid');
$sql = "DELETE FROM ".MAIN_DB_PREFIX."product_price_by_qty";
$sql.= " WHERE fk_product_price = ".$priceid;
$result = $db->query($sql);
}
/*
* View
@ -230,6 +320,77 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES))
print price($object->multiprices_min["$i"]).' '.$langs->trans($object->multiprices_base_type["$i"]);
}
print '</td></tr>';
// Price by quantity
if($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) {
print '<tr><td>'.$langs->trans("PriceByQuantity").' '.$i;
print '</td><td>';
if($object->prices_by_qty[$i] == 1) {
print '<table width="50%" class="noborder">';
print '<tr class="liste_titre">';
print '<td>'.$langs->trans("PriceByQuantityRange").' '.$i.'</td>';
print '<td align="right">'.$langs->trans("HT").'</td>';
print '<td align="right">'.$langs->trans("UnitPrice").'</td>';
print '<td align="right">'.$langs->trans("Discount").'</td>';
print '<td>&nbsp;</td>';
print '</tr>';
foreach ($object->prices_by_qty_list[$i] as $ii=> $prices) {
if($action == 'edit_price_by_qty' && $rowid == $prices['rowid'] && ($user->rights->produit->creer || $user->rights->service->creer)) {
print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
print '<input type="hidden" name="action" value="update_price_by_qty">';
print '<input type="hidden" name="priceid" value="'.$object->prices_by_qty_id[$i].'">';
print '<input type="hidden" value="'.$prices['rowid'].'" name="rowid">';
print '<tr class="'.($ii % 2 == 0 ? 'pair':'impair').'">';
print '<td><input size="5" type="text" value="'.$prices['quantity'].'" name="quantity"></td>';
print '<td align="right" colspan="2"><input size="10" type="text" value="'.$prices['price'].'" name="price">&nbsp;'.$object->price_base_type.'</td>';
//print '<td align="right">&nbsp;</td>';
print '<td align="right"><input size="5" type="text" value="'.$prices['remise_percent'].'" name="remise_percent">&nbsp;%</td>';
print '<td align="center"><input type="submit" value="'.$langs->trans("Modify").'" class="button"></td>';
print '</tr>';
print '</form>';
} else {
print '<tr class="'.($ii % 2 == 0 ? 'pair':'impair').'">';
print '<td>'.$prices['quantity'].'</td>';
print '<td align="right">'.price($prices['price']).'</td>';
print '<td align="right">'.price($prices['unitprice']).'</td>';
print '<td align="right">'.price($prices['remise_percent']).' %</td>';
print '<td align="center">';
if(($user->rights->produit->creer || $user->rights->service->creer)) {
print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=edit_price_by_qty&amp;rowid='.$prices["rowid"].'">';
print img_edit().'</a>';
print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=delete_price_by_qty&amp;rowid='.$prices["rowid"].'">';
print img_delete().'</a>';
} else {
print '&nbsp;';
}
print '</td>';
print '</tr>';
}
}
if($action != 'edit_price_by_qty' && ($user->rights->produit->creer || $user->rights->service->creer)) {
print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
print '<input type="hidden" name="action" value="update_price_by_qty">';
print '<input type="hidden" name="priceid" value="'.$object->prices_by_qty_id[$i].'">';
print '<input type="hidden" value="0" name="rowid">';
print '<tr class="'.($ii % 2 == 0 ? 'pair':'impair').'">';
print '<td><input size="5" type="text" value="1" name="quantity"></td>';
print '<td align="right" colspan="2"><input size="10" type="text" value="0" name="price">&nbsp;'.$object->price_base_type.'</td>';
//print '<td align="right">&nbsp;</td>';
print '<td align="right"><input size="5" type="text" value="0" name="remise_percent">&nbsp;%</td>';
print '<td align="center"><input type="submit" value="'.$langs->trans("Add").'" class="button"></td>';
print '</tr>';
print '</form>';
}
print '</table>';
} else {
print $langs->trans("No");
print '&nbsp;<a href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=activate_price_by_qty&level='.$i.'">('.$langs->trans("Activate").')</a>';
}
print '</td></tr>';
}
}
}
}
@ -261,6 +422,78 @@ else
print price($object->price_min).' '.$langs->trans($object->price_base_type);
}
print '</td></tr>';
// Price by quantity
if($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) {
print '<tr><td>'.$langs->trans("PriceByQuantity");
if($object->prices_by_qty[0] == 0) {
print '&nbsp;<a href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=activate_price_by_qty&level=1">'.$langs->trans("Activate");
}
print '</td><td>';
if($object->prices_by_qty[0] == 1) {
print '<table width="50%" class="noborder">';
print '<tr class="liste_titre">';
print '<td>'.$langs->trans("PriceByQuantityRange").'</td>';
print '<td align="right">'.$langs->trans("HT").'</td>';
print '<td align="right">'.$langs->trans("UnitPrice").'</td>';
print '<td align="right">'.$langs->trans("Discount").'</td>';
print '<td>&nbsp;</td>';
print '</tr>';
foreach ($object->prices_by_qty_list[0] as $ii=> $prices) {
if($action == 'edit_price_by_qty' && $rowid == $prices['rowid'] && ($user->rights->produit->creer || $user->rights->service->creer)) {
print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
print '<input type="hidden" name="action" value="update_price_by_qty">';
print '<input type="hidden" name="priceid" value="'.$object->prices_by_qty_id[0].'">';
print '<input type="hidden" value="'.$prices['rowid'].'" name="rowid">';
print '<tr class="'.($ii % 2 == 0 ? 'pair':'impair').'">';
print '<td><input size="5" type="text" value="'.$prices['quantity'].'" name="quantity"></td>';
print '<td align="right" colspan="2"><input size="10" type="text" value="'.$prices['price'].'" name="price">&nbsp;'.$object->price_base_type.'</td>';
//print '<td align="right">&nbsp;</td>';
print '<td align="right"><input size="5" type="text" value="'.$prices['remise_percent'].'" name="remise_percent">&nbsp;%</td>';
print '<td align="center"><input type="submit" value="'.$langs->trans("Modify").'" class="button"></td>';
print '</tr>';
print '</form>';
} else {
print '<tr class="'.($ii % 2 == 0 ? 'pair':'impair').'">';
print '<td>'.$prices['quantity'].'</td>';
print '<td align="right">'.price($prices['price']).'</td>';
print '<td align="right">'.price($prices['unitprice']).'</td>';
print '<td align="right">'.price($prices['remise_percent']).' %</td>';
print '<td align="center">';
if(($user->rights->produit->creer || $user->rights->service->creer)) {
print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=edit_price_by_qty&amp;rowid='.$prices["rowid"].'">';
print img_edit().'</a>';
print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=delete_price_by_qty&amp;rowid='.$prices["rowid"].'">';
print img_delete().'</a>';
} else {
print '&nbsp;';
}
print '</td>';
print '</tr>';
}
}
if($action != 'edit_price_by_qty') {
print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
print '<input type="hidden" name="action" value="update_price_by_qty">';
print '<input type="hidden" name="priceid" value="'.$object->prices_by_qty_id[0].'">';
print '<input type="hidden" value="0" name="rowid">';
print '<tr class="'.($ii % 2 == 0 ? 'pair':'impair').'">';
print '<td><input size="5" type="text" value="1" name="quantity"></td>';
print '<td align="right" colspan="2"><input size="10" type="text" value="0" name="price">&nbsp;'.$object->price_base_type.'</td>';
//print '<td align="right">&nbsp;</td>';
print '<td align="right"><input size="5" type="text" value="0" name="remise_percent">&nbsp;%</td>';
print '<td align="center"><input type="submit" value="'.$langs->trans("Add").'" class="button"></td>';
print '</tr>';
print '</form>';
}
print '</table>';
} else {
print $langs->trans("No");
}
print '</td></tr>';
}
}
// Status (to sell)
@ -426,7 +659,7 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights->
// Liste des evolutions du prix
$sql = "SELECT p.rowid, p.price, p.price_ttc, p.price_base_type, p.tva_tx, p.recuperableonly,";
$sql.= " p.price_level, p.price_min, p.price_min_ttc,";
$sql.= " p.price_level, p.price_min, p.price_min_ttc,p.price_by_qty,";
$sql.= " p.date_price as dp, u.rowid as user_id, u.login";
$sql.= " FROM ".MAIN_DB_PREFIX."product_price as p,";
$sql.= " ".MAIN_DB_PREFIX."user as u";
@ -464,7 +697,11 @@ if ($result)
if (! empty($conf->global->PRODUIT_MULTIPRICES))
{
print '<td>'.$langs->trans("MultiPriceLevelsName").'</td>';
print '<td align="center">'.$langs->trans("MultiPriceLevelsName").'</td>';
}
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY))
{
print '<td align="center">'.$langs->trans("Type").'</td>';
}
print '<td align="center">'.$langs->trans("PriceBase").'</td>';
@ -492,6 +729,12 @@ if ($result)
{
print '<td align="center">'.$objp->price_level."</td>";
}
// Price by quantity
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY))
{
$type = ($objp->price_by_qty == 1) ? 'PriceByQuantity' : 'Standard';
print '<td align="center">'.$langs->trans($type)."</td>";
}
print '<td align="center">'.$langs->trans($objp->price_base_type)."</td>";
print '<td align="right">'.vatrate($objp->tva_tx,true,$objp->recuperableonly)."</td>";

View File

@ -1044,19 +1044,19 @@ class Societe extends CommonObject
// Remove extrafields
if (! $error)
{
$sql = "DELETE FROM ".MAIN_DB_PREFIX."societe_extrafields WHERE fk_object = ".$id;
dol_syslog(get_class($this)."::delete sql=".$sql);
if (! $this->db->query($sql))
{
$error++;
$this->error = $this->db->lasterror();
dol_syslog(get_class($this)."::delete error -3 ".$this->error, LOG_ERR);
}
$sql = "DELETE FROM ".MAIN_DB_PREFIX."societe_extrafields WHERE fk_object = ".$id;
dol_syslog(get_class($this)."::delete sql=".$sql);
if (! $this->db->query($sql))
{
$error++;
$this->error = $this->db->lasterror();
dol_syslog(get_class($this)."::delete error -3 ".$this->error, LOG_ERR);
}
}
// Remove third party
if (! $error)
{
if (! $error)
{
$sql = "DELETE FROM ".MAIN_DB_PREFIX."societe";
$sql.= " WHERE rowid = " . $id;
dol_syslog(get_class($this)."::delete sql=".$sql, LOG_DEBUG);

View File

@ -700,7 +700,7 @@ class User extends CommonObject
$sql = "DELETE FROM ".MAIN_DB_PREFIX."usergroup_user WHERE fk_user = ".$this->id;
if (! $error && ! $this->db->query($sql))
{
$error++;
$error++;
$this->error = $this->db->lasterror();
dol_syslog(get_class($this)."::delete error -2 ".$this->error, LOG_ERR);
}

View File

@ -0,0 +1,529 @@
<?php
/* Copyright (C) 2006-2011 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2012 JF FERRY <jfefe@aternatik.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 2 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/webservices/server_contact.php
* \brief File that is entry point to call Dolibarr WebServices
*/
// This is to make Dolibarr working with Plesk
set_include_path($_SERVER['DOCUMENT_ROOT'].'/htdocs');
require_once("../master.inc.php");
require_once(NUSOAP_PATH.'/nusoap.php'); // Include SOAP
require_once(DOL_DOCUMENT_ROOT."/core/lib/ws.lib.php");
require_once(DOL_DOCUMENT_ROOT."/contact/class/contact.class.php");
dol_syslog("Call Contact webservices interfaces");
// Enable and test if module web services is enabled
if (empty($conf->global->MAIN_MODULE_WEBSERVICES))
{
$langs->load("admin");
dol_syslog("Call Dolibarr webservices interfaces with module webservices disabled");
print $langs->trans("WarningModuleNotActive",'WebServices').'.<br><br>';
print $langs->trans("ToActivateModule");
exit;
}
// Create the soap Object
$server = new nusoap_server();
$server->soap_defencoding='UTF-8';
$server->decode_utf8=false;
$ns='http://www.dolibarr.org/ns/';
$server->configureWSDL('WebServicesDolibarrContact',$ns);
$server->wsdl->schemaTargetNamespace=$ns;
// Define WSDL Authentication object
$server->wsdl->addComplexType(
'authentication',
'complexType',
'struct',
'all',
'',
array(
'dolibarrkey' => array('name'=>'dolibarrkey','type'=>'xsd:string'),
'sourceapplication' => array('name'=>'sourceapplication','type'=>'xsd:string'),
'login' => array('name'=>'login','type'=>'xsd:string'),
'password' => array('name'=>'password','type'=>'xsd:string'),
'entity' => array('name'=>'entity','type'=>'xsd:string'),
)
);
// Define WSDL Return object
$server->wsdl->addComplexType(
'result',
'complexType',
'struct',
'all',
'',
array(
'result_code' => array('name'=>'result_code','type'=>'xsd:string'),
'result_label' => array('name'=>'result_label','type'=>'xsd:string'),
)
);
// Define other specific objects
$server->wsdl->addComplexType(
'contact',
'complexType',
'struct',
'all',
'',
array(
'id' => array('name'=>'id','type'=>'xsd:string'),
'lastname' => array('name'=>'lastname','type'=>'xsd:string'),
'firstname' => array('name'=>'firstname','type'=>'xsd:string'),
'address' => array('name'=>'address','type'=>'xsd:string'),
'zip' => array('name'=>'zip','type'=>'xsd:string'),
'town' => array('name'=>'town','type'=>'xsd:string'),
'state_id' => array('name'=>'state_id','type'=>'xsd:string'),
'state_code' => array('name'=>'state_code','type'=>'xsd:string'),
'state' => array('name'=>'state','type'=>'xsd:string'),
'country_id' => array('name'=>'country_id','type'=>'xsd:string'),
'country_code' => array('name'=>'country_code','type'=>'xsd:string'),
'country' => array('name'=>'country','type'=>'xsd:string'),
'socid' => array('name'=>'socid','type'=>'xsd:string'),
'status' => array('name'=>'status','type'=>'xsd:string'),
'code' => array('name'=>'code','type'=>'xsd:string'),
'email' => array('name'=>'email','type'=>'xsd:string'),
'birthday' => array('name'=>'birthday','type'=>'xsd:string'),
'default_lang' => array('name'=>'default_lang','type'=>'xsd:string'),
'note' => array('name'=>'note','type'=>'xsd:string'),
'no_email' => array('name'=>'no_email','type'=>'xsd:string'),
'ref_facturation' => array('name'=>'ref_facturation','type'=>'xsd:string'),
'ref_contrat' => array('name'=>'ref_contrat','type'=>'xsd:string'),
'ref_commande' => array('name'=>'ref_commande','type'=>'xsd:string'),
'ref_propal' => array('name'=>'ref_propal','type'=>'xsd:string'),
'user_id' => array('name'=>'user_id','type'=>'xsd:string'),
'user_login' => array('name'=>'user_login','type'=>'xsd:string'),
'civility_id' => array('name'=>'civility_id','type'=>'xsd:string')
//...
)
);
$server->wsdl->addComplexType(
'ContactsArray2',
'complexType',
'array',
'sequence',
'',
array(
'contact' => array(
'name' => 'contact',
'type' => 'tns:contact',
'minOccurs' => '0',
'maxOccurs' => 'unbounded'
)
)
);
// 5 styles: RPC/encoded, RPC/literal, Document/encoded (not WS-I compliant), Document/literal, Document/literal wrapped
// Style merely dictates how to translate a WSDL binding to a SOAP message. Nothing more. You can use either style with any programming model.
// http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/
$styledoc='rpc'; // rpc/document (document is an extend into SOAP 1.0 to support unstructured messages)
$styleuse='encoded'; // encoded/literal/literal wrapped
// Better choice is document/literal wrapped but literal wrapped not supported by nusoap.
// Register WSDL
$server->register(
'getContact',
// Entry values
array('authentication'=>'tns:authentication','id'=>'xsd:string','ref'=>'xsd:string','ref_ext'=>'xsd:string'),
// Exit values
array('result'=>'tns:result','contact'=>'tns:contact'),
$ns,
$ns.'#getContact',
$styledoc,
$styleuse,
'WS to get contact'
);
// Register WSDL
$server->register(
'createContact',
// Entry values
array('authentication'=>'tns:authentication','contact'=>'tns:contact'),
// Exit values
array('result'=>'tns:result','id'=>'xsd:string'),
$ns,
$ns.'#createContact',
$styledoc,
$styleuse,
'WS to create a contact'
);
$server->register(
'getContactsForThirdParty',
// Entry values
array('authentication'=>'tns:authentication','idthirdparty'=>'xsd:string'),
// Exit values
array('result'=>'tns:result','contacts'=>'tns:ContactsArray2'),
$ns,
$ns.'#getContactsForThirdParty',
$styledoc,
$styleuse,
'WS to get all contacts of a third party'
);
/**
* Get Contact
*
* @param array $authentication Array of authentication information
* @param int $id Id of object
* @param string $ref Ref of object
* @param ref_ext $ref_ext Ref external of object
* @return mixed
*/
function getContact($authentication,$id,$ref='',$ref_ext='')
{
global $db,$conf,$langs;
dol_syslog("Function: getContact login=".$authentication['login']." id=".$id." ref=".$ref." ref_ext=".$ref_ext);
if ($authentication['entity']) $conf->entity=$authentication['entity'];
// Init and check authentication
$objectresp=array();
$errorcode='';$errorlabel='';
$error=0;
$fuser=check_authentication($authentication,$error,$errorcode,$errorlabel);
// Check parameters
if (! $error && (($id && $ref) || ($id && $ref_ext) || ($ref && $ref_ext)))
{
$error++;
$errorcode='BAD_PARAMETERS'; $errorlabel="Parameter id, ref and ref_ext can't be both provided. You must choose one or other but not both.";
}
if (! $error)
{
$fuser->getrights();
if ($fuser->rights->contact->read)
{
$contact=new Contact($db);
$result=$contact->fetch($id,$ref,$ref_ext);
if ($result > 0)
{
// Create
$objectresp = array(
'result'=>array('result_code'=>'OK', 'result_label'=>''),
'contact'=>array(
'id' => $contact->id,
'lastname' => $contact->lastname,
'firstname' => $contact->firstname,
'address' => $contact->address,
'zip' => $contact->zip,
'town' => $contact->town,
'state_id' => $contact->state_id,
'state_code' => $contact->state_code,
'state' => $contact->state,
'country_id' => $contact->country_id,
'country_code' => $contact->country_code,
'country' => $contact->country,
'socid' => $contact->socid,
'status' => $contact->status,
'code' => $contact->code,
'email' => $contact->email,
'birthday' => $contact->birthday,
'default_lang' => $contact->default_lang,
'note' => $contact->note,
'no_email' => $contact->no_email,
'ref_facturation' => $contact->ref_facturation,
'ref_contrat' => $contact->ref_contrat,
'ref_commande' => $contact->ref_commande,
'ref_propal' => $contact->ref_propal,
'user_id' => $contact->user_id,
'user_login' => $contact->user_login,
'civility_id' => $contact->civility_id
)
);
}
else
{
$error++;
$errorcode='NOT_FOUND'; $errorlabel='Object not found for id='.$id.' nor ref='.$ref.' nor ref_ext='.$ref_ext;
}
}
else
{
$error++;
$errorcode='PERMISSION_DENIED'; $errorlabel='User does not have permission for this request';
}
}
if ($error)
{
$objectresp = array('result'=>array('result_code' => $errorcode, 'result_label' => $errorlabel));
}
return $objectresp;
}
/**
* Create Contact
*
* @param array $authentication Array of authentication information
* @param Contact $contact $contact
* @return array Array result
*/
function createContact($authentication,$contact)
{
global $db,$conf,$langs;
$now=dol_now();
dol_syslog("Function: createContact login=".$authentication['login']);
if ($authentication['entity']) $conf->entity=$authentication['entity'];
// Init and check authentication
$objectresp=array();
$errorcode='';$errorlabel='';
$error=0;
$fuser=check_authentication($authentication,$error,$errorcode,$errorlabel);
// Check parameters
if (empty($contact['lastname']))
{
$error++; $errorcode='KO'; $errorlabel="Name is mandatory.";
}
if (! $error)
{
$newobject=new Contact($db);
$newobject->id=$contact['id'];
$newobject->civility_id=$contact['civility_id'];
$newobject->lastname=$contact['lastname'];
$newobject->firstname=$contact['firstname'];
$newobject->address=$contact['address'];
$newobject->zip=$contact['zip'];
$newobject->town=$contact['town'];
$newobject->state_id=$contact['state_id'];
$newobject->state_code=$contact['state_code'];
$newobject->state=$contact['state'];
$newobject->country_id=$contact['country_id'];
$newobject->country_code=$contact['country_code'];
$newobject->country=$contact['country'];
$newobject->socid=$contact['socid'];
$newobject->status=$contact['status'];
$newobject->code=$contact['code'];
$newobject->email=$contact['email'];
$newobject->birthday=$contact['birthday'];
$newobject->default_lang=$contact['default_lang'];
$newobject->note=$contact['note'];
$newobject->no_email=$contact['no_email'];
$newobject->ref_facturation=$contact['ref_facturation'];
$newobject->ref_contrat=$contact['ref_contrat'];
$newobject->ref_commande=$contact['ref_commande'];
$newobject->ref_propal=$contact['ref_propal'];
$newobject->user_id=$contact['user_id'];
$newobject->user_login=$contact['user_login'];
//...
$db->begin();
$result=$newobject->create($fuser);
if ($result <= 0)
{
$error++;
}
if (! $error)
{
$db->commit();
$objectresp=array('result'=>array('result_code'=>'OK', 'result_label'=>''),'id'=>$newobject->id,'ref'=>$newobject->ref);
}
else
{
$db->rollback();
$error++;
$errorcode='KO';
$errorlabel=$newobject->error;
}
}
if ($error)
{
$objectresp = array('result'=>array('result_code' => $errorcode, 'result_label' => $errorlabel));
}
return $objectresp;
}
/**
* Get list of contacts for third party
*
* @param array $authentication Array of authentication information
* @param int $idthirdparty Id thirdparty
* @return array Array result
*/
function getContactsForThirdParty($authentication,$idthirdparty)
{
global $db,$conf,$langs;
dol_syslog("Function: getContactsForThirdParty login=".$authentication['login']." idthirdparty=".$idthirdparty);
if ($authentication['entity']) $conf->entity=$authentication['entity'];
// Init and check authentication
$objectresp=array();
$errorcode='';$errorlabel='';
$error=0;
$fuser=check_authentication($authentication,$error,$errorcode,$errorlabel);
// Check parameters
if (! $error && empty($idthirdparty))
{
$error++;
$errorcode='BAD_PARAMETERS'; $errorlabel='Parameter id is not provided';
}
if (! $error)
{
$linesinvoice=array();
$sql = "SELECT c.rowid, c.fk_soc, c.civilite as civility_id, c.name as lastname, c.firstname,";
$sql.= " c.address, c.cp as zip, c.ville as town,";
$sql.= " c.fk_pays as country_id,";
$sql.= " c.fk_departement,";
$sql.= " c.birthday,";
$sql.= " c.poste, c.phone, c.phone_perso, c.phone_mobile, c.fax, c.email, c.jabberid,";
//$sql.= " c.priv, c.note, c.default_lang, c.no_email, c.canvas,";
$sql.= " p.libelle as country, p.code as country_code,";
$sql.= " d.nom as state, d.code_departement as state_code,";
$sql.= " u.rowid as user_id, u.login as user_login,";
$sql.= " s.nom as socname, s.address as socaddress, s.cp as soccp, s.ville as soccity, s.default_lang as socdefault_lang";
$sql.= " FROM ".MAIN_DB_PREFIX."socpeople as c";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_pays as p ON c.fk_pays = p.rowid";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as d ON c.fk_departement = d.rowid";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON c.rowid = u.fk_socpeople";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON c.fk_soc = s.rowid";
$sql.= " WHERE c.fk_soc=$idthirdparty";
$resql=$db->query($sql);
if ($resql)
{
$num=$db->num_rows($resql);
$i=0;
while ($i < $num)
{
// En attendant remplissage par boucle
$obj=$db->fetch_object($resql);
$contact=new Contact($db);
$contact->fetch($obj->rowid);
// Now define invoice
$linescontact[]=array(
'id' => $contact->id,
'ref' => $contact->ref,
'civility_id' => $contact->civility_id?$contact->civility_id:'',
'lastname' => $contact->lastname?$contact->lastname:'',
'firstname' => $contact->firstname?$contact->firstname:'',
'address' => $contact->address?$contact->address:'',
'zip' => $contact->zip?$contact->zip:'',
'town' => $contact->town?$contact->town:'',
'state_id' => $contact->state_id?$contact->state_id:'',
'state_code' => $contact->state_code?$contact->state_code:'',
'state' => $contact->state?$contact->state:'',
'fk_pays' => $contact->fk_pays?$contact->fk_pays:'',
'country_id' => $contact->country_id?$contact->country_id:'',
'pays_code' => $contact->pays_code?$contact->pays_code:'',
'country_code' => $contact->country_code?$contact->country_code:'',
'pays' => $contact->pays?$contact->pays:'',
'country' => $contact->country?$contact->country:'',
'socid' => $contact->socid?$contact->socid:'',
'socname' => $contact->socname?$contact->socname:'',
'poste' => $contact->poste?$contact->poste:'',
'phone_pro' => $contact->phone_pro?$contact->phone_pro:'',
'fax' => $contact->fax?$contact->fax:'',
'phone_perso' => $contact->phone_perso?$contact->phone_perso:'',
'phone_mobile' => $contact->phone_mobile?$contact->phone_mobile:'',
'email' => $contact->email?$contact->email:'',
'jabberid' => $contact->jabberid?$contact->jabberid:'',
'priv' => $contact->priv?$contact->priv:'',
'mail' => $contact->mail?$contact->mail:'',
'birthday' => $contact->birthday?$contact->birthday:'',
'default_lang' => $contact->default_lang?$contact->default_lang:'',
'note' => $contact->note?$contact->note:'',
'no_email' => $contact->no_email?$contact->no_email:'',
'ref_facturation' => $contact->ref_facturation?$contact->ref_facturation:'',
'ref_contrat' => $contact->ref_contrat?$contact->ref_contrat:'',
'ref_commande' => $contact->ref_commande?$contact->ref_commande:'',
'ref_propal' => $contact->ref_propal?$contact->ref_propal:'',
'user_id' => $contact->user_id?$contact->user_id:'',
'user_login' => $contact->no_email?$contact->user_login:''
);
$i++;
}
$objectresp=array(
'result'=>array('result_code'=>'OK', 'result_label'=>''),
'contacts'=>$linescontact
);
}
else
{
$error++;
$errorcode=$db->lasterrno(); $errorlabel=$db->lasterror();
}
}
if ($error)
{
$objectresp = array('result'=>array('result_code' => $errorcode, 'result_label' => $errorlabel));
}
return $objectresp;
}
// Return the results.
$server->service($HTTP_RAW_POST_DATA);
?>

View File

@ -107,7 +107,7 @@ $server->wsdl->addComplexType(
'pass_indatabase_crypted' => array('name'=>'pass_indatabase_crypted','type'=>'xsd:string'),
'datec' => array('name'=>'datec','type'=>'xsd:dateTime'),
'datem' => array('name'=>'datem','type'=>'xsd:dateTime'),
'societe_id' => array('name'=>'societe_id','type'=>'xsd:string'),
'fk_socpeople' => array('name'=>'fk_socpeople','type'=>'xsd:string'),
'fk_member' => array('name'=>'fk_member','type'=>'xsd:string'),
'datelastlogin' => array('name'=>'datelastlogin','type'=>'xsd:dateTime'),
'datepreviouslogin' => array('name'=>'datepreviouslogin','type'=>'xsd:dateTime'),
@ -251,6 +251,7 @@ function getUser($authentication,$id,$ref='',$ref_ext='')
'datec' => dol_print_date($user->datec,'dayhourrfc'),
'datem' => dol_print_date($user->datem,'dayhourrfc'),
'societe_id' => $user->societe_id,
'fk_socpeople' => $user->fk_socpeople,
'fk_member' => $user->fk_member,
'webcal_login' => $user->webcal_login,
'phenix_login' => $user->phenix_login,