Mise a jour des champ total_ht, total_tva et total_ttc au niveau ligne

This commit is contained in:
Laurent Destailleur 2006-06-16 00:33:04 +00:00
parent 6d09c5a35e
commit a53e6f7cfc
17 changed files with 1341 additions and 1289 deletions

View File

@ -212,51 +212,21 @@ if ($_GET["action"] == 'create')
}
/*
* Destinataire de la propale
* Contact de la propale
*/
print "<tr><td>".$langs->trans("Contact")."</td><td colspan=\"2\">\n";
$sql = "SELECT p.idp, p.name, p.firstname, p.poste, p.phone, p.fax, p.email FROM ".MAIN_DB_PREFIX."socpeople as p";
$sql .= " WHERE p.fk_soc = ".$soc->id;
if ( $db->query($sql) )
{
$i = 0 ;
$numdest = $db->num_rows();
if ($numdest==0)
{
print '<font class="error">Cette societe n\'a pas de contact, veuillez en créer un avant de faire votre proposition commerciale</font><br>';
print '<a href="'.DOL_URL_ROOT.'/contact/fiche.php?socid='.$soc->id.'&amp;action=create&amp;backtoreferer=1">'.$langs->trans("AddContact").'</a>';
}
else
{
print "<select name=\"contactidp\">\n";
while ($i < $numdest)
{
$contact = $db->fetch_object();
print '<option value="'.$contact->idp.'"';
if ($contact->idp == $setcontact)
{
print ' selected="true"';
}
print '>'.$contact->firstname.' '.$contact->name;
if ($contact->email) { print ' &lt;'.$contact->email.'&gt;'; }
print '</option>';
$i++;
}
print '</select>';
}
$db->free();
}
else
{
dolibarr_print_error($db);
}
print "<tr><td>".$langs->trans("DefaultContact")."</td><td colspan=\"2\">\n";
$html->select_contacts($soc->id,$setcontact,'contactidp',1);
print '</td></tr>';
// Model
print '<tr>';
print '<td>'.$langs->trans("DefaultModel").'</td>';
print '<td colspan="2">';
$model=new ModelePDFPropales();
$liste=$model->liste_modeles($db);
$html->select_array("model",$liste,$conf->global->PROPALE_ADDON_PDF);
print "</td></tr>";
// Projet
if ($conf->projet->enabled)
{
@ -266,20 +236,12 @@ if ($_GET["action"] == 'create')
$numprojet=$html->select_projects($soc->id,$projetid,'projetidp');
if ($numprojet==0)
{
print ' &nbsp; <a href=../projet/fiche.php?socidp='.$soc->id.'&action=create>'.$langs->trans("AddProject").'</a>';
print ' &nbsp; <a href="../projet/fiche.php?socidp='.$soc->id.'&action=create">'.$langs->trans("AddProject").'</a>';
}
print '</td>';
print '</tr>';
}
print '<tr>';
print '<td>'.$langs->trans("Model").'</td>';
print '<td colspan="2">';
$model=new ModelePDFPropales();
$liste=$model->liste_modeles($db);
$html->select_array("model",$liste,$conf->global->PROPALE_ADDON_PDF);
print "</td></tr>";
print "</table>";
print '<br>';
@ -324,7 +286,7 @@ if ($_GET["action"] == 'create')
{
$lib=$langs->trans("ProductsAndServices");
print '<table class="border">';
print '<table class="border" width="100%">';
print '<tr>';
print '<td>'.$lib.'</td>';
print '<td>'.$langs->trans("Qty").'</td>';
@ -355,16 +317,11 @@ if ($_GET["action"] == 'create')
print '</table>';
print '<br>';
/*
* Si il n'y a pas de contact pour la societe on ne permet pas la creation de propale
*/
if ($numdest > 0)
{
$langs->load("bills");
print '<center>';
print '<input type="submit" class="button" value="'.$langs->trans("CreateDraft").'">';
print '</center>';
}
$langs->load("bills");
print '<center>';
print '<input type="submit" class="button" value="'.$langs->trans("CreateDraft").'">';
print '</center>';
print "</form>";
}

File diff suppressed because it is too large Load Diff

View File

