Fix: Ajout protection pour éviter qu'une remise soit appliquée 2 fois sur une meme facture et dès création du brouillon.

This commit is contained in:
Laurent Destailleur 2007-04-05 11:14:10 +00:00
parent 5b3a421275
commit 35eefd83ab
5 changed files with 406 additions and 356 deletions

View File

@ -1174,6 +1174,8 @@ if ($_GET['propalid'] > 0)
} }
print '<td align="right">'.$objp->tva_tx.'%</td>'; print '<td align="right">'.$objp->tva_tx.'%</td>';
print '<td align="right">'.price($objp->subprice)."</td>\n"; print '<td align="right">'.price($objp->subprice)."</td>\n";
// Qty
print '<td align="right">'; print '<td align="right">';
if (($objp->info_bits & 2) != 2) if (($objp->info_bits & 2) != 2)
{ {

View File

@ -556,7 +556,14 @@ if ($_POST['action'] == 'add' && $user->rights->facture->creer)
'', '',
0, 0,
$prop->lignes[$i]->info_bits, $prop->lignes[$i]->info_bits,
$prop->lignes[$i]->fk_remise_except); $prop->lignes[$i]->fk_remise_except
);
if ($result < 0)
{
$error++;
break;
}
} }
} }
else else
@ -600,7 +607,14 @@ if ($_POST['action'] == 'add' && $user->rights->facture->creer)
'', '',
0, 0,
$lines[$i]->info_bits, $lines[$i]->info_bits,
$lines[$i]->fk_remise_except); $lines[$i]->fk_remise_except
);
if ($result < 0)
{
$error++;
break;
}
} }
} }
else else
@ -651,7 +665,14 @@ if ($_POST['action'] == 'add' && $user->rights->facture->creer)
$date_end, $date_end,
0, 0,
$lines[$i]->info_bits, $lines[$i]->info_bits,
$lines[$i]->fk_remise_except); $lines[$i]->fk_remise_except
);
if ($result < 0)
{
$error++;
break;
}
} }
} }
else else
@ -679,6 +700,9 @@ if ($_POST['action'] == 'add' && $user->rights->facture->creer)
{ {
$db->rollback(); $db->rollback();
$_GET["action"]='create'; $_GET["action"]='create';
$_GET["propalid"]=$_POST["propalid"];
$_GET["commandeid"]=$_POST["commandeid"];
$_GET["contratid"]=$_POST["contratid"];
if (! $mesg) $mesg='<div class="error">'.$facture->error.'</div>'; if (! $mesg) $mesg='<div class="error">'.$facture->error.'</div>';
} }
} }
@ -1315,48 +1339,6 @@ if ($_GET['action'] == 'create')
$html->select_types_paiements($mode_reglement_id,'mode_reglement_id'); $html->select_types_paiements($mode_reglement_id,'mode_reglement_id');
print '</td></tr>'; print '</td></tr>';
// Réductions relatives (Remises-Ristournes-Rabbais)
/* Une réduction doit s'appliquer obligatoirement sur des lignes de factures
et non globalement
print '<tr><td>'.$langs->trans("CustomerRelativeDiscount").'</td>';
print '<td>';
if (! $_GET['propalid'] && ! $_GET['commandeid'] && ! $_GET['contratid']) print '<input type="text" name="remise_percent" size="1" value="';
print $remise_percent;
if (! $_GET['propalid'] && ! $_GET['commandeid'] && ! $_GET['contratid']) print '">';
print ' %';
print '</td><td>'.img_info().' ';
$relative_discount=$soc->remise_client;
if ($relative_discount)
{
print $langs->trans("CompanyHasRelativeDiscount",$relative_discount);
}
else
{
print $langs->trans("CompanyHasNoRelativeDiscount");
}
print '</td></tr>';
*/
// Réductions absolues (Remises-Ristournes-Rabbais)
/* Les remises absolues doivent s'appliquer par ajout de lignes spécialisées
print '<tr><td>'.$langs->trans("CustomerAbsoluteDiscount").'</td>';
print '<td>';
if (! $_GET['propalid'] && ! $_GET['commandeid'] && ! $_GET['contratid']) print '<input type="text" name="remise_absolue" size="1" value="';
print $remise_absolue;
if (! $_GET['propalid'] && ! $_GET['commandeid'] && ! $_GET['contratid']) print '">';
print ' '.$langs->trans("Currency".$conf->monnaie);
print '</td><td>'.img_info().' ';
if ($absolute_discount)
{
print $langs->trans("CompanyHasAbsoluteDiscount",$absolute_discount,$langs->trans("Currency".$conf->monnaie));
}
else
{
print $langs->trans("CompanyHasNoAbsoluteDiscount");
}
print '</td></tr>';
*/
// Projet // Projet
if ($conf->projet->enabled) if ($conf->projet->enabled)
{ {

View File

@ -407,7 +407,16 @@ if ($_GET["propalid"] > 0)
} }
print '<td align="right">'.$objp->tva_tx.'%</td>'; print '<td align="right">'.$objp->tva_tx.'%</td>';
print '<td align="right">'.price($objp->subprice)."</td>\n"; print '<td align="right">'.price($objp->subprice)."</td>\n";
print '<td align="right">'.$objp->qty.'</td>';
// Qty
print '<td align="right">';
if (($objp->info_bits & 2) != 2)
{
print $objp->qty;
}
else print '&nbsp;';
print '</td>';
if ($objp->remise_percent > 0) if ($objp->remise_percent > 0)
{ {
print '<td align="right">'.$objp->remise_percent."%</td>\n"; print '<td align="right">'.$objp->remise_percent."%</td>\n";

View File

@ -183,13 +183,13 @@ class DiscountAbsolute
/** /**
* \brief Link the discount to a particular invoice * \brief Link the discount to a particular invoice line
* \param rowid Invoice id * \param rowid Invoice line id
* \return int <0 ko, >0 ok * \return int <0 ko, >0 ok
*/ */
function link_to_invoice($rowid) function link_to_invoice($rowid)
{ {
dolibarr_syslog("Discount.class::link_to_invoice link discount ".$this->id." to invoice rowid=".$rowid); dolibarr_syslog("DiscountAbsolute::link_to_invoice link discount ".$this->id." to invoice line rowid=".$rowid);
$sql ="UPDATE ".MAIN_DB_PREFIX."societe_remise_except"; $sql ="UPDATE ".MAIN_DB_PREFIX."societe_remise_except";
$sql.=" SET fk_facture = ".$rowid; $sql.=" SET fk_facture = ".$rowid;
@ -202,7 +202,7 @@ class DiscountAbsolute
else else
{ {
$this->error=$this->db->error(); $this->error=$this->db->error();
dolibarr_syslog("Discount.class::link_to_invoice ".$this->error." sql=".$sql); dolibarr_syslog("DiscountAbsolute::link_to_invoice ".$this->error." sql=".$sql);
return -1; return -1;
} }
} }

View File

@ -140,11 +140,13 @@ class Facture extends CommonObject
if (! $this->mode_reglement_id) $this->mode_reglement_id = 0; if (! $this->mode_reglement_id) $this->mode_reglement_id = 0;
$this->brouillon = 1; $this->brouillon = 1;
dolibarr_syslog("Facture::Create"); dolibarr_syslog("Facture::Create user=".$user->id);
$soc = new Societe($this->db); $soc = new Societe($this->db);
$soc->fetch($this->socid); $soc->fetch($this->socid);
$error=0;
$this->db->begin(); $this->db->begin();
// Facture récurrente // Facture récurrente
@ -196,6 +198,7 @@ class Facture extends CommonObject
$sql.= ",".$this->mode_reglement_id; $sql.= ",".$this->mode_reglement_id;
$sql.= ",".$this->db->idate($datelim).", '".$this->modelpdf."')"; $sql.= ",".$this->db->idate($datelim).", '".$this->modelpdf."')";
dolibarr_syslog("Facture::Create sql=".$sql);
$resql=$this->db->query($sql); $resql=$this->db->query($sql);
if ($resql) if ($resql)
{ {
@ -203,25 +206,29 @@ class Facture extends CommonObject
$sql = 'UPDATE '.MAIN_DB_PREFIX."facture SET facnumber='(PROV".$this->id.")' WHERE rowid=".$this->id; $sql = 'UPDATE '.MAIN_DB_PREFIX."facture SET facnumber='(PROV".$this->id.")' WHERE rowid=".$this->id;
$resql=$this->db->query($sql); $resql=$this->db->query($sql);
if (! $resql) $error++;
// Mise a jour lien avec propal ou commande // Mise a jour lien avec propal ou commande
if ($resql && $this->id && $this->propalid) if (! $error && $this->id && $this->propalid)
{ {
$sql = 'INSERT INTO '.MAIN_DB_PREFIX.'fa_pr (fk_facture, fk_propal) VALUES ('.$this->id.','.$this->propalid.')'; $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'fa_pr (fk_facture, fk_propal) VALUES ('.$this->id.','.$this->propalid.')';
$resql=$this->db->query($sql); $resql=$this->db->query($sql);
if (! $resql) $error++;
} }
if ($resql && $this->id && $this->commandeid) if (! $error && $this->id && $this->commandeid)
{ {
$sql = 'INSERT INTO '.MAIN_DB_PREFIX.'co_fa (fk_facture, fk_commande) VALUES ('.$this->id.','.$this->commandeid.')'; $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'co_fa (fk_facture, fk_commande) VALUES ('.$this->id.','.$this->commandeid.')';
$resql=$this->db->query($sql); $resql=$this->db->query($sql);
if (! $resql) $error++;
} }
/* /*
* Insertion du detail des produits dans la base * Insertion du detail des produits dans la base,
* si tableau products défini.
*/ */
for ($i = 0 ; $i < sizeof($this->products) ; $i++) for ($i = 0 ; $i < sizeof($this->products) ; $i++)
{ {
$resql = $this->addline( $result = $this->addline(
$this->id, $this->id,
$this->products[$i]->desc, $this->products[$i]->desc,
$this->products[$i]->subprice, $this->products[$i]->subprice,
@ -233,10 +240,9 @@ class Facture extends CommonObject
$this->products[$i]->date_end $this->products[$i]->date_end
); );
if ($resql < 0) if ($result < 0)
{ {
$this->error=$this->db->error; $error++;
dolibarr_print_error($this->db);
break; break;
} }
} }
@ -244,7 +250,7 @@ class Facture extends CommonObject
/* /*
* Produits de la facture récurrente * Produits de la facture récurrente
*/ */
if ($resql && $this->fac_rec > 0) if (! $error && $this->fac_rec > 0)
{ {
for ($i = 0 ; $i < sizeof($_facrec->lignes) ; $i++) for ($i = 0 ; $i < sizeof($_facrec->lignes) ; $i++)
{ {
@ -266,12 +272,14 @@ class Facture extends CommonObject
if ( $result_insert < 0) if ( $result_insert < 0)
{ {
dolibarr_print_error($this->db); $error++;
$this->error=$this->db->error();
break;
} }
} }
} }
if ($resql) if (! $error)
{ {
$resql=$this->update_price($this->id); $resql=$this->update_price($this->id);
if ($resql) if ($resql)
@ -293,6 +301,7 @@ class Facture extends CommonObject
} }
else else
{ {
dolibarr_syslog("Facture::create error ".$this->error);
$this->db->rollback(); $this->db->rollback();
return -2; return -2;
} }
@ -1109,31 +1118,40 @@ class Facture extends CommonObject
// On vérifie si la facture était une provisoire // On vérifie si la facture était une provisoire
if (! $error && $facref == 'PROV') if (! $error && $facref == 'PROV')
{ {
/* $this->fetch_lines();
* Pour chaque produit, on met a jour indicateur nbvente
* On crée ici une dénormalisation des données pas forcément utilisée.
*/
$sql = 'SELECT fk_product FROM '.MAIN_DB_PREFIX.'facturedet';
$sql.= ' WHERE fk_facture = '.$this->id;
$sql.= ' AND fk_product > 0';
$resql = $this->db->query($sql); /* La vérif qu'une remise n'est pas utilisée 2 fois est faite au moment de l'insertion de ligne
if ($resql) foreach($this->lignes as $i => $line)
{ {
$num = $this->db->num_rows($resql); // For each line, we check if it's a discount and, if a discount,
$i = 0; // we check it is not already affected to another invoice
while ($i < $num) if ($line->fk_remise_except)
{ {
$obj = $this->db->fetch_object($resql); $discount=new DiscountAbsolute($this->db);
$sql = 'UPDATE '.MAIN_DB_PREFIX.'product SET nbvente=nbvente+1 WHERE rowid = '.$obj->fk_product; $result=$discount->fetch($line->fk_remise_except);
$resql2 = $this->db->query($sql); if ($result > 0)
$i++; {
}
} }
else else
{ {
$this->error=$discount->error;
$error++; $error++;
$this->error=$this->db->error().' sql='.$sql; }
}
*/
// On met a jour table des ventes
// On crée ici une denormalisation pas forcement utilisé !!!
// TODO Virer utilisation du champ nbvente si utilisation non justifié
foreach($this->lignes as $i => $line)
{
if ($line->fk_product)
{
$sql = 'UPDATE '.MAIN_DB_PREFIX.'product SET nbvente=nbvente+1 WHERE rowid = '.$line->rowid;
$resql2 = $this->db->query($sql);
$i++;
}
} }
} }
@ -1279,7 +1297,7 @@ class Facture extends CommonObject
*/ */
function addline($facid, $desc, $pu, $qty, $txtva, $fk_product=0, $remise_percent=0, $date_start='', $date_end='', $ventil=0, $info_bits='', $fk_remise_except='', $price_base_type='HT', $pu_ttc=0) function addline($facid, $desc, $pu, $qty, $txtva, $fk_product=0, $remise_percent=0, $date_start='', $date_end='', $ventil=0, $info_bits='', $fk_remise_except='', $price_base_type='HT', $pu_ttc=0)
{ {
dolibarr_syslog("Facture::Addline $facid,$desc,$pu,$qty,$txtva,$fk_product,$remise_percent,$date_start,$date_end,$ventil,$info_bits", LOG_DEBUG); dolibarr_syslog("Facture::Addline $facid,$desc,$pu,$qty,$txtva,$fk_product,$remise_percent,$date_start,$date_end,$ventil,$info_bits,$fk_remise_except", LOG_DEBUG);
include_once(DOL_DOCUMENT_ROOT.'/lib/price.lib.php'); include_once(DOL_DOCUMENT_ROOT.'/lib/price.lib.php');
if ($this->brouillon) if ($this->brouillon)
@ -1295,13 +1313,6 @@ class Facture extends CommonObject
$pu = price2num($pu); $pu = price2num($pu);
$txtva=price2num($txtva); $txtva=price2num($txtva);
// Si facture de type avoir, le montant est forcé négatif
if ($this->type == 2)
{
// $pu=-abs($pu);
// $txtva=-abs($txtva);
}
// Calcul du total TTC et de la TVA pour la ligne a partir de // Calcul du total TTC et de la TVA pour la ligne a partir de
// qty, pu, remise_percent et txtva // qty, pu, remise_percent et txtva
// TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
@ -2659,7 +2670,8 @@ class FactureLigne
var $remise_percent; // % de la remise ligne (exemple 20%) var $remise_percent; // % de la remise ligne (exemple 20%)
var $rang = 0; var $rang = 0;
var $info_bits = 0; // Bit 0: 0 si TVA normal - 1 si TVA NPR var $info_bits = 0; // Bit 0: 0 si TVA normal - 1 si TVA NPR
//! Bit 1: 0 si ligne normal - 1 si bit discount // Bit 1: 0 si ligne normal - 1 si bit discount
//! Total HT de la ligne toute quantité et incluant la remise ligne //! Total HT de la ligne toute quantité et incluant la remise ligne
var $total_ht; var $total_ht;
//! Total TVA de la ligne toute quantité et incluant la remise ligne //! Total TVA de la ligne toute quantité et incluant la remise ligne
@ -2719,7 +2731,7 @@ class FactureLigne
$this->tva_tx = $objp->tva_taux; $this->tva_tx = $objp->tva_taux;
$this->remise_percent = $objp->remise_percent; $this->remise_percent = $objp->remise_percent;
$this->fk_remise_except = $objp->fk_remise_except; $this->fk_remise_except = $objp->fk_remise_except;
$this->produit_id = $objp->fk_product; $this->produit_id = $objp->fk_product; // Ne plus utiliser
$this->fk_product = $objp->fk_product; $this->fk_product = $objp->fk_product;
$this->date_start = $objp->date_start; $this->date_start = $objp->date_start;
$this->date_end = $objp->date_end; $this->date_end = $objp->date_end;
@ -2754,6 +2766,8 @@ class FactureLigne
*/ */
function insert() function insert()
{ {
global $langs;
dolibarr_syslog("FactureLigne::Insert rang=".$this->rang, LOG_DEBUG); dolibarr_syslog("FactureLigne::Insert rang=".$this->rang, LOG_DEBUG);
$this->db->begin(); $this->db->begin();
@ -2815,6 +2829,48 @@ class FactureLigne
{ {
$this->rowid=$this->db->last_insert_id(MAIN_DB_PREFIX.'facturedet'); $this->rowid=$this->db->last_insert_id(MAIN_DB_PREFIX.'facturedet');
// Si fk_remise_except défini, on lie la remise à la facture
// ce qui la flague comme "consommée".
if ($this->fk_remise_except)
{
$discount=new DiscountAbsolute($this->db);
$result=$discount->fetch($this->fk_remise_except);
if ($result >= 0)
{
// Check if discount was found
if ($result > 0)
{
// Check if discount not already affected to another invoice
if ($discount->fk_facture)
{
$this->error=$langs->trans("ErrorDiscountAlreadyUsed",$discount->id);
dolibarr_syslog("FactureLigne::insert Error ".$this->error);
$this->db->rollback();
return -3;
}
else
{
$discount->link_to_invoice($this->rowid);
}
}
else
{
$this->error=$langs->trans("ErrorADiscountThatHasBeenRemovedIsIncluded");
dolibarr_syslog("FactureLigne::insert Error ".$this->error);
$this->db->rollback();
return -3;
}
}
else
{
$this->error=$discount->error;
dolibarr_syslog("FactureLigne::insert Error ".$this->error);
$this->db->rollback();
return -3;
}
}
// Appel des triggers // Appel des triggers
include_once(DOL_DOCUMENT_ROOT . "/interfaces.class.php"); include_once(DOL_DOCUMENT_ROOT . "/interfaces.class.php");
$interface=new Interfaces($this->db); $interface=new Interfaces($this->db);
@ -2823,6 +2879,7 @@ class FactureLigne
$this->db->commit(); $this->db->commit();
return $this->rowid; return $this->rowid;
} }
else else
{ {