diff --git a/htdocs/compta/facture.php b/htdocs/compta/facture.php
index 0884fbe1504..56a26abc2ec 100644
--- a/htdocs/compta/facture.php
+++ b/htdocs/compta/facture.php
@@ -45,7 +45,7 @@ if ($conf->commande->enabled) require_once(DOL_DOCUMENT_ROOT.'/commande/commande
$user->getrights('facture');
$user->getrights('banque');
-if (!$user->rights->facture->lire)
+if (! $user->rights->facture->lire)
accessforbidden();
$langs->load('bills');
@@ -53,9 +53,9 @@ $langs->load('companies');
$langs->load('products');
$langs->load('main');
-$sall=isset($_GET['sall'])?$_GET['sall']:$_POST['sall'];
-if (isset($_GET['msg'])) { $msg=urldecode($_GET['msg']); }
-if ($_GET['socidp']) { $socidp=$_GET['socidp']; }
+$sall=isset($_GET['sall'])?trim($_GET['sall']):trim($_POST['sall']);
+$msg=isset($_GET['msg'])?urldecode($_GET['msg']):'';
+$socidp=isset($_GET['socidp'])?$_GET['socidp']:$_POST['socidp'];
// Sécurité accés client
if ($user->societe_id > 0)
@@ -273,10 +273,12 @@ if ($_POST['action'] == 'add')
$facture = new Facture($db, $_POST['socid']);
+ $facture->type = $_POST['type'];
+ if ($facture->type == 1) $facture->fk_facture_source = $_POST['replacement_ref'];
$facture->number = $_POST['facnumber'];
$facture->date = $datefacture;
- $facture->note_public = $_POST['note_public'];
- $facture->note = $_POST['note'];
+ $facture->note_public = trim($_POST['note_public']);
+ $facture->note = trim($_POST['note']);
$facture->ref_client = $_POST['ref_client'];
$facture->modelpdf = $_POST['model'];
@@ -604,17 +606,24 @@ if ($_POST['action'] == 'updateligne' && $user->rights->facture->creer && $_POST
exit;
}
-if ($_GET['action'] == 'deleteline' && $user->rights->facture->creer && !$conf->global->PRODUIT_CONFIRM_DELETE_LINE)
+if ($_GET['action'] == 'deleteline' && $user->rights->facture->creer && ! $conf->global->PRODUIT_CONFIRM_DELETE_LINE)
{
$fac = new Facture($db,'',$_GET['facid']);
$fac->fetch($_GET['facid']);
$result = $fac->deleteline($_GET['rowid']);
- if ($_REQUEST['lang_id'])
+ if ($result > 0)
{
- $outputlangs = new Translate(DOL_DOCUMENT_ROOT ."/langs");
- $outputlangs->setDefaultLang($_REQUEST['lang_id']);
+ if ($_REQUEST['lang_id'])
+ {
+ $outputlangs = new Translate(DOL_DOCUMENT_ROOT ."/langs");
+ $outputlangs->setDefaultLang($_REQUEST['lang_id']);
+ }
+ // facture_pdf_create($db, $fac->id, '', $fac->modelpdf, $outputlangs);
+ }
+ else
+ {
+ print $fac->error;
}
- facture_pdf_create($db, $fac->id, '', $fac->modelpdf, $outputlangs);
}
if ($_POST['action'] == 'confirm_delete' && $_POST['confirm'] == 'yes')
@@ -623,9 +632,15 @@ if ($_POST['action'] == 'confirm_delete' && $_POST['confirm'] == 'yes')
{
$fac = new Facture($db);
$result = $fac->delete($_GET['facid']);
- $_GET['facid'] = 0 ;
- Header('Location: '.$_SERVER["PHP_SELF"]);
- exit;
+ if ($result > 0)
+ {
+ Header('Location: '.$_SERVER["PHP_SELF"]);
+ exit;
+ }
+ else
+ {
+ $mesg='
';
print '';
print '';
@@ -2203,7 +2251,7 @@ else
else
{
// Générer
- if ($fac->statut == 1 && $user->rights->facture->creer)
+ if ($fac->statut >= 1 && $user->rights->facture->creer)
{
if ($fac->paye == 0)
{
@@ -2216,12 +2264,6 @@ else
}
}
- // On vérifie si la facture est supprimable. Si oui, on propose bouton supprimer
- if ($fac->statut == 0 && $fac->is_erasable() && $user->rights->facture->supprimer && $_GET['action'] != 'delete')
- {
- print 'id.'&action=delete">'.$langs->trans('Delete').'';
- }
-
// Envoyer
if ($fac->statut == 1 && $user->rights->facture->envoyer)
{
@@ -2263,6 +2305,12 @@ else
// Ajouter bouton "Annuler et Créer facture remplacement"
}
}
+
+ // Supprimer
+ if ($fac->is_erasable() && $user->rights->facture->supprimer && $_GET['action'] != 'delete')
+ {
+ print 'id.'&action=delete">'.$langs->trans('Delete').'';
+ }
print '';
}
@@ -2276,7 +2324,7 @@ else
$filename=sanitize_string($fac->ref);
$filedir=$conf->facture->dir_output . '/' . sanitize_string($fac->ref);
$urlsource=$_SERVER['PHP_SELF'].'?facid='.$fac->id;
- $genallowed=($fac->statut == 1 && $user->rights->facture->creer);
+ $genallowed=($fac->statut >= 1 && $user->rights->facture->creer);
$delallowed=$user->rights->facture->supprimer;
$var=true;
@@ -2568,196 +2616,192 @@ else
* Mode Liste *
* *
***************************************************************************/
- $page = $_GET['page'];
+ $page =$_GET['page'];
$sortorder=$_GET['sortorder'];
$sortfield=$_GET['sortfield'];
- $month=$_GET['month'];
- $year=$_GET['year'];
+ $month =$_GET['month'];
+ $year =$_GET['year'];
+ $limit = $conf->liste_limit;
+ $offset = $limit * $page ;
+
+ if (! $sortorder) $sortorder='DESC';
+ if (! $sortfield) $sortfield='f.datef';
$facturestatic=new Facture($db);
if ($page == -1) $page = 0 ;
- if ($user->rights->facture->lire)
+ $sql = 'SELECT s.nom, s.idp,';
+ $sql.= ' f.rowid as facid, f.facnumber, f.increment, f.total, f.total_ttc,';
+ $sql.= $db->pdate('f.datef').' as df, '.$db->pdate('f.date_lim_reglement').' as datelimite, ';
+ $sql.= ' f.paye as paye, f.fk_statut';
+ if (! $sall) $sql.= ' ,sum(pf.amount) as am';
+ $sql.= ' FROM '.MAIN_DB_PREFIX.'societe as s';
+ $sql.= ','.MAIN_DB_PREFIX.'facture as f';
+ if (! $sall) $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'paiement_facture as pf ON f.rowid=pf.fk_facture ';
+ if ($sall) $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'facturedet as fd ON f.rowid=fd.fk_facture ';
+ $sql.= ' WHERE f.fk_soc = s.idp';
+ if ($socidp) $sql .= ' AND s.idp = '.$socidp;
+ if ($month > 0) $sql .= ' AND date_format(f.datef, \'%m\') = '.$month;
+ if ($_GET['filtre'])
{
- $limit = $conf->liste_limit;
- $offset = $limit * $page ;
-
- if (! $sortorder) $sortorder='DESC';
- if (! $sortfield) $sortfield='f.datef';
-
- $sql = 'SELECT s.nom, s.idp,';
- $sql.= ' f.rowid as facid, f.facnumber, f.increment, f.total, f.total_ttc,';
- $sql.= $db->pdate('f.datef').' as df, '.$db->pdate('f.date_lim_reglement').' as datelimite, ';
- $sql.= ' f.paye as paye, f.fk_statut';
- if (! $sall) $sql.= ' ,sum(pf.amount) as am';
- $sql.= ' FROM '.MAIN_DB_PREFIX.'societe as s';
- $sql.= ','.MAIN_DB_PREFIX.'facture as f';
- if (! $sall) $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'paiement_facture as pf ON f.rowid=pf.fk_facture ';
- if ($sall) $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'facturedet as fd ON f.rowid=fd.fk_facture ';
- $sql.= ' WHERE f.fk_soc = s.idp';
- if ($socidp) $sql .= ' AND s.idp = '.$socidp;
- if ($month > 0) $sql .= ' AND date_format(f.datef, \'%m\') = '.$month;
- if ($_GET['filtre'])
+ $filtrearr = split(',', $_GET['filtre']);
+ foreach ($filtrearr as $fil)
{
- $filtrearr = split(',', $_GET['filtre']);
- foreach ($filtrearr as $fil)
+ $filt = split(':', $fil);
+ $sql .= ' AND ' . trim($filt[0]) . ' = ' . trim($filt[1]);
+ }
+ }
+ if ($_GET['search_ref'])
+ {
+ $sql .= ' AND f.facnumber like \'%'.addslashes(trim($_GET['search_ref'])).'%\'';
+ }
+ if ($_GET['search_societe'])
+ {
+ $sql .= ' AND s.nom like \'%'.addslashes(trim($_GET['search_societe'])).'%\'';
+ }
+ if ($_GET['search_montant_ht'])
+ {
+ $sql .= ' AND f.total = \''.addslashes(trim($_GET['search_montant_ht'])).'\'';
+ }
+ if ($_GET['search_montant_ttc'])
+ {
+ $sql .= ' AND f.total_ttc = \''.addslashes(trim($_GET['search_montant_ttc'])).'\'';
+ }
+ if ($year > 0)
+ {
+ $sql .= ' AND date_format(f.datef, \'%Y\') = '.$year;
+ }
+ if ($_POST['sf_ref'])
+ {
+ $sql .= ' AND f.facnumber like \'%'.addslashes(trim($_POST['sf_ref'])) . '%\'';
+ }
+ if ($sall)
+ {
+ $sql .= ' AND (s.nom like \'%'.addslashes($sall).'%\' OR f.facnumber like \'%'.addslashes($sall).'%\' OR f.note like \'%'.addslashes($sall).'%\' OR fd.description like \'%'.addslashes($sall).'%\')';
+ }
+
+ $sql .= ' GROUP BY f.rowid';
+
+ $sql .= ' ORDER BY ';
+ $listfield=split(',',$sortfield);
+ foreach ($listfield as $key => $value)
+ $sql.= $listfield[$key].' '.$sortorder.',';
+ $sql .= ' f.rowid DESC ';
+
+ $sql .= $db->plimit($limit+1,$offset);
+
+ $resql = $db->query($sql);
+ if ($resql)
+ {
+ $num = $db->num_rows($resql);
+
+ if ($socidp)
+ {
+ $soc = new Societe($db);
+ $soc->fetch($socidp);
+ }
+
+ print_barre_liste($langs->trans('BillsCustomers').' '.($socidp?' '.$soc->nom:''),$page,'facture.php','&socidp='.$socidp,$sortfield,$sortorder,'',$num);
+
+ $i = 0;
+ print '';
+ print '';
+ print_liste_field_titre($langs->trans('Ref'),$_SERVER['PHP_SELF'],'f.facnumber','','&socidp='.$socidp,'',$sortfield);
+ print_liste_field_titre($langs->trans('Date'),$_SERVER['PHP_SELF'],'f.datef','','&socidp='.$socidp,'align="center"',$sortfield);
+ print_liste_field_titre($langs->trans('Company'),$_SERVER['PHP_SELF'],'s.nom','','&socidp='.$socidp,'',$sortfield);
+ print_liste_field_titre($langs->trans('AmountHT'),$_SERVER['PHP_SELF'],'f.total','','&socidp='.$socidp,'align="right"',$sortfield);
+ print_liste_field_titre($langs->trans('AmountTTC'),$_SERVER['PHP_SELF'],'f.total_ttc','','&socidp='.$socidp,'align="right"',$sortfield);
+ print_liste_field_titre($langs->trans('Received'),$_SERVER['PHP_SELF'],'am','','&socidp='.$socidp,'align="right"',$sortfield);
+ print_liste_field_titre($langs->trans('Status'),$_SERVER['PHP_SELF'],'fk_statut,paye,am','','&socidp='.$socidp,'align="right"',$sortfield);
+ print ' ';
+
+ // Lignes des champs de filtre
+ print '';
+
+ if ($num > 0)
+ {
+ $var=True;
+ $total=0;
+ $totalrecu=0;
+
+ while ($i < min($num,$limit))
{
- $filt = split(':', $fil);
- $sql .= ' AND ' . $filt[0] . ' = ' . $filt[1];
- }
- }
- if ($_GET['search_ref'])
- {
- $sql .= ' AND f.facnumber like \'%'.addslashes($_GET['search_ref']).'%\'';
- }
- if ($_GET['search_societe'])
- {
- $sql .= ' AND s.nom like \'%'.addslashes($_GET['search_societe']).'%\'';
- }
- if ($_GET['search_montant_ht'])
- {
- $sql .= ' AND f.total = \''.addslashes($_GET['search_montant_ht']).'\'';
- }
- if ($_GET['search_montant_ttc'])
- {
- $sql .= ' AND f.total_ttc = \''.addslashes($_GET['search_montant_ttc']).'\'';
- }
- if ($year > 0)
- {
- $sql .= ' AND date_format(f.datef, \'%Y\') = '.$year;
- }
- if ($_POST['sf_ref'])
- {
- $sql .= ' AND f.facnumber like \'%'.addslashes($_POST['sf_ref']) . '%\'';
- }
- if ($sall)
- {
- $sql .= ' AND (s.nom like \'%'.addslashes($sall).'%\' OR f.facnumber like \'%'.addslashes($sall).'%\' OR f.note like \'%'.addslashes($sall).'%\' OR fd.description like \'%'.addslashes($sall).'%\')';
- }
+ $objp = $db->fetch_object($resql);
+ $var=!$var;
- $sql .= ' GROUP BY f.rowid';
+ print '';
+ print '| facid.'">'.img_object($langs->trans('ShowBill'),'bill').' ';
+ print 'facid.'">'.$objp->facnumber.''.$objp->increment;
+ if ($objp->datelimite < (time() - $conf->facture->client->warning_delay) && ! $objp->paye && $objp->fk_statut == 1 && ! $objp->am) print img_warning($langs->trans('Late'));
+ print ' | ';
- $sql .= ' ORDER BY ';
- $listfield=split(',',$sortfield);
- foreach ($listfield as $key => $value)
- $sql.= $listfield[$key].' '.$sortorder.',';
- $sql .= ' f.rowid DESC ';
-
- $sql .= $db->plimit($limit+1,$offset);
-
- $resql = $db->query($sql);
- if ($resql)
- {
- $num = $db->num_rows($resql);
-
- if ($socidp)
- {
- $soc = new Societe($db);
- $soc->fetch($socidp);
- }
-
- print_barre_liste($langs->trans('BillsCustomers').' '.($socidp?' '.$soc->nom:''),$page,'facture.php','&socidp='.$socidp,$sortfield,$sortorder,'',$num);
-
- $i = 0;
- print '';
- print '';
- print_liste_field_titre($langs->trans('Ref'),$_SERVER['PHP_SELF'],'f.facnumber','','&socidp='.$socidp,'',$sortfield);
- print_liste_field_titre($langs->trans('Date'),$_SERVER['PHP_SELF'],'f.datef','','&socidp='.$socidp,'align="center"',$sortfield);
- print_liste_field_titre($langs->trans('Company'),$_SERVER['PHP_SELF'],'s.nom','','&socidp='.$socidp,'',$sortfield);
- print_liste_field_titre($langs->trans('AmountHT'),$_SERVER['PHP_SELF'],'f.total','','&socidp='.$socidp,'align="right"',$sortfield);
- print_liste_field_titre($langs->trans('AmountTTC'),$_SERVER['PHP_SELF'],'f.total_ttc','','&socidp='.$socidp,'align="right"',$sortfield);
- print_liste_field_titre($langs->trans('Received'),$_SERVER['PHP_SELF'],'am','','&socidp='.$socidp,'align="right"',$sortfield);
- print_liste_field_titre($langs->trans('Status'),$_SERVER['PHP_SELF'],'fk_statut,paye,am','','&socidp='.$socidp,'align="right"',$sortfield);
- print ' ';
-
- // Lignes des champs de filtre
- print '';
-
- if ($num > 0)
- {
- $var=True;
- $total=0;
- $totalrecu=0;
-
- while ($i < min($num,$limit))
+ if ($objp->df > 0 )
{
- $objp = $db->fetch_object($resql);
- $var=!$var;
-
- print '';
- print '| facid.'">'.img_object($langs->trans('ShowBill'),'bill').' ';
- print 'facid.'">'.$objp->facnumber.''.$objp->increment;
- if ($objp->datelimite < (time() - $conf->facture->client->warning_delay) && ! $objp->paye && $objp->fk_statut == 1 && ! $objp->am) print img_warning($langs->trans('Late'));
- print ' | ';
-
- if ($objp->df > 0 )
- {
- print '';
- $y = strftime('%Y',$objp->df);
- $m = strftime('%m',$objp->df);
- print strftime('%d',$objp->df);
- print ' ';
- print substr(strftime('%B',$objp->df),0,3).'';
- print ' ';
- print strftime('%Y',$objp->df).' | ';
- }
- else
- {
- print '!!! | ';
- }
- print ''.img_object($langs->trans('ShowCompany'),'company').' '.dolibarr_trunc($objp->nom,48).' | ';
- print ''.price($objp->total).' | ';
- print ''.price($objp->total_ttc).' | ';
- print ''.price($objp->am).' | ';
-
- // Affiche statut de la facture
- print '';
- print $facturestatic->LibStatut($objp->paye,$objp->fk_statut,5,$objp->am);
- print ' | ';
-
- print ' ';
- $total+=$objp->total;
- $total_ttc+=$objp->total_ttc;
- $totalrecu+=$objp->am;
- $i++;
+ print '';
+ $y = strftime('%Y',$objp->df);
+ $m = strftime('%m',$objp->df);
+ print strftime('%d',$objp->df);
+ print ' ';
+ print substr(strftime('%B',$objp->df),0,3).'';
+ print ' ';
+ print strftime('%Y',$objp->df).' | ';
}
-
- if (($offset + $num) <= $limit)
+ else
{
- // Print total
- print '';
- print '| '.$langs->trans('Total').' | ';
- print ''.price($total).' | ';
- print ''.price($total_ttc).' | ';
- print ''.price($totalrecu).' | ';
- print ' | ';
- print ' ';
+ print '!!! | ';
}
+ print ''.img_object($langs->trans('ShowCompany'),'company').' '.dolibarr_trunc($objp->nom,48).' | ';
+ print ''.price($objp->total).' | ';
+ print ''.price($objp->total_ttc).' | ';
+ print ''.price($objp->am).' | ';
+
+ // Affiche statut de la facture
+ print '';
+ print $facturestatic->LibStatut($objp->paye,$objp->fk_statut,5,$objp->am);
+ print ' | ';
+
+ print '';
+ $total+=$objp->total;
+ $total_ttc+=$objp->total_ttc;
+ $totalrecu+=$objp->am;
+ $i++;
}
- print ' ';
- $db->free($resql);
- }
- else
- {
- dolibarr_print_error($db);
+ if (($offset + $num) <= $limit)
+ {
+ // Print total
+ print ' ';
+ print '| '.$langs->trans('Total').' | ';
+ print ''.price($total).' | ';
+ print ''.price($total_ttc).' | ';
+ print ''.price($totalrecu).' | ';
+ print ' | ';
+ print ' ';
+ }
}
+
+ print ' ';
+ $db->free($resql);
+ }
+ else
+ {
+ dolibarr_print_error($db);
}
}
}
diff --git a/htdocs/discount.class.php b/htdocs/discount.class.php
index 2d86c490b8a..f8cf2707486 100644
--- a/htdocs/discount.class.php
+++ b/htdocs/discount.class.php
@@ -50,7 +50,7 @@ class DiscountAbsolute
/**
- * \brief Charge objet remiset depuis la base
+ * \brief Charge objet remise depuis la base
* \param rowid id du projet à charger
* \return int <0 si ko, =0 si non trouvé, >0 si ok
*/
@@ -91,5 +91,31 @@ class DiscountAbsolute
return -1;
}
}
+
+ /**
+ * \brief Link the discount to a particular invoice
+ * \param rowid Invoice id
+ * \return int <0 ko, >0 ok
+ */
+ function link_to_invoice($rowid)
+ {
+ dolibarr_syslog("Discount.class::link_to_invoice link discount ".$this->id." to invoice rowid=".$rowid);
+
+ $sql ="UPDATE ".MAIN_DB_PREFIX."societe_remise_except";
+ $sql.=" SET fk_facture = ".$rowid;
+ $sql.=" WHERE rowid = ".$this->id;
+ $resql = $this->db->query($sql);
+ if ($resql)
+ {
+ return 1;
+ }
+ else
+ {
+ $this->error=$this->db->error();
+ dolibarr_syslog("Discount.class::link_to_invoice ".$this->error." sql=".$sql);
+ return -1;
+ }
+ }
+
}
?>
diff --git a/htdocs/facture.class.php b/htdocs/facture.class.php
index d378be036b8..f4d3d649b50 100644
--- a/htdocs/facture.class.php
+++ b/htdocs/facture.class.php
@@ -63,7 +63,8 @@ class Facture extends CommonObject
var $note_public;
var $statut;
var $paye; // 1 si facture payée COMPLETEMENT, 0 sinon
- var $close_code; // Si mis a paye sans paiement complet, code qui justifie
+ var $fk_facture_source; // id facture source si facture de remplacement ou avoir
+ var $close_code; // abandon, replaced, avoir, discount_vat
var $close_note; // Commentaire si mis a paye sans paiement complet
var $propalid;
var $projetid;
@@ -77,7 +78,7 @@ class Facture extends CommonObject
// Pour board
var $nbtodo;
var $nbtodolate;
-
+
var $specimen;
var $error;
@@ -108,21 +109,21 @@ class Facture extends CommonObject
}
/**
- * \brief Création de la facture en base
- * \param user object utilisateur qui crée
+ * \brief Création de la facture en base
+ * \param user Object utilisateur qui crée
+ * \return int <0 si ko, >0 si ok
*/
function create($user)
{
global $langs,$conf,$mysoc;
// Nettoyage paramètres
+ if (! $this->type) $this->type = 0 ;
+ $this->ref_client=trim($this->ref_client);
$this->note=trim($this->note);
$this->note_public=trim($this->note_public);
- $this->ref_client=trim($this->ref_client);
if (! $this->remise) $this->remise = 0 ;
if (! $this->mode_reglement_id) $this->mode_reglement_id = 0;
-
- // On positionne en mode brouillon la facture
$this->brouillon = 1;
dolibarr_syslog("Facture::create");
@@ -132,6 +133,45 @@ class Facture extends CommonObject
$this->db->begin();
+ // Verification paramètres
+ if ($this->type == 1) // si remplacement
+ {
+ // Controle que facture source connue
+ if ($this->fk_facture_source <= 0)
+ {
+ $this->error=$langs->trans("ErrorFieldRequired",$langs->trans("InvoiceReplacement"));
+ $this->db->rollback();
+ return -10;
+ }
+
+ // Charge la facture source a remplacer
+ $facreplaced=new Facture($this->db);
+ $result=$facreplaced->fetch($this->fk_facture_source);
+ if ($result <= 0)
+ {
+ $this->error=$langs->trans("ErrorBadInvoice");
+ $this->db->rollback();
+ return -11;
+ }
+
+ // Controle que facture source non deja remplacee
+ $idreplacement=$facreplaced->getIdNextInvoice();
+ if ($idreplacement != 0)
+ {
+ $this->error=$langs->trans("ErrorInvoiceAlreadyReplaced",$facreplaced->ref);
+ $this->db->rollback();
+ return -12;
+ }
+
+ $result=$facreplaced->set_canceled($user,'replaced','');
+ if ($result < 0)
+ {
+ $this->error=$facreplaced->error." sql=".$sql;
+ $this->db->rollback();
+ return -13;
+ }
+ }
+
// Facture récurrente
if ($this->fac_rec > 0)
{
@@ -147,7 +187,7 @@ class Facture extends CommonObject
$this->amount = $_facrec->amount;
$this->remise_absolue = $_facrec->remise_absolue;
$this->remise_percent = $_facrec->remise_percent;
- $this->remise = $_facrec->remise;
+ $this->remise = $_facrec->remise;
}
// Definition de la date limite
@@ -162,19 +202,20 @@ class Facture extends CommonObject
$totalht = ($amount - $remise);
$sql = 'INSERT INTO '.MAIN_DB_PREFIX.'facture (';
- $sql.= ' facnumber, fk_soc, datec, amount, remise_absolue, remise_percent,';
+ $sql.= ' facnumber, type, fk_soc, datec, amount, remise_absolue, remise_percent,';
$sql.= ' datef,';
$sql.= ' note,';
$sql.= ' note_public,';
$sql.= ' ref_client,';
- $sql.= ' fk_user_author, fk_projet,';
- $sql.= ' fk_cond_reglement, fk_mode_reglement, date_lim_reglement, model_pdf) ';
- $sql.= " VALUES (";
- $sql.= "'$number','$socid', now(), '$totalht', '".$this->remise_absolue."'";
+ $sql.= ' fk_facture_source, fk_user_author, fk_projet,';
+ $sql.= ' fk_cond_reglement, fk_mode_reglement, date_lim_reglement, model_pdf)';
+ $sql.= ' VALUES (';
+ $sql.= "'$number', '".$this->type."', '$socid', now(), '$totalht', '".$this->remise_absolue."'";
$sql.= ",'".$this->remise_percent."', ".$this->db->idate($this->date);
$sql.= ",".($this->note?"'".addslashes($this->note)."'":"null");
$sql.= ",".($this->note_public?"'".addslashes($this->note_public)."'":"null");
$sql.= ",".($this->ref_client?"'".addslashes($this->ref_client)."'":"null");
+ $sql.= ",".($this->fk_facture_source?"'".addslashes($this->fk_facture_source)."'":"null");
$sql.= ",".$user->id;
$sql.= ",".($this->projetid?$this->projetid:"null");
$sql.= ','.$this->cond_reglement_id;
@@ -189,6 +230,7 @@ class Facture extends CommonObject
$sql = 'UPDATE '.MAIN_DB_PREFIX."facture SET facnumber='(PROV".$this->id.")' WHERE rowid=".$this->id;
$resql=$this->db->query($sql);
+ // Mise a jour lien avec propal ou commande
if ($resql && $this->id && $this->propalid)
{
$sql = 'INSERT INTO '.MAIN_DB_PREFIX.'fa_pr (fk_facture, fk_propal) VALUES ('.$this->id.','.$this->propalid.')';
@@ -301,6 +343,27 @@ class Facture extends CommonObject
}
+ /**
+ * \brief Renvoie nom clicable (avec eventuellement le picto)
+ * \param withpicto Inclut le picto dans le lien
+ * \param option Sur quoi pointe le lien
+ * \return string Chaine avec URL
+ */
+ function getNomUrl($withpicto=0,$option='')
+ {
+ global $langs;
+
+ $result='';
+
+ $lien = '';
+ $lienfin='';
+
+ if ($withpicto) $result.=($lien.img_object($langs->trans("ShowInvoice"),'bill').$lienfin.' ');
+ $result.=$lien.$this->ref.$lienfin;
+ return $result;
+ }
+
+
/**
* \brief Recupére l'objet facture et ses lignes de factures
* \param rowid id de la facture a récupérer
@@ -311,20 +374,21 @@ class Facture extends CommonObject
{
//dolibarr_syslog("Facture::Fetch rowid : $rowid, societe_id : $societe_id");
- $sql = 'SELECT f.fk_soc,f.facnumber,f.amount,f.tva,f.total,f.total_ttc,f.remise_percent,f.remise_absolue,f.remise';
- $sql .= ','.$this->db->pdate('f.datef').' as df, f.fk_projet';
- $sql .= ','.$this->db->pdate('f.date_lim_reglement').' as dlr';
- $sql .= ', f.note, f.note_public, f.fk_statut, f.paye, f.close_code, f.close_note, f.fk_user_author, f.model_pdf';
- $sql .= ', f.fk_mode_reglement, f.ref_client, p.code as mode_reglement_code, p.libelle as mode_reglement_libelle';
- $sql .= ', f.fk_cond_reglement, c.code as cond_reglement_code, c.libelle as cond_reglement_libelle, c.libelle_facture as cond_reglement_libelle_facture';
- $sql .= ', cf.fk_commande';
- $sql .= ' FROM '.MAIN_DB_PREFIX.'cond_reglement as c, '.MAIN_DB_PREFIX.'facture as f';
- $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as p ON f.fk_mode_reglement = p.id';
- $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'co_fa as cf ON cf.fk_facture = f.rowid';
- $sql .= ' WHERE f.rowid='.$rowid.' AND c.rowid = f.fk_cond_reglement';
+ $sql = 'SELECT f.facnumber,f.ref_client,f.type,f.fk_soc,f.amount,f.tva,f.total,f.total_ttc,f.remise_percent,f.remise_absolue,f.remise';
+ $sql.= ','.$this->db->pdate('f.datef').' as df, f.fk_projet';
+ $sql.= ','.$this->db->pdate('f.date_lim_reglement').' as dlr';
+ $sql.= ', f.note, f.note_public, f.fk_statut, f.paye, f.close_code, f.close_note, f.fk_user_author, f.model_pdf';
+ $sql.= ', f.fk_mode_reglement, p.code as mode_reglement_code, p.libelle as mode_reglement_libelle';
+ $sql.= ', f.fk_cond_reglement, c.code as cond_reglement_code, c.libelle as cond_reglement_libelle, c.libelle_facture as cond_reglement_libelle_facture';
+ $sql.= ', f.fk_facture_source';
+ $sql.= ', cf.fk_commande';
+ $sql.= ' FROM '.MAIN_DB_PREFIX.'cond_reglement as c, '.MAIN_DB_PREFIX.'facture as f';
+ $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as p ON f.fk_mode_reglement = p.id';
+ $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'co_fa as cf ON cf.fk_facture = f.rowid';
+ $sql.= ' WHERE f.rowid='.$rowid.' AND c.rowid = f.fk_cond_reglement';
if ($societe_id > 0)
{
- $sql .= ' AND f.fk_soc = '.$societe_id;
+ $sql.= ' AND f.fk_soc = '.$societe_id;
}
$result = $this->db->query($sql);
@@ -336,10 +400,11 @@ class Facture extends CommonObject
//print strftime('%Y%m%d%H%M%S',$obj->df).' '.$obj->df.' '.dolibarr_print_date($obj->df);
$this->id = $rowid;
- $this->datep = $obj->dp;
- $this->date = $obj->df;
$this->ref = $obj->facnumber;
$this->ref_client = $obj->ref_client;
+ $this->type = $obj->type;
+ $this->datep = $obj->dp;
+ $this->date = $obj->df;
$this->amount = $obj->amount;
$this->remise_percent = $obj->remise_percent;
$this->remise_absolue = $obj->remise_absolue;
@@ -361,6 +426,7 @@ class Facture extends CommonObject
$this->cond_reglement = $obj->cond_reglement_libelle;
$this->cond_reglement_facture = $obj->cond_reglement_libelle_facture;
$this->projetid = $obj->fk_projet;
+ $this->fk_facture_source = $obj->fk_facture_source;
$this->note = $obj->note;
$this->note_public = $obj->note_public;
$this->user_author = $obj->fk_user_author;
@@ -368,15 +434,14 @@ class Facture extends CommonObject
$this->commande_id = $obj->fk_commande;
$this->lignes = array();
-
if ($this->commande_id)
{
$sql = "SELECT ref";
$sql.= " FROM ".MAIN_DB_PREFIX."commande";
$sql.= " WHERE rowid = ".$this->commande_id;
-
+
$resqlcomm = $this->db->query($sql);
-
+
if ($resqlcomm)
{
$objc = $this->db->fetch_object($resqlcomm);
@@ -465,7 +530,7 @@ class Facture extends CommonObject
/**
- * \brief Ajout d'une ligne remise fixe dans la facture, en base
+ * \brief Ajout en base d'une ligne remise fixe en ligne de facture
* \param idremise Id de la remise fixe
* \return int >0 si ok, <0 si ko
*/
@@ -480,9 +545,15 @@ class Facture extends CommonObject
$remise=new DiscountAbsolute($this->db);
$result=$remise->fetch($idremise);
-
if ($result > 0)
{
+ if ($remise->fk_facture)
+ {
+ $this->error=$langs->trans("ErrorDiscountAlreadyUsed");
+ $this->db->rollback();
+ return -5;
+ }
+
$facligne=new FactureLigne($this->db);
$facligne->fk_facture=$this->id;
$facligne->fk_remise_except=$remise->id;
@@ -502,36 +573,46 @@ class Facture extends CommonObject
$facligne->total_tva = $tabprice[1];
$facligne->total_ttc = $tabprice[2];
- $result=$facligne->insert();
- if ($result > 0)
+ $lineid=$facligne->insert();
+ if ($lineid > 0)
{
$result=$this->update_price($this->id);
if ($result > 0)
{
+ // Crée lien entre remise et ligne de facture
+ $result=$remise->link_to_invoice($lineid);
+ if ($result < 0)
+ {
+ $this->error=$remise->error;
+ $this->db->rollback();
+ return -4;
+ }
+
$this->db->commit();
return 1;
}
else
{
- $this->db->rollback();
+ $this->error=$facligne->error;
+ $this->db->rollback();
return -1;
}
}
else
{
$this->error=$facligne->error;
- $this->db->rollback();
+ $this->db->rollback();
return -2;
}
}
else
{
$this->db->rollback();
- return -2;
+ return -3;
}
}
-
-
+
+
/**
* \brief Classe la facture dans un projet
* \param projid Id du projet dans lequel classer la facture
@@ -574,78 +655,92 @@ class Facture extends CommonObject
}
/**
- * \brief Supprime la facture
- * \param rowid id de la facture à supprimer
+ * \brief Supprime la facture
+ * \param rowid Id de la facture à supprimer
+ * \return int <0 si ko, >0 si ok
*/
function delete($rowid)
{
global $user,$langs,$conf;
+ dolibarr_syslog("Facture.class::delete rowid=".$rowid);
+
$this->db->begin();
- $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'facture_tva_sum WHERE fk_facture = '.$rowid;
- if ( $this->db->query( $sql) )
+ $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'facture_tva_sum WHERE fk_facture = '.$rowid;
+ if ($this->db->query($sql))
{
$sql = 'DELETE FROM '.MAIN_DB_PREFIX.'fa_pr WHERE fk_facture = '.$rowid;
- if ($this->db->query( $sql) )
+ if ($this->db->query($sql))
{
$sql = 'DELETE FROM '.MAIN_DB_PREFIX.'co_fa WHERE fk_facture = '.$rowid;
- if ($this->db->query( $sql) )
+ if ($this->db->query($sql))
{
- $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'facturedet WHERE fk_facture = '.$rowid;
- if ($this->db->query( $sql) )
+ // On désaffecte de la facture les remises liées
+ $sql = 'UPDATE '.MAIN_DB_PREFIX.'societe_remise_except';
+ $sql.= ' SET fk_facture = NULL WHERE fk_facture = '.$rowid;
+ if ($this->db->query($sql))
{
- // On désaffecte de la facture les remises liées
- $sql = 'UPDATE '.MAIN_DB_PREFIX.'societe_remise_except';
- $sql.= ' SET fk_facture = NULL WHERE fk_facture = '.$rowid;
- if ($this->db->query( $sql) )
+ $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'facturedet WHERE fk_facture = '.$rowid;
+ if ($this->db->query($sql))
{
- $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'facture WHERE rowid = '.$rowid.' AND fk_statut = 0';
- $resql=$this->db->query($sql) ;
-
- if ($resql)
- {
- // Appel des triggers
- include_once(DOL_DOCUMENT_ROOT . "/interfaces.class.php");
- $interface=new Interfaces($this->db);
- $result=$interface->run_triggers('BILL_DELETE',$this,$user,$langs,$conf);
- // Fin appel triggers
-
- $this->db->commit();
- return 1;
- }
- else
- {
- $this->db->rollback();
- return -6;
- }
- }
- else
- {
- $this->db->rollback();
- return -5;
- }
+ $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'facture WHERE rowid = '.$rowid;
+ $resql=$this->db->query($sql);
+ if ($resql)
+ {
+ // Appel des triggers
+ include_once(DOL_DOCUMENT_ROOT . "/interfaces.class.php");
+ $interface=new Interfaces($this->db);
+ $result=$interface->run_triggers('BILL_DELETE',$this,$user,$langs,$conf);
+ // Fin appel triggers
+
+ $this->db->commit();
+ return 1;
+ }
+ else
+ {
+ $this->error=$this->db->error()." sql=".$sql;
+ dolibarr_syslog("Facture.class::delete ".$this->error);
+ $this->db->rollback();
+ return -6;
+ }
+ }
+ else
+ {
+ $this->error=$this->db->error()." sql=".$sql;
+ dolibarr_syslog("Facture.class::delete ".$this->error);
+ $this->db->rollback();
+ return -4;
+ }
}
else
{
+ $this->error=$this->db->error()." sql=".$sql;
+ dolibarr_syslog("Facture.class::delete ".$this->error);
$this->db->rollback();
- return -4;
+ return -5;
}
}
else
{
+ $this->error=$this->db->error()." sql=".$sql;
+ dolibarr_syslog("Facture.class::delete ".$this->error);
$this->db->rollback();
return -3;
}
}
else
{
+ $this->error=$this->db->error()." sql=".$sql;
+ dolibarr_syslog("Facture.class::delete ".$this->error);
$this->db->rollback();
return -2;
}
}
else
{
+ $this->error=$this->db->error()." sql=".$sql;
+ dolibarr_syslog("Facture.class::delete ".$this->error);
$this->db->rollback();
return -1;
}
@@ -796,25 +891,48 @@ class Facture extends CommonObject
global $conf,$langs;
dolibarr_syslog("Facture.class.php::set_canceled rowid=".$this->id);
+
+ $this->db->begin();
+
$sql = 'UPDATE '.MAIN_DB_PREFIX.'facture SET';
$sql.= ' fk_statut=3';
if ($close_code) $sql.= ", close_code='".addslashes($close_code)."'";
if ($close_note) $sql.= ", close_note='".addslashes($close_note)."'";
$sql.= ' WHERE rowid = '.$this->id;
- $resql = $this->db->query($sql);
+ $resql = $this->db->query($sql);
if ($resql)
{
- $this->use_webcal=($conf->global->PHPWEBCALENDAR_BILLSTATUS=='always'?1:0);
+ // On désaffecte de la facture les remises liées
+ $sql = 'UPDATE '.MAIN_DB_PREFIX.'societe_remise_except';
+ $sql.= ' SET fk_facture = NULL WHERE fk_facture = '.$this->id;
+ $resql=$this->db->query($sql);
+ if ($resql)
+ {
+ $this->use_webcal=($conf->global->PHPWEBCALENDAR_BILLSTATUS=='always'?1:0);
- // Appel des triggers
- include_once(DOL_DOCUMENT_ROOT . "/interfaces.class.php");
- $interface=new Interfaces($this->db);
- $result=$interface->run_triggers('BILL_CANCEL',$this,$user,$langs,$conf);
- // Fin appel triggers
+ // Appel des triggers
+ include_once(DOL_DOCUMENT_ROOT . "/interfaces.class.php");
+ $interface=new Interfaces($this->db);
+ $result=$interface->run_triggers('BILL_CANCEL',$this,$user,$langs,$conf);
+ // Fin appel triggers
+
+ $this->db->commit();
+ return 1;
+ }
+ else
+ {
+ $this->error=$this->db->error()." sql=".$sql;
+ $this->db->rollback();
+ return -1;
+ }
+ }
+ else
+ {
+ $this->error=$this->db->error()." sql=".$sql;
+ $this->db->rollback();
+ return -2;
}
-
- return 1;
}
/**
@@ -836,7 +954,7 @@ class Facture extends CommonObject
// on vérifie si la facture est en numérotation provisoire
$facref = substr($this->ref, 1, 4);
-
+
if ($force_number)
{
$numfa = $force_number;
@@ -910,7 +1028,7 @@ class Facture extends CommonObject
{
// Ligne de remise
dolibarr_syslog("Facture.class::set_valid: recherche si remise ".$this->lignes[$i]->fk_remise_except." toujours dispo");
-
+
// On recherche si ligne de remise pas deja attribuée
$sql = 'SELECT fk_facture';
$sql.= ' FROM '.MAIN_DB_PREFIX.'societe_remise_except';
@@ -923,7 +1041,7 @@ class Facture extends CommonObject
if ($num >= 1)
{
dolibarr_syslog("Facture.class::set_valid: top ligne de remise ".$this->lignes[$i]->fk_remise_except." pour ligne de facture ".$this->lignes[$i]->rowid);
-
+
// On met à jour ligne de remise comme utilisée
$sql = 'UPDATE '.MAIN_DB_PREFIX.'societe_remise_except';
$sql.= ' SET fk_facture = '.$this->lignes[$i]->rowid;
@@ -931,7 +1049,7 @@ class Facture extends CommonObject
$resql=$this->db->query($sql);
if ($resql)
{
-
+
}
else
{
@@ -947,7 +1065,7 @@ class Facture extends CommonObject
$this->error=$langs->trans("InvoiceDiscountNotAvailable");
dolibarr_syslog("Facture.class::set_valid: Error ".$this->error);
break;
- }
+ }
}
else
{
@@ -969,7 +1087,7 @@ class Facture extends CommonObject
$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);
if ($resql)
{
@@ -996,7 +1114,7 @@ class Facture extends CommonObject
$soc=new Societe($this->db);
$soc->id = $this->socidp;
$result=$soc->set_as_client();
-
+
$this->ref = $numfa;
$this->use_webcal=($conf->global->PHPWEBCALENDAR_BILLSTATUS=='always'?1:0);
@@ -1017,7 +1135,7 @@ class Facture extends CommonObject
}
}
}
-
+
/**
*
*
@@ -1026,7 +1144,7 @@ class Facture extends CommonObject
{
$sql = "UPDATE ".MAIN_DB_PREFIX."facture SET fk_statut = 0";
$sql .= " WHERE rowid = $this->id;";
-
+
if ($this->db->query($sql) )
{
return 1;
@@ -1049,7 +1167,7 @@ class Facture extends CommonObject
{
$sql = "UPDATE ".MAIN_DB_PREFIX."facture SET model_pdf = '$modelpdf'";
$sql .= " WHERE rowid = $this->id AND fk_statut < 2 ;";
-
+
if ($this->db->query($sql) )
{
$this->modelpdf=$modelpdf;
@@ -1127,7 +1245,7 @@ class Facture extends CommonObject
// 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
+ // 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];
@@ -1157,7 +1275,7 @@ class Facture extends CommonObject
$ligne->subprice=$subprice;
$ligne->remise=$remise;
$ligne->date_start=$date_start;
- $ligne->date_end=$date_end;
+ $ligne->date_end=$date_end;
$ligne->ventil=$ventil;
$ligne->rang=-1;
$ligne->info_bits=$info_bits;
@@ -1166,12 +1284,12 @@ class Facture extends CommonObject
$ligne->total_tva=$total_tva;
$ligne->total_ttc=$total_ttc;
- $result=$ligne->insert();
+ $result=$ligne->insert();
if ($result > 0)
{
// Mise a jour informations denormalisees au niveau de la facture meme
$result=$this->update_price($facid);
- if ($result > 0)
+ if ($result > 0)
{
$this->db->commit();
return 1;
@@ -1213,7 +1331,7 @@ class Facture extends CommonObject
if ($this->brouillon)
{
$this->db->begin();
-
+
// Nettoyage paramètres
$remise_percent=price2num($remise_percent);
$qty=price2num($qty);
@@ -1223,7 +1341,7 @@ class Facture extends CommonObject
// 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
+ // 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];
@@ -1246,7 +1364,7 @@ class Facture extends CommonObject
$ligne=new FactureLigne($this->db);
$ligne->rowid=$rowid;
$ligne->fetch($rowid);
-
+
$ligne->desc=$desc;
$ligne->price=$price;
$ligne->qty=$qty;
@@ -1255,12 +1373,12 @@ class Facture extends CommonObject
$ligne->subprice=$subprice;
$ligne->remise=$remise;
$ligne->date_start=$date_start;
- $ligne->date_end=$date_end;
+ $ligne->date_end=$date_end;
$ligne->total_ht=$total_ht;
$ligne->total_tva=$total_tva;
$ligne->total_ttc=$total_ttc;
- $result=$ligne->update();
+ $result=$ligne->update();
if ($result > 0)
{
// Mise a jour info denormalisees au niveau facture
@@ -1282,16 +1400,45 @@ class Facture extends CommonObject
}
/**
- * \brief Supprime une ligne facture de la base
- * \param rowid id de la ligne de facture a supprimer
+ * \brief Supprime une ligne facture de la base
+ * \param rowid Id de la ligne de facture a supprimer
*/
function deleteline($rowid)
{
+ dolibarr_syslog("Facture.class::deleteline rowid=".$rowid." ".$this->brouillon);
+
if ($this->brouillon)
{
+ $this->db->begin();
+
+ // Libere remise liee a ligne de facture
+ $sql = 'UPDATE '.MAIN_DB_PREFIX.'societe_remise_except';
+ $sql.= ' SET fk_facture = NULL where fk_facture = '.$rowid;
+ $result = $this->db->query($sql);
+ if ($result < 0)
+ {
+ $this->error=$this->db->error();
+ dolibarr_syslog("Facture.class::deleteline Error ".$this->error);
+ $this->db->rollback();
+ return -1;
+ }
+
+ // Efface ligne de facture
$sql = 'DELETE FROM '.MAIN_DB_PREFIX.'facturedet WHERE rowid = '.$rowid;
- $result = $this->db->query( $sql);
- $this->update_price($this->id);
+ $result = $this->db->query($sql);
+ if ($result < 0)
+ {
+ $this->error=$this->db->error();
+ dolibarr_syslog("Facture.class::deleteline Error ".$this->error);
+ $this->db->rollback();
+ return -1;
+ }
+
+ $result=$this->update_price($this->id);
+
+ $this->db->commit();
+
+ return 1;
}
}
@@ -1522,6 +1669,50 @@ class Facture extends CommonObject
}
}
+ /**
+ * \brief Renvoie l'id de la facture qui la remplace
+ * \return int <0 si ko, 0 si aucune facture ne remplace, id facture sinon
+ */
+ function getIdNextInvoice()
+ {
+ $sql = 'SELECT rowid';
+ $sql.= ' FROM '.MAIN_DB_PREFIX.'facture';
+ $sql.= ' WHERE fk_facture_source = '.$this->id;
+ $resql=$this->db->query($sql);
+ if ($resql)
+ {
+ $obj = $this->db->fetch_object($resql);
+ if ($obj)
+ {
+ // Si il y en a
+ return $obj->rowid;
+ }
+ else
+ {
+ // Si aucune facture ne remplace
+ return 0;
+ }
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ /**
+ * \brief Retourne le libellé du type de facture
+ * \return string Libelle
+ */
+ function getLibType()
+ {
+ global $langs;
+ if ($this->type == 0) return $langs->trans("InvoiceStandard");
+ if ($this->type == 1) return $langs->trans("InvoiceReplacement");
+ if ($this->type == 2) return $langs->trans("InvoiceAvoir");
+ return $langs->trans("Unknown");
+ }
+
+
/**
* \brief Retourne le libellé du statut d'une facture (brouillon, validée, abandonnée, payée)
* \param mode 0=libellé long, 1=libellé court, 2=Picto + Libellé court, 3=Picto, 4=Picto + Libellé long
@@ -1859,7 +2050,7 @@ class Facture extends CommonObject
$ventilExportCompta++;
}
}
-
+
if ($ventilExportCompta <> 0)
{
return 1;
@@ -1869,8 +2060,8 @@ class Facture extends CommonObject
return 0;
}
}
-
-
+
+
/**
* \brief Renvoi si une facture peut etre supprimée complètement.
* La règle est la suivante:
@@ -1886,7 +2077,7 @@ class Facture extends CommonObject
$facref = substr($this->ref, 1, 4);
// Si facture non brouillon et non provisoire
- if ($facref != 'PROV' && $conf->compta->enabled && $conf->global->FACTURE_ENABLE_EDITDELETE)
+ if ($facref != 'PROV' && ! $conf->comptaexpert->enabled && $conf->global->FACTURE_ENABLE_EDITDELETE)
{
// On ne peut supprimer que la dernière facture validée
// pour ne pas avoir de trou dans la numérotation
@@ -1898,7 +2089,7 @@ class Facture extends CommonObject
{
$maxfacnumber = $this->db->fetch_row($resql);
}
-
+
$ventilExportCompta = $this->getVentilExportCompta();
// Si derniere facture et si non ventilée, on peut supprimer
@@ -1911,16 +2102,52 @@ class Facture extends CommonObject
{
return 1;
}
-
+
return 0;
}
-
-
- /**
- * \brief Créé une demande de prélèvement
+
+
+ /**
+ * \brief Renvoi liste des factures remplacables
+ * Statut validee + aucun paiement + non paye
+ * \param socid Id societe
+ * \return array Tableau des factures ($id => $ref)
+ */
+ function list_replacable_invoices($socid=0)
+ {
+ global $conf;
+
+ $return = array();
+
+ $sql = "SELECT f.rowid, f.facnumber";
+ $sql.= " FROM ".MAIN_DB_PREFIX."facture as f";
+ $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."paiement_facture as pf ON f.rowid = pf.fk_facture";
+ $sql.= " WHERE f.fk_statut = 1 AND f.paye = 0 AND pf.fk_paiement IS NULL";
+ if ($socid > 0) $sql.=" AND f.fk_soc = ".$socid;
+ $sql.= " ORDER BY f.facnumber";
+
+ dolibarr_syslog("Facture.class::list_replacable_invoices sq=$sql");
+ $resql=$this->db->query($sql);
+ if ($resql)
+ {
+ while ($obj=$this->db->fetch_object($resql))
+ {
+ $return[$obj->rowid]=$obj->facnumber;
+ }
+
+ return $return;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ /**
+ * \brief Créé une demande de prélèvement
* \param user Utilisateur créant la demande
* \return int <0 si ko, >0 si ok
- */
+ */
function demande_prelevement($user)
{
dolibarr_syslog("Facture::demande_prelevement $this->statut $this->paye $this->mode_reglement_id");
@@ -2299,7 +2526,7 @@ class FactureLigne
var $libelle; // Label produit
var $product_desc; // Description produit
-
+
/**
* \brief Constructeur d'objets ligne de facture
* \param DB handler d'accès base de donnée
@@ -2349,7 +2576,7 @@ class FactureLigne
$this->fk_code_ventilation = $objp->fk_code_ventilation;
$this->fk_export_compta = $objp->fk_export_compta;
$this->rang = $objp->rang;
-
+
$this->ref = $objp->product_ref;
$this->libelle = $objp->product_libelle;
$this->product_desc = $objp->product_desc;
@@ -2391,7 +2618,7 @@ class FactureLigne
return -1;
}
}
-
+
// Insertion dans base de la ligne
$sql = 'INSERT INTO '.MAIN_DB_PREFIX.'facturedet';
$sql.= ' (fk_facture, description, price, qty, tva_taux,';
@@ -2429,8 +2656,10 @@ class FactureLigne
$resql=$this->db->query($sql);
if ($resql)
{
+ $this->rowid=$this->db->last_insert_id(MAIN_DB_PREFIX.'facturedet');
+
$this->db->commit();
- return 1;
+ return $this->rowid;
}
else
{
@@ -2440,8 +2669,8 @@ class FactureLigne
return -2;
}
}
-
-
+
+
/**
* \brief Mise a jour de l'objet ligne de facture en base
* \return int <0 si ko, >0 si ok
@@ -2478,7 +2707,7 @@ class FactureLigne
if ($resql)
{
$this->db->commit();
- return 1;
+ return 1;
}
else
{
@@ -2488,7 +2717,7 @@ class FactureLigne
return -2;
}
}
-
+
/**
* \brief Mise a jour en base des champs total_xxx de ligne de facture
* \return int <0 si ko, >0 si ok
@@ -2510,7 +2739,7 @@ class FactureLigne
if ($resql)
{
$this->db->commit();
- return 1;
+ return 1;
}
else
{
@@ -2519,7 +2748,7 @@ class FactureLigne
$this->db->rollback();
return -2;
}
- }
+ }
}
?>
diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang
index 2789463247a..10956f8c8ee 100644
--- a/htdocs/langs/en_US/bills.lang
+++ b/htdocs/langs/en_US/bills.lang
@@ -8,6 +8,17 @@ BillsCustomersUnpayedForCompany=Unpayed customers' invoices for %s
BillsSuppliersUnpayed=Unpayed suppliers' invoices
BillsUnpayed=Unpayed
BillsStatistics=Invoices statistics
+InvoiceStandard=Standard invoice
+InvoiceStandardAsk=Standard invoice
+InvoiceStandardDesc=This kind of invoice is the common invoice.
+InvoiceReplacement=Replacement invoice. Must replace invoice with reference
+InvoiceReplacementAsk=Replacement invoice for following invoice
+InvoiceReplacementDesc=Replacement invoice is used to cancel and replace completely an invoice with no paiement already recevided. Reference of canceled invoice is required.
+InvoiceAvoir=Avoir invoice
+InvoiceAvoirAsk=Avoir invoice
+InvoiceAvoirDesc=La facture d'avoir est une facture négative destinée à compenser une facture comportant un montant supérieur à ce qui a été ou sera réellement payé (toutes causes possibles).
+ReplaceInvoice=Replace invoice %s
+ReplacedByInvoice=Replaced by invoice %s
CardBill=Invoice card
Invoice=Invoice
Invoices=Invoices
@@ -68,6 +79,8 @@ ErrorVATIntraNotConfigured=Intracommunautary VAT number not yet defined
ErrorNoPaiementModeConfigured=No paiment mode yet defined
ErrorCreateBankAccount=Creat a bank account then go to Setup panel of Invoice module to define paiement modes
ErrorBillNotFound=Invoice %s does not exists
+ErrorInvoiceAlreadyReplaced=Error, invoice %s has already been replaced
+ErrorDiscountAlreadyUsed=Error, discount already used
BillFrom=From
BillTo=Bill to
ActionsOnBill=Actions on invoice
@@ -99,6 +112,7 @@ ValidateBill=Validate invoice
NumberOfBills=Nb of invoices
NumberOfBillsByMonth=Nb of invoices by month
ShowBill=Show invoice
+ShowInvoice=Show invoice
ShowPayment=Show payment
File=File
AlreadyPayed=Already payed
diff --git a/htdocs/langs/fr_FR/bills.lang b/htdocs/langs/fr_FR/bills.lang
index 67eb3aa5532..b9012415c04 100644
--- a/htdocs/langs/fr_FR/bills.lang
+++ b/htdocs/langs/fr_FR/bills.lang
@@ -8,6 +8,17 @@ BillsCustomersUnpayedForCompany=Factures clients impay
BillsSuppliersUnpayed=Factures fournisseurs impayées
BillsUnpayed=Impayées
BillsStatistics=Statistiques factures
+InvoiceStandard=Facture standard
+InvoiceStandardAsk=Facture standard
+InvoiceStandardDesc=Ce type de facture est la facture traditionnelle. On l'appelle aussi facture de doit.
+InvoiceReplacement=Facture de remplacement
+InvoiceReplacementAsk=Facture de remplacement de la facture suivante
+InvoiceReplacementDesc=La facture de remplacement sert à annuler et remplacer une facture existante sur laquelle aucun paiement n'a encore eu lieu. La référence de la facture qui doit être annulée est obligatoire.
+InvoiceAvoir=Facture avoir
+InvoiceAvoirAsk=Facture avoir
+InvoiceAvoirDesc=La facture d'avoir est une facture négative destinée à compenser une facture comportant un montant supérieur à ce qui a été ou sera réellement payé (toutes causes possibles).
+ReplaceInvoice=Remplace la facture %s
+ReplacedByInvoice=Remplacée par la facture %s
CardBill=Fiche facture
Invoice=Facture
Invoices=Factures
@@ -68,6 +79,8 @@ ErrorVATIntraNotConfigured=Num
ErrorNoPaiementModeConfigured=Aucun mode de règlement défini
ErrorCreateBankAccount=Créer un compte bancaire puis aller dans la configuration du module facture pour définir les modes de règlement
ErrorBillNotFound=Facture %s inexistante
+ErrorInvoiceAlreadyReplaced=Erreur, la facture %s a déjà été remplacée
+ErrorDiscountAlreadyUsed=Erreur, la remise a déjà été attribuée
BillFrom=Émetteur
BillTo=Adressé à
ActionsOnBill=Actions sur la facture
@@ -99,6 +112,7 @@ ValidateBill=Valider facture
NumberOfBills=Nb de factures
NumberOfBillsByMonth=Nb de factures par mois
ShowBill=Afficher facture
+ShowInvoice=Afficher facture
ShowPayment=Afficher paiement
File=Fichier
AlreadyPayed=Déjà réglé
diff --git a/htdocs/lib/functions.inc.php b/htdocs/lib/functions.inc.php
index a84b3b2ab89..24b33232130 100644
--- a/htdocs/lib/functions.inc.php
+++ b/htdocs/lib/functions.inc.php
@@ -762,8 +762,8 @@ function img_help($usehelpcursor=1,$usealttitle=1)
$s =' theme.'/img/info.png" border="0"';
- if ($usealttitle) $s.=' alt="'.$langs->trans("Info").'" title="'.$langs->trans("Info");
- $s.='">';
+ if ($usealttitle) $s.=' alt="'.$langs->trans("Info").'" title="'.$langs->trans("Info").'"';
+ $s.='>';
return $s;
}
|
|