@ -2158,20 +2158,21 @@ class Commande
class CommandeLigne
{
// From llx_propaldet
var $qty;
var $tva_tx;
var $subprice;
var $remise_percent;
var $price;
var $product_id;
var $desc; // Description ligne
var $coef;
// From llx_commandedet
var $qty;
var $tva_tx;
var $subprice;
var $remise_percent;
var $price;
var $product_id; // Id produit prédéfini
var $desc; // Description ligne
var $coef;
// From llx_product
var $libelle; // Label produit
var $product_desc; // Description produit
var $ref;
// From llx_product
var $libelle; // Label produit
var $product_desc; // Description produit
var $ref; // Reference produit
function CommandeLigne()
{

View File

@ -242,12 +242,11 @@ if ($_POST['action'] == 'add')
{
for ($i = 0 ; $i < sizeof($prop->lignes) ; $i++)
{
$liblignefac=($prop->lignes[$i]->desc?$prop->lignes[$i]->desc:$prop->lignes[$i]->libelle);
$desc=($prop->lignes[$i]->desc?$prop->lignes[$i]->desc:$prop->lignes[$i]->libelle);
$result = $facture->addline(
$facid,
addslashes($liblignefac),
$prop->lignes[$i]->desc,
$desc,
$prop->lignes[$i]->subprice,
$prop->lignes[$i]->qty,
$prop->lignes[$i]->tva_tx,
@ -281,10 +280,11 @@ if ($_POST['action'] == 'add')
$lines = $comm->fetch_lignes();
for ($i = 0 ; $i < sizeof($lines) ; $i++)
{
$desc=($lignes[$i]->description ? $lignes[$i]->description : $lignes[$i]->libelle);
$result = $facture->addline(
$facid,
addslashes($lines[$i]->description),
$lines[$i]->desc,
$desc,
$lines[$i]->subprice,
$lines[$i]->qty,
$lines[$i]->tva_tx,
@ -319,7 +319,7 @@ if ($_POST['action'] == 'add')
for ($i = 0 ; $i < sizeof($lines) ; $i++)
{
$liblignefac=($contrat->lignes[$i]->desc?$contrat->lignes[$i]->desc:$contrat->lignes[$i]->libelle);
$desc=($contrat->lignes[$i]->desc?$contrat->lignes[$i]->desc:$contrat->lignes[$i]->libelle);
// Plage de dates
$date_start=$contrat->lignes[$i]->date_debut_prevue;
@ -329,8 +329,7 @@ if ($_POST['action'] == 'add')
$result = $facture->addline(
$facid,
addslashes($liblignefac),
'',
$desc,
$lines[$i]->subprice,
$lines[$i]->qty,
$lines[$i]->tva_tx,
@ -367,6 +366,9 @@ if (($_POST['action'] == 'addligne' || $_POST['action'] == 'addligne_predef') &&
{
$fac = new Facture($db);
$fac->fetch($_POST['facid']);
$soc = new Societe($db);
$soc->fetch($fac->socidp);
$datestart='';
$dateend='';
// Si ajout champ produit libre
@ -393,13 +395,42 @@ if (($_POST['action'] == 'addligne' || $_POST['action'] == 'addligne_predef') &&
$dateend=$_POST['date_end_predefyear'].'-'.$_POST['date_end_predefmonth'].'-'.$_POST['date_end_predefday'];
}
}
// Ecrase $pu par celui du produit
// Ecrase $desc par celui du produit
// Ecrase $txtva par celui du produit
if ($_POST['idprod'])
{
$prod = new Product($db, $_POST['idprod']);
$prod->fetch($_POST['idprod']);
// multiprix
if ($conf->global->PRODUIT_MULTIPRICES == 1)
{
$pu = $prod->multiprices[$soc->price_level];
}
else
{
$pu=$prod->price;
}
$desc=$_POST['desc'];
if (! $desc) $desc = $prod->description;
if ($conf->global->PRODUIT_CHANGE_PROD_DESC) $prod->description;
$tva_tx = get_default_tva($mysoc,$soc,$prod->tva_tx);
}
else
{
$pu=$_POST['pu'];
$tva_tx=$_POST['tva_tx'];
$desc=$_POST['desc'];
}
// Insere ligne
$result = $fac->addline(
$_POST['facid'],
$_POST['desc'],
$_POST['product_desc'],
$_POST['pu'],
$desc,
$pu,
$_POST['qty'],
$_POST['tva_tx'],
$tva_tx,
$_POST['idprod'],
$_POST['remise_percent'],
$datestart,
@ -1933,7 +1964,7 @@ else
$html->select_produits('','idprod','',$conf->produit->limit_size,$soc->price_level);
else
$html->select_produits('','idprod','',$conf->produit->limit_size);
print '<br>';
if (! $conf->use_ajax) print '<br>';
print '<textarea name="desc" cols="70" rows="'.ROWS_2.'"></textarea></td>';
print '<td>&nbsp;</td>';
print '<td align="right"><input type="text" name="qty" value="1" size="2"></td>';

View File

@ -118,430 +118,425 @@ $html = new Form($db);
*/
if ($_GET["propalid"] > 0)
{
if ($mesg) print "$mesg<br>";
if ($mesg) print "$mesg<br>";
$propal = new Propal($db);
$propal->fetch($_GET['propalid']);
$societe = new Societe($db);
$societe->fetch($propal->soc_id);
$propal = new Propal($db);
$propal->fetch($_GET["propalid"]);
$head = propal_prepare_head($propal);
dolibarr_fiche_head($head, 'compta', $langs->trans('Proposal'));
/*
* Fiche propal
*
*/
$sql = 'SELECT s.nom, s.idp, p.price, p.fk_projet, p.remise, p.tva, p.total, p.ref,'.$db->pdate('p.datep').' as dp, c.id as statut, c.label as lst, p.note,';
$sql.= ' x.firstname, x.name, x.fax, x.phone, x.email, p.fk_user_author, p.fk_user_valid, p.fk_user_cloture, p.datec, p.date_valid, p.date_cloture, p.fk_cond_reglement, p.fk_mode_reglement';
$sql.= ' FROM '.MAIN_DB_PREFIX.'societe as s, '.MAIN_DB_PREFIX.'propal as p, '.MAIN_DB_PREFIX.'c_propalst as c, '.MAIN_DB_PREFIX.'socpeople as x';
$sql.= ' WHERE p.fk_soc = s.idp AND p.fk_statut = c.id AND x.idp = p.fk_soc_contact AND p.rowid = '.$propal->id;
if ($socidp) $sql .= ' AND s.idp = '.$socidp;
print '<table class="border" width="100%">';
// Ref
print '<tr><td>'.$langs->trans('Ref').'</td><td colspan="5">'.$propal->ref_url.'</td></tr>';
// Ref client
print '<tr><td>';
print '<table class="nobordernopadding" width="100%"><tr><td nowrap>';
print $langs->trans('RefCustomer').'</td><td align="left">';
print '</td>';
if ($_GET['action'] != 'refclient' && $propal->brouillon) print '<td align="right"><a href="'.$_SERVER['PHP_SELF'].'?action=refclient&amp;propalid='.$propal->id.'">'.img_edit($langs->trans('Edit')).'</a></td>';
print '</tr></table>';
print '</td><td colspan="3">';
print $propal->ref_client;
print '</td>';
print '</tr>';
$rowspan=8;
$resql = $db->query($sql);
if ($resql)
// Société
print '<tr><td>'.$langs->trans('Company').'</td><td colspan="5">'.$societe->getNomUrl(1).'</td></tr>';
// Ligne info remises tiers
print '<tr><td>'.$langs->trans('Discounts').'</td><td colspan="5">';
if ($societe->remise_client) print $langs->trans("CompanyHasRelativeDiscount",$societe->remise_client);
else print $langs->trans("CompanyHasNoRelativeDiscount");
$absolute_discount=$societe->getCurrentDiscount();
print '. ';
if ($absolute_discount) print $langs->trans("CompanyHasAbsoluteDiscount",$absolute_discount,$langs->trans("Currency".$conf->monnaie));
else print $langs->trans("CompanyHasNoAbsoluteDiscount");
print '.';
print '</td></tr>';
// Dates
print '<tr><td>'.$langs->trans('Date').'</td><td colspan="3">';
print dolibarr_print_date($propal->date,'%a %d %B %Y');
print '</td>';
if ($conf->projet->enabled) $rowspan++;
// Note
print '<td valign="top" colspan="2" width="50%" rowspan="'.$rowspan.'">'.$langs->trans('NotePublic').' :<br>'. nl2br($propal->note_public).'</td>';
print '</tr>';
// Date fin propal
print '<tr>';
print '<td>'.$langs->trans('DateEndPropal').'</td><td colspan="3">';
if ($propal->fin_validite)
{
if ($db->num_rows($resql))
print dolibarr_print_date($propal->fin_validite,'%a %d %B %Y');
if ($propal->statut == 1 && $propal->fin_validite < (time() - $conf->propal->cloture->warning_delay)) print img_warning($langs->trans("Late"));
}
else
{
print $langs->trans("Unknown");
}
print '</td>';
print '</tr>';
// Conditions et modes de réglement
print '<tr><td>';
print '<table class="nobordernopadding" width="100%"><tr><td>';
print $langs->trans('PaymentConditionsShort');
print '</td>';
if ($_GET['action'] != 'editconditions' && $propal->brouillon) print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editconditions&amp;propalid='.$propal->id.'">'.img_edit($langs->trans('SetConditions'),1).'</a></td>';
print '</tr></table>';
print '</td><td colspan="3">';
if ($_GET['action'] == 'editconditions')
{
$html->form_conditions_reglement($_SERVER['PHP_SELF'].'?propalid='.$propal->id,$propal->cond_reglement_id,'cond_reglement_id');
}
else
{
$html->form_conditions_reglement($_SERVER['PHP_SELF'].'?propalid='.$propal->id,$propal->cond_reglement_id,'none');
}
print '</td>';
// Mode de paiement
print '<tr>';
print '<td width="25%">';
print '<table class="nobordernopadding" width="100%"><tr><td>';
print $langs->trans('PaymentMode');
print '</td>';
if ($_GET['action'] != 'editmode' && $propal->brouillon) print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editmode&amp;facid='.$propal->id.'">'.img_edit($langs->trans('SetMode'),1).'</a></td>';
print '</tr></table>';
print '</td><td colspan="3">';
if ($_GET['action'] == 'editmode')
{
$html->form_modes_reglement($_SERVER['PHP_SELF'].'?propalid='.$propal->id,$propal->mode_reglement_id,'mode_reglement_id');
}
else
{
$html->form_modes_reglement($_SERVER['PHP_SELF'].'?propalid='.$propal->id,$propal->mode_reglement_id,'none');
}
print '</td></tr>';
// Destinataire
/* Remplacé par contacts de propal
$langs->load('mails');
print '<tr>';
print '<td>'.$langs->trans('MailTo').'</td>';
if ($propal->statut == 0 && $user->rights->propale->creer)
{
print '<td colspan="3">';
$html->form_contacts($_SERVER['PHP_SELF'].'?propalid='.$propal->id,$societe,$propal->contactid,'none');
print '</td>';
}
else
{
if (!empty($propal->contactid))
{
$obj = $db->fetch_object($resql);
$societe = new Societe($db);
$societe->fetch($obj->idp);
print '<table class="border" width="100%">';
// Ref
print '<tr><td>'.$langs->trans('Ref').'</td><td colspan="5">'.$propal->ref_url.'</td></tr>';
$rowspan=9;
// Société
print '<tr><td>'.$langs->trans('Company').'</td><td colspan="5">'.$societe->getNomUrl(1).'</td></tr>';
// Ligne info remises tiers
print '<tr><td>'.$langs->trans('Discounts').'</td><td colspan="5">';
if ($societe->remise_client) print $langs->trans("CompanyHasRelativeDiscount",$societe->remise_client);
else print $langs->trans("CompanyHasNoRelativeDiscount");
$absolute_discount=$societe->getCurrentDiscount();
print '. ';
if ($absolute_discount) print $langs->trans("CompanyHasAbsoluteDiscount",$absolute_discount,$langs->trans("Currency".$conf->monnaie));
else print $langs->trans("CompanyHasNoAbsoluteDiscount");
print '.';
print '</td></tr>';
// Dates
print '<tr><td>'.$langs->trans('Date').'</td><td colspan="3">';
print dolibarr_print_date($propal->date,'%a %d %B %Y');
print '<td colspan="3">';
$html->form_contacts($_SERVER['PHP_SELF'].'?propalid='.$propal->id,$societe,$propal->contactid,'none');
print '</td>';
if ($conf->projet->enabled) $rowspan++;
// Note
print '<td valign="top" colspan="2" width="50%" rowspan="'.$rowspan.'">'.$langs->trans('NotePublic').' :<br>'. nl2br($propal->note_public).'</td>';
print '</tr>';
// Date fin propal
print '<tr>';
print '<td>'.$langs->trans('DateEndPropal').'</td><td colspan="3">';
if ($propal->fin_validite)
{
print dolibarr_print_date($propal->fin_validite,'%a %d %B %Y');
if ($propal->statut == 1 && $propal->fin_validite < (time() - $conf->propal->cloture->warning_delay)) print img_warning($langs->trans("Late"));
}
else
{
print $langs->trans("Unknown");
}
}
else {
print '<td colspan="3">&nbsp;</td>';
}
}
*/
// Projet
if ($conf->projet->enabled)
{
$langs->load("projects");
print '<tr><td>'.$langs->trans('Project').'</td>';
$numprojet = $societe->has_projects();
if (! $numprojet)
{
print '<td colspan="2">';
print $langs->trans("NoProject").'</td><td>';
print '<a href=../projet/fiche.php?socidp='.$societe->id.'&action=create>'.$langs->trans('AddProject').'</a>';
print '</td>';
print '</tr>';
// Conditions et modes de réglement
print '<tr><td>';
print '<table class="nobordernopadding" width="100%"><tr><td>';
print $langs->trans('PaymentConditionsShort');
print '</td>';
if ($_GET['action'] != 'editconditions' && $propal->brouillon) print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editconditions&amp;propalid='.$propal->id.'">'.img_edit($langs->trans('SetConditions'),1).'</a></td>';
print '</tr></table>';
print '</td><td colspan="3">';
if ($_GET['action'] == 'editconditions')
{
$html->form_conditions_reglement($_SERVER['PHP_SELF'].'?propalid='.$propal->id,$propal->cond_reglement_id,'cond_reglement_id');
}
else
{
$html->form_conditions_reglement($_SERVER['PHP_SELF'].'?propalid='.$propal->id,$propal->cond_reglement_id,'none');
}
print '</td>';
// Mode de paiement
print '<tr>';
print '<td width="25%">';
print '<table class="nobordernopadding" width="100%"><tr><td>';
print $langs->trans('PaymentMode');
print '</td>';
if ($_GET['action'] != 'editmode' && $propal->brouillon) print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editmode&amp;facid='.$propal->id.'">'.img_edit($langs->trans('SetMode'),1).'</a></td>';
print '</tr></table>';
print '</td><td colspan="3">';
if ($_GET['action'] == 'editmode')
{
$html->form_modes_reglement($_SERVER['PHP_SELF'].'?propalid='.$propal->id,$propal->mode_reglement_id,'mode_reglement_id');
}
else
{
$html->form_modes_reglement($_SERVER['PHP_SELF'].'?propalid='.$propal->id,$propal->mode_reglement_id,'none');
}
print '</td></tr>';
// Destinataire
$langs->load('mails');
print '<tr>';
print '<td>'.$langs->trans('MailTo').'</td>';
}
else
{
if ($propal->statut == 0 && $user->rights->propale->creer)
{
print '<td colspan="3">';
$html->form_contacts($_SERVER['PHP_SELF'].'?propalid='.$propal->id,$societe,$propal->contactid,'none');
$html->select_projects($societe->id, $propal->projetidp, 'projetidp');
print '</td>';
}
else
{
if (!empty($propal->contactid))
if (!empty($propal->projetidp))
{
print '<td colspan="3">';
$html->form_contacts($_SERVER['PHP_SELF'].'?propalid='.$propal->id,$societe,$propal->contactid,'none');
$proj = new Project($db);
$proj->fetch($propal->projetidp);
print '<a href="../projet/fiche.php?id='.$propal->projetidp.'" title="'.$langs->trans('ShowProject').'">';
print $proj->title;
print '</a>';
print '</td>';
}
else {
print '<td colspan="3">&nbsp;</td>';
}
}
// Projet
if ($conf->projet->enabled)
}
print '</tr>';
}
// Amount
print '<tr><td height="10">'.$langs->trans('AmountHT').'</td>';
print '<td align="right" colspan="2"><b>'.price($propal->price).'</b></td>';
print '<td>'.$langs->trans("Currency".$conf->monnaie).'</td></tr>';
print '<tr><td height="10">'.$langs->trans('AmountVAT').'</td><td align="right" colspan="2">'.price($propal->total_tva).'</td>';
print '<td>'.$langs->trans("Currency".$conf->monnaie).'</td></tr>';
print '<tr><td height="10">'.$langs->trans('AmountTTC').'</td><td align="right" colspan="2">'.price($propal->total_ttc).'</td>';
print '<td>'.$langs->trans("Currency".$conf->monnaie).'</td></tr>';
// Statut
print '<tr><td height="10">'.$langs->trans('Status').'</td><td align="left" colspan="3">'.$propal->getLibStatut(4).'</td></tr>';
print '</table><br>';
/*
* Lignes de propale
*
*/
$sql = 'SELECT pt.rowid, pt.description, pt.price, pt.fk_product, pt.qty, pt.tva_tx, pt.remise_percent, pt.subprice, p.label as product, p.ref, p.fk_product_type, p.rowid as prodid';
$sql .= ' FROM '.MAIN_DB_PREFIX.'propaldet as pt LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON pt.fk_product=p.rowid';
$sql .= ' WHERE pt.fk_propal = '.$propal->id;
$sql .= ' ORDER BY pt.rowid ASC';
$resql = $db->query($sql);
if ($resql)
{
$num_lignes = $db->num_rows($resql);
$i = 0;
$total = 0;
print '<table class="noborder" width="100%">';
if ($num_lignes)
{
print '<tr class="liste_titre">';
print '<td>'.$langs->trans('Description').'</td>';
print '<td align="right" width="50">'.$langs->trans('VAT').'</td>';
print '<td align="right" width="80">'.$langs->trans('PriceUHT').'</td>';
print '<td align="right" width="50">'.$langs->trans('Qty').'</td>';
print '<td align="right" width="50">'.$langs->trans('Discount').'</td>';
print '<td align="right" width="50">'.$langs->trans('AmountHT').'</td>';
print '<td width="16">&nbsp;</td>';
print '<td width="16">&nbsp;</td>';
print '<td width="16">&nbsp;</td>';
print "</tr>\n";
}
$var=true;
while ($i < $num_lignes)
{
$objp = $db->fetch_object($resql);
$var=!$var;
if ($_GET['action'] != 'editline' || $_GET['rowid'] != $objp->rowid)
{
$langs->load("projects");
print '<tr><td>'.$langs->trans('Project').'</td>';
$numprojet = $societe->has_projects();
if (! $numprojet)
print '<tr '.$bc[$var].'>';
if ($objp->fk_product > 0)
{
print '<td colspan="2">';
print $langs->trans("NoProject").'</td><td>';
print '<a href=../projet/fiche.php?socidp='.$societe->id.'&action=create>'.$langs->trans('AddProject').'</a>';
print '<td><a href="'.DOL_URL_ROOT.'/product/fiche.php?id='.$objp->fk_product.'">';
if ($objp->fk_product_type)
print img_object($langs->trans('ShowService'),'service');
else
print img_object($langs->trans('ShowProduct'),'product');
print ' '.$objp->ref.'</a> - '.stripslashes(nl2br($objp->product));
if ($objp->date_start && $objp->date_end)
{
print ' (Du '.dolibarr_print_date($objp->date_start).' au '.dolibarr_print_date($objp->date_end).')';
}
if ($objp->date_start && ! $objp->date_end)
{
print ' (A partir du '.dolibarr_print_date($objp->date_start).')';
}
if (! $objp->date_start && $objp->date_end)
{
print " (Jusqu'au ".dolibarr_print_date($objp->date_end).')';
}
print ($objp->description && $objp->description!=$objp->product)?'<br>'.stripslashes(nl2br($objp->description)):'';
print '</td>';
}
else
{
if ($propal->statut == 0 && $user->rights->propale->creer)
print '<td>'.stripslashes(nl2br($objp->description));
if ($objp->date_start && $objp->date_end)
{
print '<td colspan="3">';
$html->select_projects($societe->id, $propal->projetidp, 'projetidp');
print '</td>';
print ' (Du '.dolibarr_print_date($objp->date_start).' au '.dolibarr_print_date($objp->date_end).')';
}
else
if ($objp->date_start && ! $objp->date_end)
{
if (!empty($propal->projetidp))
{
print '<td colspan="3">';
$proj = new Project($db);
$proj->fetch($propal->projetidp);
print '<a href="../projet/fiche.php?id='.$propal->projetidp.'" title="'.$langs->trans('ShowProject').'">';
print $proj->title;
print '</a>';
print '</td>';
}
else {
print '<td colspan="3">&nbsp;</td>';
}
print ' (A partir du '.dolibarr_print_date($objp->date_start).')';
}
if (! $objp->date_start && $objp->date_end)
{
print " (Jusqu'au ".dolibarr_print_date($objp->date_end).')';
}
print "</td>\n";
}
print '<td align="right">'.$objp->tva_tx.'%</td>';
print '<td align="right">'.price($objp->subprice)."</td>\n";
print '<td align="right">'.$objp->qty.'</td>';
if ($objp->remise_percent > 0)
{
print '<td align="right">'.$objp->remise_percent."%</td>\n";
}
else
{
print '<td>&nbsp;</td>';
}
print '<td align="right">'.price($objp->subprice*$objp->qty*(100-$objp->remise_percent)/100)."</td>\n";
print '<td colspan="3">&nbsp;</td>';
print '</tr>';
}
// Amount
print '<tr><td height="10">'.$langs->trans('AmountHT').'</td>';
print '<td align="right" colspan="2"><b>'.price($propal->price).'</b></td>';
print '<td>'.$langs->trans("Currency".$conf->monnaie).'</td></tr>';
print '<tr><td height="10">'.$langs->trans('AmountVAT').'</td><td align="right" colspan="2">'.price($propal->total_tva).'</td>';
print '<td>'.$langs->trans("Currency".$conf->monnaie).'</td></tr>';
print '<tr><td height="10">'.$langs->trans('AmountTTC').'</td><td align="right" colspan="2">'.price($propal->total_ttc).'</td>';
print '<td>'.$langs->trans("Currency".$conf->monnaie).'</td></tr>';
// Statut
print '<tr><td height="10">'.$langs->trans('Status').'</td><td align="left" colspan="3">'.$propal->getLibStatut(4).'</td></tr>';
print '</table><br>';
/*
* Lignes de propale
*
*/
$sql = 'SELECT pt.rowid, pt.description, pt.price, pt.fk_product, pt.qty, pt.tva_tx, pt.remise_percent, pt.subprice, p.label as product, p.ref, p.fk_product_type, p.rowid as prodid';
$sql .= ' FROM '.MAIN_DB_PREFIX.'propaldet as pt LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON pt.fk_product=p.rowid';
$sql .= ' WHERE pt.fk_propal = '.$propal->id;
$sql .= ' ORDER BY pt.rowid ASC';
$resql = $db->query($sql);
if ($resql)
{
$num_lignes = $db->num_rows($resql);
$i = 0;
$total = 0;
print '<table class="noborder" width="100%">';
if ($num_lignes)
{
print '<tr class="liste_titre">';
print '<td>'.$langs->trans('Description').'</td>';
print '<td align="right" width="50">'.$langs->trans('VAT').'</td>';
print '<td align="right" width="80">'.$langs->trans('PriceUHT').'</td>';
print '<td align="right" width="50">'.$langs->trans('Qty').'</td>';
print '<td align="right" width="50">'.$langs->trans('Discount').'</td>';
print '<td align="right" width="50">'.$langs->trans('AmountHT').'</td>';
print '<td width="16">&nbsp;</td>';
print '<td width="16">&nbsp;</td>';
print '<td width="16">&nbsp;</td>';
print "</tr>\n";
}
$var=true;
while ($i < $num_lignes)
{
$objp = $db->fetch_object($resql);
$var=!$var;
if ($_GET['action'] != 'editline' || $_GET['rowid'] != $objp->rowid)
{
print '<tr '.$bc[$var].'>';
if ($objp->fk_product > 0)
{
print '<td><a href="'.DOL_URL_ROOT.'/product/fiche.php?id='.$objp->fk_product.'">';
if ($objp->fk_product_type)
print img_object($langs->trans('ShowService'),'service');
else
print img_object($langs->trans('ShowProduct'),'product');
print ' '.$objp->ref.'</a> - '.stripslashes(nl2br($objp->product));
if ($objp->date_start && $objp->date_end)
{
print ' (Du '.dolibarr_print_date($objp->date_start).' au '.dolibarr_print_date($objp->date_end).')';
}
if ($objp->date_start && ! $objp->date_end)
{
print ' (A partir du '.dolibarr_print_date($objp->date_start).')';
}
if (! $objp->date_start && $objp->date_end)
{
print " (Jusqu'au ".dolibarr_print_date($objp->date_end).')';
}
print ($objp->description && $objp->description!=$objp->product)?'<br>'.stripslashes(nl2br($objp->description)):'';
print '</td>';
}
else
{
print '<td>'.stripslashes(nl2br($objp->description));
if ($objp->date_start && $objp->date_end)
{
print ' (Du '.dolibarr_print_date($objp->date_start).' au '.dolibarr_print_date($objp->date_end).')';
}
if ($objp->date_start && ! $objp->date_end)
{
print ' (A partir du '.dolibarr_print_date($objp->date_start).')';
}
if (! $objp->date_start && $objp->date_end)
{
print " (Jusqu'au ".dolibarr_print_date($objp->date_end).')';
}
print "</td>\n";
}
print '<td align="right">'.$objp->tva_tx.'%</td>';
print '<td align="right">'.price($objp->subprice)."</td>\n";
print '<td align="right">'.$objp->qty.'</td>';
if ($objp->remise_percent > 0)
{
print '<td align="right">'.$objp->remise_percent."%</td>\n";
}
else
{
print '<td>&nbsp;</td>';
}
print '<td align="right">'.price($objp->subprice*$objp->qty*(100-$objp->remise_percent)/100)."</td>\n";
print '<td colspan="3">&nbsp;</td>';
print '</tr>';
}
$total = $total + ($objp->qty * $objp->price);
$i++;
}
$db->free($resql);
}
else
{
dolibarr_print_error($db);
}
/*
* Lignes de remise
*/
// Réductions relatives (Remises-Ristournes-Rabbais)
/* Une réduction doit s'appliquer obligatoirement sur des lignes de factures
et non globalement
$var=!$var;
print '<form name="updateligne" action="'.$_SERVER["PHP_SELF"].'" method="post">';
print '<input type="hidden" name="action" value="setremisepercent">';
print '<input type="hidden" name="propalid" value="'.$propal->id.'">';
print '<tr class="liste_total"><td>';
print $langs->trans('CustomerRelativeDiscount');
if ($propal->brouillon) print ' <font style="font-weight: normal">('.($soc->remise_client?$langs->trans("CompanyHasRelativeDiscount",$soc->remise_client):$langs->trans("CompanyHasNoRelativeDiscount")).')</font>';
print '</td>';
print '<td>&nbsp;</td>';
print '<td>&nbsp;</td>';
print '<td>&nbsp;</td>';
print '<td align="right"><font style="font-weight: normal">';
if ($_GET['action'] == 'editrelativediscount')
{
print '<input type="text" name="remise_percent" size="2" value="'.$propal->remise_percent.'">%';
}
else
{
print $propal->remise_percent?$propal->remise_percent.'%':'&nbsp;';
}
print '</font></td>';
print '<td align="right"><font style="font-weight: normal">';
if ($_GET['action'] != 'editrelativediscount') print $propal->remise_percent?'-'.price($propal->remise_percent*$total/100):$langs->trans("DiscountNone");
else print '&nbsp;';
print '</font></td>';
if ($_GET['action'] != 'editrelativediscount')
{
if ($propal->brouillon && $user->rights->propale->creer)
{
print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editrelativediscount&amp;propalid='.$propal->id.'">'.img_edit($langs->trans('SetRelativeDiscount'),1).'</a></td>';
}
else
{
print '<td>&nbsp;</td>';
}
if ($propal->brouillon && $user->rights->propale->creer && $propal->remise_percent)
{
print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?propalid='.$propal->id.'&amp;action=setremisepercent&amp;rowid='.$objp->rowid.'">';
print img_delete();
print '</a></td>';
}
else
{
print '<td>&nbsp;</td>';
}
print '<td>&nbsp;</td>';
}
else
{
print '<td colspan="3"><input type="submit" class="button" value="'.$langs->trans("Save").'"></td>';
}
print '</tr>';
print '</form>';
*/
// Remise absolue
/* Les remises absolues doivent s'appliquer par ajout de lignes spécialisées
$var=!$var;
print '<form name="updateligne" action="'.$_SERVER["PHP_SELF"].'" method="post">';
print '<input type="hidden" name="action" value="setremiseabsolue">';
print '<input type="hidden" name="propalid" value="'.$propal->id.'">';
print '<tr class="liste_total"><td>';
print $langs->trans('CustomerAbsoluteDiscount');
if ($propal->brouillon) print ' <font style="font-weight: normal">('.($avoir_en_cours?$langs->trans("CompanyHasAbsoluteDiscount",$avoir_en_cours,$langs->trans("Currency".$conf->monnaie)):$langs->trans("CompanyHasNoAbsoluteDiscount")).')</font>';
print '</td>';
print '<td>&nbsp;</td>';
print '<td>&nbsp;</td>';
print '<td>&nbsp;</td>';
print '<td>&nbsp;</td>';
print '<td align="right"><font style="font-weight: normal">';
if ($_GET['action'] == 'editabsolutediscount')
{
print '-<input type="text" name="remise_absolue" size="2" value="'.$propal->remise_absolue.'">';
}
else
{
print $propal->remise_absolue?'-'.price($propal->remise_absolue):$langs->trans("DiscountNone");
}
print '</font></td>';
if ($_GET['action'] != 'editabsolutediscount')
{
if ($propal->brouillon && $user->rights->propale->creer)
{
print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editabsolutediscount&amp;propalid='.$propal->id.'">'.img_edit($langs->trans('SetAbsoluteDiscount'),1).'</a></td>';
}
else
{
print '<td>&nbsp;</td>';
}
if ($propal->brouillon && $user->rights->propale->creer && $propal->remise_absolue)
{
print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?propalid='.$propal->id.'&amp;action=setremiseabsolue&amp;rowid='.$objp->rowid.'">';
print img_delete();
print '</a></td>';
}
else
{
print '<td>&nbsp;</td>';
}
print '<td>&nbsp;</td>';
}
else
{
print '<td colspan="3"><input type="submit" class="button" value="'.$langs->trans("Save").'"></td>';
}
print '</tr>';
print '</form>';
*/
print '</table>';
$total = $total + ($objp->qty * $objp->price);
$i++;
}
$db->free($resql);
}
else
{
dolibarr_print_error($db);
}
/*
* Lignes de remise
*/
// Réductions relatives (Remises-Ristournes-Rabbais)
/* Une réduction doit s'appliquer obligatoirement sur des lignes de factures
et non globalement
$var=!$var;
print '<form name="updateligne" action="'.$_SERVER["PHP_SELF"].'" method="post">';
print '<input type="hidden" name="action" value="setremisepercent">';
print '<input type="hidden" name="propalid" value="'.$propal->id.'">';
print '<tr class="liste_total"><td>';
print $langs->trans('CustomerRelativeDiscount');
if ($propal->brouillon) print ' <font style="font-weight: normal">('.($soc->remise_client?$langs->trans("CompanyHasRelativeDiscount",$soc->remise_client):$langs->trans("CompanyHasNoRelativeDiscount")).')</font>';
print '</td>';
print '<td>&nbsp;</td>';
print '<td>&nbsp;</td>';
print '<td>&nbsp;</td>';
print '<td align="right"><font style="font-weight: normal">';
if ($_GET['action'] == 'editrelativediscount')
{
print '<input type="text" name="remise_percent" size="2" value="'.$propal->remise_percent.'">%';
}
else
{
print $propal->remise_percent?$propal->remise_percent.'%':'&nbsp;';
}
print '</font></td>';
print '<td align="right"><font style="font-weight: normal">';
if ($_GET['action'] != 'editrelativediscount') print $propal->remise_percent?'-'.price($propal->remise_percent*$total/100):$langs->trans("DiscountNone");
else print '&nbsp;';
print '</font></td>';
if ($_GET['action'] != 'editrelativediscount')
{
if ($propal->brouillon && $user->rights->propale->creer)
{
print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editrelativediscount&amp;propalid='.$propal->id.'">'.img_edit($langs->trans('SetRelativeDiscount'),1).'</a></td>';
}
else
{
print '<td>&nbsp;</td>';
}
if ($propal->brouillon && $user->rights->propale->creer && $propal->remise_percent)
{
print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?propalid='.$propal->id.'&amp;action=setremisepercent&amp;rowid='.$objp->rowid.'">';
print img_delete();
print '</a></td>';
}
else
{
print '<td>&nbsp;</td>';
}
print '<td>&nbsp;</td>';
}
else
{
print '<td colspan="3"><input type="submit" class="button" value="'.$langs->trans("Save").'"></td>';
}
print '</tr>';
print '</form>';
*/
// Remise absolue
/* Les remises absolues doivent s'appliquer par ajout de lignes spécialisées
$var=!$var;
print '<form name="updateligne" action="'.$_SERVER["PHP_SELF"].'" method="post">';
print '<input type="hidden" name="action" value="setremiseabsolue">';
print '<input type="hidden" name="propalid" value="'.$propal->id.'">';
print '<tr class="liste_total"><td>';
print $langs->trans('CustomerAbsoluteDiscount');
if ($propal->brouillon) print ' <font style="font-weight: normal">('.($avoir_en_cours?$langs->trans("CompanyHasAbsoluteDiscount",$avoir_en_cours,$langs->trans("Currency".$conf->monnaie)):$langs->trans("CompanyHasNoAbsoluteDiscount")).')</font>';
print '</td>';
print '<td>&nbsp;</td>';
print '<td>&nbsp;</td>';
print '<td>&nbsp;</td>';
print '<td>&nbsp;</td>';
print '<td align="right"><font style="font-weight: normal">';
if ($_GET['action'] == 'editabsolutediscount')
{
print '-<input type="text" name="remise_absolue" size="2" value="'.$propal->remise_absolue.'">';
}
else
{
print $propal->remise_absolue?'-'.price($propal->remise_absolue):$langs->trans("DiscountNone");
}
print '</font></td>';
if ($_GET['action'] != 'editabsolutediscount')
{
if ($propal->brouillon && $user->rights->propale->creer)
{
print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editabsolutediscount&amp;propalid='.$propal->id.'">'.img_edit($langs->trans('SetAbsoluteDiscount'),1).'</a></td>';
}
else
{
print '<td>&nbsp;</td>';
}
if ($propal->brouillon && $user->rights->propale->creer && $propal->remise_absolue)
{
print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?propalid='.$propal->id.'&amp;action=setremiseabsolue&amp;rowid='.$objp->rowid.'">';
print img_delete();
print '</a></td>';
}
else
{
print '<td>&nbsp;</td>';
}
print '<td>&nbsp;</td>';
}
else
{
print '<td colspan="3"><input type="submit" class="button" value="'.$langs->trans("Save").'"></td>';
}
print '</tr>';
print '</form>';
*/
print '</table>';
print '</div>';
@ -688,7 +683,7 @@ if ($_GET["propalid"] > 0)
*/
$sql = 'SELECT id, '.$db->pdate('a.datea'). ' as da, label, note, fk_user_author' ;
$sql .= ' FROM '.MAIN_DB_PREFIX.'actioncomm as a';
$sql .= ' WHERE a.fk_soc = '.$obj->idp.' AND a.propalrowid = '.$propal->id ;
$sql .= ' WHERE a.fk_soc = '.$societe->id.' AND a.propalrowid = '.$propal->id ;
$resql = $db->query($sql);
if ($resql)
{

View File

@ -107,7 +107,7 @@ class Facture
*/
function create($user)
{
global $langs,$conf;
global $langs,$conf,$mysoc;
$this->db->begin();
@ -198,10 +198,7 @@ class Facture
$res=$prod->fetch($this->products[$i]);
$soc = new Societe($this->db);
$soc->fetch($this->socidp);
if($soc->tva_assuj == "0")
$tva_tx ="0";
else
$tva_tx=$prod->tva_tx;
$tva_tx = get_default_tva($mysoc,$soc,$prod->tva_tx);
// multiprix
if($conf->global->PRODUIT_MULTIPRICES == 1)
$price = $prod->multiprices[$soc->price_level];
@ -239,8 +236,9 @@ class Facture
if ($_facrec->lignes[$i]->produit_id)
{
$prod = new Product($this->db, $_facrec->lignes[$i]->produit_id);
$prod->fetch($_facrec->lignes[$i]->produit_id);
$res=$prod->fetch($_facrec->lignes[$i]->produit_id);
}
$tva_tx = get_default_tva($mysoc,$soc,$prod->tva_tx);
$result_insert = $this->addline(
$this->id,
@ -400,7 +398,7 @@ class Facture
*/
$sql = 'SELECT l.rowid, l.fk_product, l.description, l.price, l.qty, l.tva_taux, l.remise, l.remise_percent, l.subprice,';
$sql.= ' '.$this->db->pdate('l.date_start').' as date_start,'.$this->db->pdate('l.date_end').' as date_end,';
$sql.= ' l.info_bits, l.total_ht, l.total_ttc,';
$sql.= ' l.info_bits, l.total_ht, l.total_tva, l.total_ttc,';
$sql.= ' p.label as label, p.description as product_desc';
$sql.= ' FROM '.MAIN_DB_PREFIX.'facturedet as l';
$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON l.fk_product = p.rowid';
@ -432,6 +430,7 @@ class Facture
$faclig->date_end = $objp->date_end;
$faclig->info_bits = $objp->info_bits;
$faclig->total_ht = $objp->total_ht;
$faclig->total_tva = $objp->total_tva;
$faclig->total_ttc = $objp->total_ttc;
$this->lignes[$i] = $faclig;
$i++;
@ -996,23 +995,23 @@ class Facture
}
/**
* \brief Ajoute une ligne de facture (associé à un produit/service prédéfini ou non)
* \param facid id de la facture
* \param desc description de la ligne
* \param product_desc surcharge description produit
* \param pu prix unitaire
* \param qty quantit
* \param txtva taux de tva
* \param fk_product id du produit/service predéfini
* \param remise_percent pourcentage de remise de la ligne
* \param datestart date de debut de validité du service
* \param dateend date de fin de validité du service
* \param ventil code de ventilation comptable
* \remarks Les parametres sont deja censé etre juste et avec valeurs finales a l'appel
* de cette methode. Aussi, pour le taux tva, il doit deja avoir ete défini
* par l'appelant par la methode get_default_tva(societe_vendeuse,societe_acheteuse,taux_produit)
*/
function addline($facid, $desc, $product_desc, $pu, $qty, $txtva, $fk_product=0, $remise_percent=0, $datestart='', $dateend='', $ventil = 0)
* \brief Ajoute une ligne de facture (associé à un produit/service prédéfini ou non)
* \param facid id de la facture
* \param desc description de la ligne
* \param pu prix unitaire
* \param qty quantité
* \param txtva taux de tva forcé, sinon -1
* \param fk_product id du produit/service predéfini
* \param remise_percent pourcentage de remise de la ligne
* \param datestart date de debut de validité du service
* \param dateend date de fin de validité du service
* \param ventil code de ventilation comptable
* \remarks Les parametres sont deja censé etre juste et avec valeurs finales a l'appel
* de cette methode. Aussi, pour le taux tva, il doit deja avoir ete défini
* par l'appelant par la methode get_default_tva(societe_vendeuse,societe_acheteuse,taux_produit)
* et le desc doit deja avoir la bonne valeur (a l'appelant de gerer le multilangue)
*/
function addline($facid, $desc, $pu, $qty, $txtva, $fk_product=0, $remise_percent=0, $datestart='', $dateend='', $ventil = 0)
{
global $conf;
dolibarr_syslog("facture.class.php::addline($facid,$desc,$product_desc,$pu,$qty,$txtva,$fk_product,$remise_percent,$datestart,$dateend,$ventil)");
@ -1028,19 +1027,6 @@ class Facture
if (! $qty) $qty=1;
if (! $ventil) $ventil=0;
if (! $info_bits) $info_bits=0;
if ($fk_product && ! $pu)
{
$prod = new Product($this->db, $fk_product);
$prod->fetch($fk_product);
$product_desc = $prod->description;
// multiprix
if($conf->global->PRODUIT_MULTIPRICES == 1)
$pu = $prod->multiprices[$soc->price_level];
else
{
$pu=$prod->price;
}
}
$pu = price2num($pu);
$txtva=price2num($txtva);
@ -1082,34 +1068,15 @@ class Facture
return -1;
}
if ($conf->global->PRODUIT_CHANGE_PROD_DESC)
{
if (!$product_desc)
{
$product_desc = $desc;
}
}
// Insertion dans base de la ligne
$sql = 'INSERT INTO '.MAIN_DB_PREFIX.'facturedet';
$sql.= ' (fk_facture, description, price, qty, tva_taux,';
$sql.= ' fk_product, remise_percent, subprice, remise, date_start, date_end, fk_code_ventilation, rang,';
$sql.= ' info_bits, total_ht, total_tva, total_ttc)';
if ($conf->global->PRODUIT_CHANGE_PROD_DESC)
{
$sql.= " VALUES ($facid, '".addslashes($product_desc)."',";
$sql.= "'".price2num($price)."',";
$sql.= "'".price2num($qty)."',";
$sql.= "'".price2num($txtva)."',";
}
else
{
$sql.= " VALUES ($facid, '".addslashes($desc)."',";
$sql.= "'".price2num($price)."',";
$sql.= "'".price2num($qty)."',";
$sql.= "'".price2num($txtva)."',";
}
$sql.= " VALUES (".$facid.", '".addslashes($desc)."',";
$sql.= "'".price2num($price)."',";
$sql.= "'".price2num($qty)."',";
$sql.= "'".price2num($txtva)."',";
if ($fk_product) { $sql.= "'$fk_product',"; }
else { $sql.='0,'; }
$sql.= " '".price2num($remise_percent)."',";
@ -1265,7 +1232,7 @@ class Facture
$err=0;
// Lit les lignes detail
$sql = 'SELECT qty, tva_taux, subprice, remise_percent, price, total_ht, total_ttc';
$sql = 'SELECT qty, tva_taux, subprice, remise_percent, price, total_ht, total_tva, total_ttc';
$sql.= ' FROM '.MAIN_DB_PREFIX.'facturedet';
$sql.= ' WHERE fk_facture = '.$facid;
$result = $this->db->query($sql);

View File

@ -89,6 +89,7 @@ Supplier=Supplier
CompanyList=Companies' list
AddContact=Add contact
Contact=Contact
DefaultContact=Default contact
AddCompany=Add company
DeleteACompany=Delete a company
PersonalInformations=Personal data

View File

@ -104,6 +104,7 @@ Family=Family
Description=Description
Designation=Description
Model=Model
DefaultModel=Default model
Action=Action
About=About
WelcomeString=<font class="body">We are </font>%s<font class="body">, and you are connected as user</font> %s

View File

@ -89,6 +89,7 @@ Supplier=Fournisseur
CompanyList=Liste des sociétés
AddContact=Créer contact
Contact=Contact
DefaultContact=Contact par défaut
AddCompany=Créer société
DeleteACompany=Supprimer une société
PersonalInformations=Informations personnelles

View File

@ -104,6 +104,7 @@ Description=Description
Designation=Désignation
Action=Action
Model=Modèle
DefaultModel=Modèle par défaut
About=À propos
WelcomeString=<font class="body">Nous sommes le</font> %s<font class="body">, et vous êtes connecté(e) en tant que </font> %s
Number=Nombre

View File

@ -1702,10 +1702,13 @@ function price2num($amount)
* \param taux_produit Taux par defaut du produit vendu
* \return float Taux de tva de la ligne
*/
function get_default_tva($societe_vendeuse='', $societe_acheteuse='', $taux_produit='')
function get_default_tva($societe_vendeuse, $societe_acheteuse, $taux_produit)
{
// Si vendeur non assujeti à TVA
if (! $societe_vendeuse->tva_assuj) return 0;
dolibarr_syslog("get_default_tva vendeur_assujeti=$societe_vendeuse->tva_assuj pays_vendeur=$societe_vendeuse->pays_id, pays_acheteur=$societe_acheteuse->pays_id, taux_produit=$taux_produit");
// Si vendeur non assujeti à TVA (tva_assuj vaut 0/1 ou franchise/reel)
if (is_numeric($societe_vendeuse->tva_assuj) && ! $societe_vendeuse->tva_assuj) return 0;
if (! is_numeric($societe_vendeuse->tva_assuj) && $societe_vendeuse->tva_assuj=='franchise') return 0;
// Si le (pays vendeur = pays acheteur) alors la TVA par défaut=TVA du produit vendu. Fin de règle.
if ($societe_vendeuse->pays_id == $societe_acheteuse->pays_id)

View File

@ -33,22 +33,25 @@
/**
\brief Permet de calculer les parts total HT, TVA et TTC d'une ligne de
facture, propale ou autre depuis son prix unitaire, quantité et remise ligne.
facture, propale ou autre depuis:
Prix unitaire, quantité, remise_percent_ligne, txtva, remise_percent_global.
\param qty
\param pu
\param remise_percent
\param remise_percent_ligne
\param txtva
\param remise_percent_global
\return result[0] total_ht
result[1] total_tva
result[2] total_ttc
*/
function calcul_price_total($qty, $pu, $remise_percent, $txtva)
function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $remise_percent_global=0)
{
$result=array();
$tot_sans_remise = $pu * $qty;
$tot_avec_remise = $tot_sans_remise - ($tot_sans_remise * $remise_percent / 100);
$tot_avec_remise_ligne = $tot_sans_remise * ( 1 - ($remise_percent_ligne / 100));
$tot_avec_remise = $tot_avec_remise_ligne * ( 1 - ($remise_percent_global / 100));
$result[0] = round($tot_avec_remise, 2);
$result[2] = round($tot_avec_remise + ($tot_avec_remise * $txtva / 100), 2);
$result[2] = round($tot_avec_remise * ( 1 + ($txtva / 100)), 2);
$result[1] = $result[2] - $result[0];
return $result;
}

View File

@ -174,7 +174,27 @@ $mysoc->nom=$conf->global->MAIN_INFO_SOCIETE_NOM;
$mysoc->adresse=$conf->global->MAIN_INFO_SOCIETE_ADRESSE;
$mysoc->cp=$conf->global->MAIN_INFO_SOCIETE_CP;
$mysoc->ville=$conf->global->MAIN_INFO_SOCIETE_VILLE;
$mysoc->pays_code=$conf->global->MAIN_INFO_SOCIETE_PAYS;
// Si dans MAIN_INFO_SOCIETE_PAYS on a un id de pays, on recupere code
if (is_numeric($conf->global->MAIN_INFO_SOCIETE_PAYS))
{
$mysoc->pays_id=$conf->global->MAIN_INFO_SOCIETE_PAYS;
$sql = "SELECT code from ".MAIN_DB_PREFIX."c_pays";
$sql .= " WHERE rowid = ".$conf->global->MAIN_INFO_SOCIETE_PAYS;
$result=$db->query($sql);
if ($result)
{
$obj = $db->fetch_object();
$mysoc->pays_code=$obj->code;
}
else {
dolibarr_print_error($db);
}
}
// Si dans MAIN_INFO_SOCIETE_PAYS on a deja un code, tout est fait
else
{
$mysoc->pays_code=$conf->global->MAIN_INFO_SOCIETE_PAYS;
}
$mysoc->tel=$conf->global->MAIN_INFO_SOCIETE_TEL;
$mysoc->fax=$conf->global->MAIN_INFO_SOCIETE_FAX;
$mysoc->url=$conf->global->MAIN_INFO_SOCIETE_WEB;

View File

@ -780,6 +780,7 @@ class Product
if (! $id && ! $ref)
{
$this->error=$langs->trans('ErrorWrongParameters');
dolibarr_error("Product::fetch ".$this->error);
return -1;
}

View File

@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2002-2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2004 Éric Seigne <eric.seigne@ryxeo.com>
* Copyright (C) 2004-2005 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2004-2006 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2005 Marc Barilley / Ocebo <marc@ocebo.com>
* Copyright (C) 2005-2006 Regis Houssin <regis.houssin@cap-networks.com>
* Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
@ -55,9 +55,6 @@ class Propal
var $status;
var $datep;
var $fin_validite;
var $products;
var $products_qty;
var $price;
var $cond_reglement_id;
var $cond_reglement_code;
@ -69,9 +66,12 @@ class Propal
var $note;
var $note_public;
var $date_livraison;
var $date_livraison;
var $adresse_livraison_id;
var $products;
var $products_qty;
var $labelstatut=array();
var $labelstatut_short=array();
@ -125,7 +125,6 @@ class Propal
* \return void
* \see insert_product
*/
function add_product($idproduct, $qty, $remise_percent=0)
{
if ($idproduct > 0)
@ -150,25 +149,31 @@ class Propal
* \return int >0 si ok, <0 si ko
* \see add_product
*/
function insert_discount($idproduct, $qty, $remise_percent=0, $p_desc='')
function insert_discount($idproduct, $qty, $remise_percent=0, $desc='')
{
}
/**
* \brief Ajout d'un produit dans la proposition, en base
* \param idproduct Id du produit à ajouter
* \param qty Quantité
* \param remise_percent Remise relative effectuée sur le produit
* \param p_desc Descriptif optionnel
* \return int >0 si ok, <0 si ko
* \see add_product
* \brief Ajout d'un produit dans la proposition, en base
* \param idproduct Id du produit à ajouter
* \param qty Quantité
* \param remise_percent Remise relative effectuée sur le produit
* \param desc Descriptif optionnel
* \return int >0 si ok, <0 si ko
* \see add_product
* \remarks Les parametres sont deja censé etre juste et avec valeurs finales a l'appel
* de cette methode. Aussi, pour le taux tva, il doit deja avoir ete défini
* par l'appelant par la methode get_default_tva(societe_vendeuse,societe_acheteuse,taux_produit)
* et le desc doit deja avoir la bonne valeur (a l'appelant de gerer le multilangue)
*/
function insert_product($idproduct, $qty, $remise_percent=0, $p_desc='')
function insert_product($idproduct, $qty, $remise_percent=0, $desc='')
{
global $conf;
dolibarr_syslog("propal.class.php::insert_product $idproduct, $qty, $remise_percent, $p_desc");
global $conf,$mysoc;
dolibarr_syslog("propal.class.php::insert_product $idproduct, $qty, $remise_percent, $desc");
include_once(DOL_DOCUMENT_ROOT.'/lib/price.lib.php');
if ($this->statut == 0)
{
// Nettoyage parametres
@ -180,14 +185,10 @@ class Propal
$prod = new Product($this->db, $idproduct);
if ($prod->fetch($idproduct) > 0)
{
$p_product_desc = $prod->description;
$this -> fetch_client();
if($this->client->tva_assuj == "0")
$txtva ="0";
else
$txtva=$prod->tva_tx;
$this->fetch_client();
// multiprix
if($conf->global->PRODUIT_MULTIPRICES == 1)
if ($conf->global->PRODUIT_MULTIPRICES == 1)
{
$price = price2num($prod->multiprices[$this->client->price_level]);
$subprice = price2num($prod->multiprices[$this->client->price_level]);
@ -197,28 +198,37 @@ class Propal
$price = price2num($prod->price);
$subprice = price2num($prod->price);
}
/*
$txtva = get_default_tva($mysoc,$this->client,$prod->tva_tx);
if (! $desc) $desc = $prod->description;
if ($conf->global->PRODUIT_CHANGE_PROD_DESC) $desc=$prod->description;
*/
// Calcul du total TTC et de la TVA pour la ligne a partir de
// qty, pu, remise_percent et txtva
// TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
// la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
$tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva);
$total_ht = $tabprice[0];
$total_tva = $tabprice[1];
$total_ttc = $tabprice[2];
// Calcul remise et nouveau prix
// Anciens indicateurs: $price, $subprice, $remise (a ne plus utiliser)
$remise = 0;
if ($remise_percent > 0)
{
$remise = round(($prod->price * $remise_percent / 100), 2);
$price = $prod->price - $remise;
}
if ($conf->global->PRODUIT_CHANGE_PROD_DESC)
{
$sql = "INSERT INTO ".MAIN_DB_PREFIX."propaldet (fk_propal, fk_product, qty, price, tva_tx, description, remise_percent, subprice) VALUES ";
$sql .= " (".$this->id.",". $idproduct.",'". $qty."','". price2num($price)."','".$txtva."','".addslashes($p_product_desc)."','".price2num($remise_percent)."','".price2num($subprice)."')";
}
else
{
$sql = "INSERT INTO ".MAIN_DB_PREFIX."propaldet (fk_propal, fk_product, qty, price, tva_tx, description, remise_percent, subprice) VALUES ";
$sql .= " (".$this->id.",". $idproduct.",'". $qty."','". price2num($price) ."','".$txtva."','".addslashes($p_desc?$p_desc:$prod->label)."','".price2num($remise_percent)."','".price2num($subprice)."')";
}
if ($this->db->query($sql) )
$sql = "INSERT INTO ".MAIN_DB_PREFIX."propaldet (fk_propal, fk_product, qty, price, tva_tx, description, remise_percent, subprice,";
$sql.= " total_ht, total_tva, total_ttc)";
$sql.= " VALUES ";
$sql.= " (".$this->id.",". $idproduct.",'". $qty."','". price2num($price) ."','".$txtva."','".addslashes($desc?$desc:$prod->label)."','".price2num($remise_percent)."','".price2num($subprice)."',";
$sql.= " '".price2num($total_ht) ."',";
$sql.= " '".price2num($total_tva)."',";
$sql.= " '".price2num($total_ttc)."'";
$sql.= ")";
if ($this->db->query($sql))
{
$this->update_price();
return 1;
@ -226,6 +236,7 @@ class Propal
else
{
$this->error=$this->db->error();
dolibarr_syslog("Error sql=$sql, error=".$this->error);
return -1;
}
}
@ -244,39 +255,61 @@ class Propal
/**
* \brief Ajout d'un produit dans la proposition, en base
* \param p_desc Descriptif optionnel
* \param p_price Prix
* \param p_qty Quantité
* \param p_tva_tx Taux tva
* \param remise_percent Remise effectuée sur le produit
* \return int >0 si ok, <0 si ko
* \see add_product
* \brief Ajout d'un produit dans la proposition, en base
* \param desc Descriptif optionnel
* \param pu Prix
* \param qty Quantité
* \param tva_tx Taux tva
* \param remise_percent Remise effectuée sur le produit
* \return int >0 si ok, <0 si ko
* \see add_product
* \remarks Les parametres sont deja censé etre juste et avec valeurs finales a l'appel
* de cette methode. Aussi, pour le taux tva, il doit deja avoir ete défini
* par l'appelant par la methode get_default_tva(societe_vendeuse,societe_acheteuse,taux_produit)
* et le desc doit deja avoir la bonne valeur (a l'appelant de gerer le multilangue)
*/
function insert_product_generic($p_desc, $p_price, $p_qty, $p_tva_tx, $remise_percent=0)
function insert_product_generic($desc, $pu, $qty, $tva_tx, $remise_percent=0)
{
dolibarr_syslog("propal.class.php::insert_product_generic $p_desc, $p_price, $p_qty, $p_tva_tx, $remise_percent");
global $conf,$mysoc;
dolibarr_syslog("propal.class.php::insert_product_generic $desc, $pu, $qty, $tva_tx, $remise_percent");
include_once(DOL_DOCUMENT_ROOT.'/lib/price.lib.php');
if ($this->statut == 0)
{
// Nettoyage paramètres
$remise_percent=price2num($remise_percent);
$p_qty=price2num($p_qty);
if (strlen(trim($p_qty))==0) $p_qty=1;
$p_price = price2num($p_price);
$qty=price2num($qty);
if (! $qty) $qty=1;
$pu = price2num($pu);
$tva_tx = price2num($tva_tx);
$price = $p_price;
$subprice = $p_price;
// Calcul du total TTC et de la TVA pour la ligne a partir de
// qty, pu, remise_percent et txtva
// TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
// la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
$tabprice=calcul_price_total($qty, $pu, $remise_percent, $tva_tx);
$total_ht = $tabprice[0];
$total_tva = $tabprice[1];
$total_ttc = $tabprice[2];
// Anciens indicateurs: $price, $subprice, $remise (a ne plus utiliser)
$price = $pu;
$subprice = $pu;
if ($remise_percent > 0)
{
$remise = round(($p_price * $remise_percent / 100), 2);
$price = $p_price - $remise;
$remise = round(($pu * $remise_percent / 100), 2);
$price = $pu - $remise;
}
$sql = "INSERT INTO ".MAIN_DB_PREFIX."propaldet (fk_propal, fk_product, qty, price, tva_tx, description, remise_percent, subprice) VALUES ";
$sql .= " (".$this->id.", 0,'". $p_qty."','". price2num($price)."','".$p_tva_tx."','".addslashes($p_desc)."','$remise_percent', '".price2num($subprice)."') ; ";
$sql = "INSERT INTO ".MAIN_DB_PREFIX."propaldet (fk_propal, fk_product, qty, price, tva_tx, description, remise_percent, subprice, total_ht, total_tva, total_ttc)";
$sql.= " VALUES ";
$sql.= " (".$this->id.", 0,'". $qty."','". price2num($price)."','".$tva_tx."','".addslashes($desc)."','$remise_percent', '".price2num($subprice)."',";
$sql.= " '".price2num($total_ht) ."',";
$sql.= " '".price2num($total_tva)."',";
$sql.= " '".price2num($total_ttc)."'";
$sql.= ")";
if ($this->db->query($sql) )
if ($this->db->query($sql))
{
if ($this->update_price() > 0)
@ -290,6 +323,8 @@ class Propal
}
else
{
$this->error=$this->db->error();
dolibarr_syslog("Error sql=$sql, error=".$this->error);
return -2;
}
}
@ -306,23 +341,39 @@ class Propal
* \param desc Description
* \return int 0 en cas de succès
*/
function UpdateLigne($id, $subprice, $qty, $remise_percent=0, $tva_tx, $desc='')
function UpdateLigne($id, $pu, $qty, $remise_percent=0, $tva_tx, $desc='')
{
global $conf,$mysoc;
dolibarr_syslog("propal.class.php::updateligne $id, $pu, $qty, $remise_percent, $tva_tx, $desc");
include_once(DOL_DOCUMENT_ROOT.'/lib/price.lib.php');
if ($this->statut == 0)
{
// Nettoyage paramètres
$subprice=price2num($subprice);
$price = $subprice;
// Nettoyage paramètres
$remise_percent=price2num($remise_percent);
$tva_tx=price2num($tva_tx);
$qty=price2num($qty);
if (! $qty) $qty=1;
$pu = price2num($pu);
$tva_tx = price2num($tva_tx);
// Calcul du total TTC et de la TVA pour la ligne a partir de
// qty, pu, remise_percent et txtva
// TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
// la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
$tabprice=calcul_price_total($qty, $pu, $remise_percent, $tva_tx);
$total_ht = $tabprice[0];
$total_tva = $tabprice[1];
$total_ttc = $tabprice[2];
// Anciens indicateurs: $price, $subprice, $remise (a ne plus utiliser)
$price = $pu;
$subprice = $pu;
if ($remise_percent > 0)
{
$remise = round(($subprice * $remise_percent / 100), 2);
$price = $subprice - $remise;
$remise = round(($pu * $remise_percent / 100), 2);
$price = $pu - $remise;
}
$sql = "UPDATE ".MAIN_DB_PREFIX."propaldet ";
$sql.= " SET qty='".$qty."'";
$sql.= " , price='". price2num($price)."'";
@ -330,6 +381,9 @@ class Propal
$sql.= " , subprice='".$subprice."'";
$sql.= " , tva_tx='".$tva_tx."'";
$sql.= " , description='".addslashes($desc)."'";
$sql.= " , total_ht='".price2num($total_ht)."'";
$sql.= " , total_tva='".price2num($total_tva)."'";
$sql.= " , total_ttc='".price2num($total_ttc)."'";
$sql.= " WHERE rowid = '".$id."';";
if ($this->db->query($sql))
@ -340,7 +394,7 @@ class Propal
else
{
$this->error=$this->db->error();
dolibarr_syslog("Propal::UpdateLigne Erreur -1");
dolibarr_syslog("Propal::UpdateLigne Erreur sql=$sql, error=".$this->error);
return -1;
}
}
@ -693,9 +747,12 @@ class Propal
function create()
{
global $langs,$conf;
// Définition paramètres
// Nettoyage/définition paramètres
$this->fin_validite = $this->datep + ($this->duree_validite * 24 * 3600);
dolibarr_syslog("Propal::create ref=".$this->ref);
$this->db->begin();
// Insertion dans la base
@ -744,6 +801,7 @@ class Propal
$result=$this->db->query($sql);
}
// Mise a journ infos dénormalisés
$resql=$this->update_price();
if ($resql)
{
@ -782,36 +840,53 @@ class Propal
*/
function update_price()
{
include_once DOL_DOCUMENT_ROOT . "/lib/price.lib.php";
include_once(DOL_DOCUMENT_ROOT.'/lib/price.lib.php');
/*
* Liste des produits a ajouter
*/
$sql = "SELECT price, qty, tva_tx FROM ".MAIN_DB_PREFIX."propaldet";
$sql = "SELECT price, qty, tva_tx, total_ht, total_tva, total_ttc";
$sql.= " FROM ".MAIN_DB_PREFIX."propaldet";
$sql.= " WHERE fk_propal = ".$this->id;
if ( $this->db->query($sql) )
$result = $this->db->query($sql);
if ($result)
{
$num = $this->db->num_rows();
$this->total_ht = 0;
$this->total_tva = 0;
$this->total_ttc = 0;
$num = $this->db->num_rows($result);
$i = 0;
while ($i < $num)
{
$obj = $this->db->fetch_object();
$obj = $this->db->fetch_object($result);
$this->total_ht += $obj->total_ht;
$this->total_tva += ($obj->total_ttc - $obj->total_ht);
$this->total_ttc += $obj->total_ttc;
// Anciens indicateurs
$this->amount_ht += $obj->price * $obj->qty;
$this->total_remise += 0; // Plus de remise globale (toute remise est sur une ligne)
/* \deprecated car simplifie par les 3 indicateurs total_ht, total_tva et total_ttc sur lignes
$products[$i][0] = $obj->price;
$products[$i][1] = $obj->qty;
$products[$i][2] = $obj->tva_tx;
*/
$i++;
}
}
$calculs = calcul_price($products, $this->remise_percent, $this->remise_absolue);
$this->db->free($result);
}
/* \deprecated car simplifie par les 3 indicateurs total_ht, total_tva et total_ttc sur lignes
$calculs = calcul_price($products, $this->remise_percent, $this->remise_absolue);
$this->total_remise = $calculs[3];
$this->amount_ht = $calculs[4];
$this->total_ht = $calculs[0];
$this->total_tva = $calculs[1];
$this->total_ttc = $calculs[2];
$tvas = $calculs[5];
*/
// Met a jour en base
$sql = "UPDATE ".MAIN_DB_PREFIX."propal SET";
$sql .= " price='". price2num($this->total_ht)."'";
@ -976,8 +1051,9 @@ class Propal
$sql.= " WHERE fk_statut = c.id";
$sql.= " AND rowid='".$rowid."';";
dolibarr_syslog("Propal::fecth rowid=".$rowid);
$resql=$this->db->query($sql);
if ($resql)
{
if ($this->db->num_rows($resql))
@ -1010,8 +1086,8 @@ class Propal
$this->statut_libelle = $obj->statut_label;
$this->cond_reglement_id = $obj->fk_cond_reglement;
$this->mode_reglement_id = $obj->fk_mode_reglement;
$this->date_livraison = $obj->date_livraison;
$this->adresse_livraison_id = $obj->fk_adresse_livraison;
$this->date_livraison = $obj->date_livraison;
$this->adresse_livraison_id = $obj->fk_adresse_livraison;
$this->user_author_id = $obj->fk_user_author;
@ -1061,7 +1137,8 @@ class Propal
* Lignes propales liées à un produit ou non
*/
$sql = "SELECT d.description, d.price, d.tva_tx, d.qty, d.remise_percent, d.subprice, d.fk_product,";
$sql.= " p.label, p.description as product_desc, p.ref";
$sql.= " d.total_ht, d.total_tva, d.total_ttc,";
$sql.= " p.ref, p.label, p.description as product_desc";
$sql.= " FROM ".MAIN_DB_PREFIX."propaldet as d";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON d.fk_product = p.rowid";
$sql.= " WHERE d.fk_propal = ".$this->id;
@ -1077,7 +1154,7 @@ class Propal
{
$objp = $this->db->fetch_object($result);
$ligne = new PropaleLigne();
$ligne = new PropaleLigne($this->db);
$ligne->desc = $objp->description; // Description ligne
$ligne->qty = $objp->qty;
@ -1085,6 +1162,11 @@ class Propal
$ligne->subprice = $objp->subprice;
$ligne->remise_percent = $objp->remise_percent;
$ligne->price = $objp->price;
$ligne->total_ht = $objp->total_ht;
$ligne->total_tva = $objp->total_tva;
$ligne->total_ttc = $objp->total_ttc;
$ligne->product_id = $objp->fk_product;
$ligne->coef = $objp->coef;
@ -1101,7 +1183,7 @@ class Propal
}
else
{
dolibarr_syslog("Propal::Fetch Erreur lecture des produits");
dolibarr_syslog("Propal::Fetch Erreur lecture des produits sql=$sql");
return -1;
}
@ -2282,13 +2364,13 @@ class PropaleLigne
var $subprice;
var $remise_percent;
var $price;
var $product_id;
var $desc; // Description ligne
var $product_id; // Id produit prédéfini
// From llx_product
var $libelle; // Label produit
var $product_desc; // Description produit
var $ref;
var $ref; // Reference produit
function PropaleLigne()
{

View File

@ -115,7 +115,11 @@ ALTER TABLE llx_facturedet ADD COLUMN total_tva real AFTER total_ht;
ALTER TABLE llx_facturedet ADD COLUMN total_ttc real AFTER total_tva;
ALTER TABLE llx_facturedet ADD COLUMN info_bits integer DEFAULT 0 AFTER date_end;
ALTER TABLE llx_propaldet ADD COLUMN total_ht real AFTER price;
ALTER TABLE llx_propaldet ADD COLUMN total_tva real AFTER total_ht;
ALTER TABLE llx_propaldet ADD COLUMN total_ttc real AFTER total_tva;
ALTER TABLE llx_propaldet ADD COLUMN info_bits integer DEFAULT 0 AFTER total_ttc;
ALTER TABLE llx_commande ADD INDEX idx_commande_fk_soc (fk_soc);
ALTER TABLE llx_commande ADD CONSTRAINT fk_commande_societe FOREIGN KEY (fk_soc) REFERENCES llx_societe (idp);

View File

@ -32,6 +32,10 @@ create table llx_propaldet
fk_remise_except integer NULL, -- Lien vers table des remises fixes
subprice real, -- prix avant remise
price real, -- prix final
total_ht real, -- Total HT de la ligne toute quantité et incluant remise ligne et globale
total_tva real, -- Total TVA de la ligne toute quantité et incluant remise ligne et globale
total_ttc real, -- Total TTC de la ligne toute quantité et incluant remise ligne et globale
info_bits integer DEFAULT 0, -- TVA NPR ou non
coef real, -- coefficient de marge
rang integer DEFAULT 0
)type=innodb;