Browse Source

Merge branch 'new_numbering_module_supplier_payment' of
https://github.com/atm-ph/dolibarr into
atm-ph-new_numbering_module_supplier_payment

Conflicts:
htdocs/accountancy/admin/productaccount.php
htdocs/install/mysql/migration/3.9.0-4.0.0.sql

Laurent Destailleur 9 years ago
parent
commit
71a12824c9

+ 220 - 0
htdocs/admin/supplier_payment.php

@@ -0,0 +1,220 @@
+<?php
+/* Copyright (C) 2015  Juanjo Menent				<jmenent@2byte.es>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ *      \file       htdocs/admin/payment.php
+ *		\ingroup    facture
+ *		\brief      Page to setup invoices payments
+ */
+
+require '../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/fourn.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/fourn/class/paiementfourn.class.php';
+
+$langs->load("admin");
+$langs->load("errors");
+$langs->load('other');
+$langs->load('bills');
+
+if (! $user->admin) accessforbidden();
+
+$action = GETPOST('action','alpha');
+$value = GETPOST('value','alpha');
+$label = GETPOST('label','alpha');
+$scandir = GETPOST('scandir','alpha');
+
+
+/*
+ * Actions
+ */
+
+if ($action == 'updateMask')
+{
+    $maskconstsupplierpayment=GETPOST('maskconstsupplierpayment','alpha');
+    $masksupplierpayment=GETPOST('masksupplierpayment','alpha');
+    if ($maskconstsupplierpayment) $res = dolibarr_set_const($db,$maskconstsupplierpayment,$masksupplierpayment,'chaine',0,'',$conf->entity);
+
+    if (! $res > 0) $error++;
+
+    if (! $error)
+    {
+        setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
+    }
+    else
+    {
+        setEventMessages($langs->trans("Error"), null, 'errors');
+    }
+}
+
+    if ($action == 'setmod')
+{
+    dolibarr_set_const($db, "SUPPLIER_PAYMENT_ADDON",$value,'chaine',0,'',$conf->entity);
+}
+
+/*
+ * View
+ */
+
+$dirmodels=array_merge(array('/'),(array) $conf->modules_parts['models']);
+
+llxHeader("",$langs->trans("SupplierPaymentSetup"),'EN:Supplier_Payment_Configuration|FR:Configuration_module_paiement_fournisseur');
+
+$form=new Form($db);
+
+
+$linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php">'.$langs->trans("BackToModuleList").'</a>';
+print load_fiche_titre($langs->trans("SupplierPaymentSetup"),$linkback,'title_setup');
+
+print "<br />";
+
+$head = supplierorder_admin_prepare_head();
+dol_fiche_head($head, 'supplierpayment', $langs->trans("SupplierPayment"), 0, 'invoice');
+
+/*
+ *  Numbering module
+ */
+
+print load_fiche_titre($langs->trans("SupplierPaymentsNumberingModule"));
+
+print '<table class="noborder" width="100%">';
+print '<tr class="liste_titre">';
+print '<td>'.$langs->trans("Name").'</td>';
+print '<td>'.$langs->trans("Description").'</td>';
+print '<td class="nowrap">'.$langs->trans("Example").'</td>';
+print '<td align="center" width="60">'.$langs->trans("Status").'</td>';
+print '<td align="center" width="16">'.$langs->trans("ShortInfo").'</td>';
+print '</tr>'."\n";
+
+clearstatcache();
+
+foreach ($dirmodels as $reldir)
+{
+    $dir = dol_buildpath($reldir."core/modules/supplier_payment/");
+    if (is_dir($dir))
+    {
+        $handle = opendir($dir);
+        if (is_resource($handle))
+        {
+            $var=true;
+
+            while (($file = readdir($handle))!==false)
+            {
+                if (! is_dir($dir.$file) || (substr($file, 0, 1) <> '.' && substr($file, 0, 3) <> 'CVS'))
+                {
+                    $filebis = $file;
+                    $classname = preg_replace('/\.php$/','',$file);
+                    // For compatibility
+                    if (! is_file($dir.$filebis))
+                    {
+                        $filebis = $file."/".$file.".modules.php";
+                        $classname = "mod_supplier_payment_".$file;
+                    }
+                    // Check if there is a filter on country
+                    preg_match('/\-(.*)_(.*)$/',$classname,$reg);
+                    if (! empty($reg[2]) && $reg[2] != strtoupper($mysoc->country_code)) continue;
+
+                    $classname = preg_replace('/\-.*$/','',$classname);
+                    if (! class_exists($classname) && is_readable($dir.$filebis) && (preg_match('/mod_/',$filebis) || preg_match('/mod_/',$classname)) && substr($filebis, dol_strlen($filebis)-3, 3) == 'php')
+                    {
+                        // Charging the numbering class
+                        require_once $dir.$filebis;
+
+                        $module = new $classname($db);
+
+                        // Show modules according to features level
+                        if ($module->version == 'development'  && $conf->global->MAIN_FEATURES_LEVEL < 2) continue;
+                        if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) continue;
+
+                        if ($module->isEnabled())
+                        {
+                            $var = !$var;
+                            print '<tr '.$bc[$var].'><td width="100">';
+                            echo preg_replace('/\-.*$/','',preg_replace('/mod_supplier_payment_/','',preg_replace('/\.php$/','',$file)));
+                            print "</td><td>\n";
+
+                            print $module->info();
+
+                            print '</td>';
+
+                            // Show example of numbering module
+                            print '<td class="nowrap">';
+                            $tmp=$module->getExample();
+                            if (preg_match('/^Error/',$tmp)) print '<div class="error">'.$langs->trans($tmp).'</div>';
+                            elseif ($tmp=='NotConfigured') print $langs->trans($tmp);
+                            else print $tmp;
+                            print '</td>'."\n";
+
+                            print '<td align="center">';
+                            //print "> ".$conf->global->SUPPLIER_PAYMENT_ADDON." - ".$file;
+                            if ($conf->global->SUPPLIER_PAYMENT_ADDON == $file || $conf->global->SUPPLIER_PAYMENT_ADDON.'.php' == $file)
+                            {
+                                print img_picto($langs->trans("Activated"),'switch_on');
+                            }
+                            else
+                            {
+                                print '<a href="'.$_SERVER["PHP_SELF"].'?action=setmod&value='.preg_replace('/\.php$/','',$file).'&scandir='.$module->scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"),'switch_off').'</a>';
+                            }
+                            print '</td>';
+
+                            $payment=new PaiementFourn($db);
+                            $payment->initAsSpecimen();
+
+                            // Example
+                            $htmltooltip='';
+                            $htmltooltip.=''.$langs->trans("Version").': <b>'.$module->getVersion().'</b><br>';
+                            $nextval=$module->getNextValue($mysoc,$payment);
+                            if ("$nextval" != $langs->trans("NotAvailable")) {  // Keep " on nextval
+                                    $htmltooltip.=$langs->trans("NextValue").': ';
+                                if ($nextval) {
+                                    if (preg_match('/^Error/',$nextval) || $nextval=='NotConfigured')
+                                        $nextval = $langs->trans($nextval);
+                                    $htmltooltip.=$nextval.'<br>';
+                                } else {
+                                    $htmltooltip.=$langs->trans($module->error).'<br>';
+                                }
+                            }
+
+                            print '<td align="center">';
+                            print $form->textwithpicto('',$htmltooltip,1,0);
+
+                            if ($conf->global->PAYMENT_ADDON.'.php' == $file)  // If module is the one used, we show existing errors
+                            {
+                                if (! empty($module->error)) dol_htmloutput_mesg($module->error,'','error',1);
+                            }
+
+                            print '</td>';
+
+                            print "</tr>\n";
+
+                        }
+                    }
+                }
+            }
+            closedir($handle);
+        }
+    }
+}
+
+print '</table>';
+
+dol_fiche_end();
+
+
+llxFooter();
+
+$db->close();

+ 5 - 0
htdocs/core/lib/fourn.lib.php

@@ -183,6 +183,11 @@ function supplierorder_admin_prepare_head()
 	$head[$h][1] = $langs->trans("SuppliersInvoice");
 	$head[$h][2] = 'invoice';
 	$h++;
+	
+	$head[$h][0] = DOL_URL_ROOT."/admin/supplier_payment.php";
+	$head[$h][1] = $langs->trans("SuppliersPayment");
+	$head[$h][2] = 'supplierpayment';
+	$h++;
 
 	complete_head_from_modules($conf,$langs,null,$head,$h,'supplierorder_admin');
 

+ 140 - 0
htdocs/core/modules/supplier_payment/mod_supplier_payment_brodator.php

@@ -0,0 +1,140 @@
+<?php
+/* Copyright (C) 2015      Juanjo Menent	    <jmenent@2byte.es>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * or see http://www.gnu.org/
+ */
+
+/**
+ * \file       htdocs/core/modules/supplier_payment/mod_supplier_payment_brodator.php
+ * \ingroup    supplier_payment
+ * \brief      File containing class for numbering module Brodator
+ */
+
+require_once DOL_DOCUMENT_ROOT .'/core/modules/supplier_payment/modules_supplier_payment.php';
+
+
+/**
+ *	Class to manage customer payment numbering rules Ant
+ */
+class mod_supplier_payment_brodator extends ModeleNumRefPayments
+{
+	var $version='dolibarr';		// 'development', 'experimental', 'dolibarr'
+	var $error = '';
+	var $nom = 'Brodator';
+
+
+    /**
+     *  Renvoi la description du modele de numerotation
+     *
+     *  @return     string      Texte descripif
+     */
+	function info()
+    {
+    	global $conf,$langs;
+
+		$langs->load("bills");
+
+		$form = new Form($this->db);
+
+		$texte = $langs->trans('GenericNumRefModelDesc')."<br>\n";
+		$texte.= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
+		$texte.= '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+		$texte.= '<input type="hidden" name="action" value="updateMask">';
+		$texte.= '<input type="hidden" name="maskconstsupplierpayment" value="SUPPLIER_PAYMENT_BRODATOR_MASK">';
+		$texte.= '<table class="nobordernopadding" width="100%">';
+
+		$tooltip=$langs->trans("GenericMaskCodes",$langs->transnoentities("Order"),$langs->transnoentities("Order"));
+		$tooltip.=$langs->trans("GenericMaskCodes2");
+		$tooltip.=$langs->trans("GenericMaskCodes3");
+		$tooltip.=$langs->trans("GenericMaskCodes4a",$langs->transnoentities("Order"),$langs->transnoentities("Order"));
+		$tooltip.=$langs->trans("GenericMaskCodes5");
+
+		// Parametrage du prefix
+		$texte.= '<tr><td>'.$langs->trans("Mask").':</td>';
+		$texte.= '<td align="right">'.$form->textwithpicto('<input type="text" class="flat" size="24" name="masksupplierpayment" value="'.$conf->global->SUPPLIER_PAYMENT_BRODATOR_MASK.'">',$tooltip,1,1).'</td>';
+
+		$texte.= '<td align="left" rowspan="2">&nbsp; <input type="submit" class="button" value="'.$langs->trans("Modify").'" name="Button"></td>';
+
+		$texte.= '</tr>';
+
+		$texte.= '</table>';
+		$texte.= '</form>';
+
+		return $texte;
+    }
+
+    /**
+     *  Renvoi un exemple de numerotation
+     *
+     *  @return     string      Example
+     */
+    function getExample()
+    {
+     	global $conf,$langs,$mysoc;
+
+    	$old_code_client=$mysoc->code_client;
+    	$mysoc->code_client='CCCCCCCCCC';
+     	$numExample = $this->getNextValue($mysoc,'');
+		$mysoc->code_client=$old_code_client;
+
+		if (! $numExample)
+		{
+			$numExample = $langs->trans('NotConfigured');
+		}
+		return $numExample;
+    }
+
+	/**
+	 * 	Return next free value
+	 *
+	 *  @param	Societe		$objsoc     Object thirdparty
+	 *  @param  Object		$object		Object we need next value for
+	 *  @return string      			Value if KO, <0 if KO
+	 */
+    function getNextValue($objsoc,$object)
+    {
+		global $db,$conf;
+
+		require_once DOL_DOCUMENT_ROOT .'/core/lib/functions2.lib.php';
+
+		// We get cursor rule
+		$mask=$conf->global->SUPPLIER_PAYMENT_BRODATOR_MASK;
+
+		if (! $mask)
+		{
+			$this->error='NotConfigured';
+			return 0;
+		}
+
+		$numFinal=get_next_value($db,$mask,'paiementfourn','ref','',$objsoc,$object->datepaye);
+
+		return  $numFinal;
+	}
+
+
+	/**
+	 *  Return next free value
+	 *
+	 *  @param	Societe		$objsoc     Object third party
+	 * 	@param	string		$objforref	Object for number to search
+	 *  @return string      			Next free value
+     */
+    function commande_get_num($objsoc,$objforref)
+    {
+        return $this->getNextValue($objsoc,$objforref);
+    }
+
+}
+

+ 150 - 0
htdocs/core/modules/supplier_payment/mod_supplier_payment_bronan.php

@@ -0,0 +1,150 @@
+<?php
+/* Copyright (C) 2015      Juanjo Menent	    <jmenent@2byte.es>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * or see http://www.gnu.org/
+ */
+
+/**
+ * \file       htdocs/core/modules/payment/mod_payment_bronan.php
+ * \ingroup    supplier_payment
+ * \brief      File containing class for numbering module Bronan
+ */
+
+require_once DOL_DOCUMENT_ROOT .'/core/modules/supplier_payment/modules_supplier_payment.php';
+
+/**
+ *	Class to manage customer payment numbering rules Cicada
+ */
+class mod_supplier_payment_bronan extends ModeleNumRefPayments
+{
+	var $version='dolibarr';		// 'development', 'experimental', 'dolibarr'
+	var $prefix='SPAY';
+	var $error='';
+	var $nom='Bronan';
+
+
+    /**
+     *  Return description of numbering module
+     *
+     *  @return     string      Text with description
+     */
+    function info()
+    {
+    	global $langs;
+      	return $langs->trans("SimpleNumRefModelDesc",$this->prefix);
+    }
+
+
+	/**
+	 *  Renvoi un exemple de numerotation
+	 *
+	 *  @return     string      Example
+	 */
+	function getExample()
+	{
+		return $this->prefix."0501-0001";
+	}
+
+
+	/**
+	 *  Test si les numeros deje en vigueur dans la base ne provoquent pas de
+	 *  de conflits qui empechera cette numerotation de fonctionner.
+	 *
+	 *  @return     boolean     false si conflit, true si ok
+	 */
+	function canBeActivated()
+	{
+		global $conf,$langs,$db;
+
+		$payyymm=''; $max='';
+
+		$posindice=9;
+		$sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max";
+		$sql.= " FROM ".MAIN_DB_PREFIX."paiementfourn";
+		$sql.= " WHERE ref LIKE '".$this->prefix."____-%'";
+		$sql.= " AND entity = ".$conf->entity;
+
+		$resql=$db->query($sql);
+		if ($resql)
+		{
+			$row = $db->fetch_row($resql);
+			if ($row) { $payyymm = substr($row[0],0,6); $max=$row[0]; }
+		}
+		if ($payyymm && ! preg_match('/'.$this->prefix.'[0-9][0-9][0-9][0-9]/i',$payyymm))
+		{
+			$langs->load("errors");
+			$this->error=$langs->trans('ErrorNumRefModel', $max);
+			return false;
+		}
+
+		return true;
+	}
+
+	/**
+	 * 	Return next free value
+	 *
+	 *  @param	Societe		$objsoc     Object thirdparty
+	 *  @param  Object		$object		Object we need next value for
+	 *  @return string      			Value if KO, <0 if KO
+	 */
+	function getNextValue($objsoc,$object)
+	{
+		global $db,$conf;
+
+		// D'abord on recupere la valeur max
+		$posindice=10;
+		$sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max";
+		$sql.= " FROM ".MAIN_DB_PREFIX."paiementfourn";
+		$sql.= " WHERE ref like '".$this->prefix."____-%'";
+		$sql.= " AND entity = ".$conf->entity;
+
+		$resql=$db->query($sql);
+		if ($resql)
+		{
+			$obj = $db->fetch_object($resql);
+			if ($obj) $max = intval($obj->max);
+			else $max=0;
+		}
+		else
+		{
+			dol_syslog(__METHOD__, LOG_DEBUG);
+			return -1;
+		}
+
+		//$date=time();
+		$date=$object->datepaye;
+		$yymm = strftime("%y%m",$date);
+
+    	if ($max >= (pow(10, 4) - 1)) $num=$max+1;	// If counter > 9999, we do not format on 4 chars, we take number as it is
+    	else $num = sprintf("%04s",$max+1);
+
+		dol_syslog(__METHOD__." return ".$this->prefix.$yymm."-".$num);
+		return $this->prefix.$yymm."-".$num;
+	}
+
+
+	/**
+	 *  Return next free value
+	 *
+	 *  @param	Societe		$objsoc     Object third party
+	 * 	@param	string		$objforref	Object for number to search
+	 *  @return string      			Next free value
+	 */
+	function payment_get_num($objsoc,$objforref)
+	{
+		return $this->getNextValue($objsoc,$objforref);
+	}
+
+}

+ 101 - 0
htdocs/core/modules/supplier_payment/modules_supplier_payment.php

@@ -0,0 +1,101 @@
+<?php
+/* Copyright (C) 2015      Juanjo Menent	    <jmenent@2byte.es>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * or see http://www.gnu.org/
+ */
+
+/**
+ *  \class      ModeleNumRefPayments
+ *  \brief      Payment numbering references mother class
+ */
+
+abstract class ModeleNumRefPayments
+{
+	var $error='';
+
+	/**
+	 *	Return if a module can be used or not
+	 *
+	 *	@return		boolean     true if module can be used
+	 */
+	function isEnabled()
+	{
+		return true;
+	}
+
+	/**
+	 *	Return the default description of numbering module
+	 *
+	 *	@return     string      Texte descripif
+	 */
+	function info()
+	{
+		global $langs;
+		$langs->load("bills");
+		return $langs->trans("NoDescription");
+	}
+
+	/**
+	 *	Return numbering example
+	 *
+	 *	@return     string      Example
+	 */
+	function getExample()
+	{
+		global $langs;
+		$langs->load("bills");
+		return $langs->trans("NoExample");
+	}
+
+	/**
+	 *  Test if the existing numbers in the database do not cause conflicts that would prevent this numbering run.
+	 *
+	 *	@return     boolean     false si conflit, true si ok
+	 */
+	function canBeActivated()
+	{
+		return true;
+	}
+
+	/**
+	 *	Returns the next value
+	 *
+	 *	@param	Societe		$objsoc     Object thirdparty
+	 *	@param	Object		$object		Object we need next value for
+	 *	@return	string      Valeur
+	 */
+	function getNextValue($objsoc,$object)
+	{
+		global $langs;
+		return $langs->trans("NotAvailable");
+	}
+
+	/**
+	 *	Returns the module numbering version
+	 *
+	 *	@return     string      Value
+	 */
+	function getVersion()
+	{
+		global $langs;
+		$langs->load("admin");
+
+		if ($this->version == 'development') return $langs->trans("VersionDevelopment");
+		if ($this->version == 'experimental') return $langs->trans("VersionExperimental");
+		if ($this->version == 'dolibarr') return DOL_VERSION;
+		if ($this->version) return $this->version;
+		return $langs->trans("NotAvailable");
+	}
+}

+ 116 - 4
htdocs/fourn/class/paiementfourn.class.php

@@ -74,7 +74,7 @@ class PaiementFourn extends Paiement
 	{
 	    $error=0;
 	    
-		$sql = 'SELECT p.rowid, p.datep as dp, p.amount, p.statut, p.fk_bank,';
+		$sql = 'SELECT p.rowid, p.ref, p.entity, p.datep as dp, p.amount, p.statut, p.fk_bank,';
 		$sql.= ' c.code as paiement_code, c.libelle as paiement_type,';
 		$sql.= ' p.num_paiement, p.note, b.fk_account';
 		$sql.= ' FROM '.MAIN_DB_PREFIX.'c_paiement as c, '.MAIN_DB_PREFIX.'paiementfourn as p';
@@ -95,7 +95,8 @@ class PaiementFourn extends Paiement
 			{
 				$obj = $this->db->fetch_object($resql);
 				$this->id             = $obj->rowid;
-				$this->ref            = $obj->rowid;
+				$this->ref            = $obj->ref;
+				$this->entity         = $obj->entity;
 				$this->date           = $this->db->jdate($obj->dp);
 				$this->numero         = $obj->num_paiement;
 				$this->bank_account   = $obj->fk_account;
@@ -149,11 +150,12 @@ class PaiementFourn extends Paiement
 
 		if ($this->total <> 0) // On accepte les montants negatifs
 		{
+			$ref = $this->getNextNumRef('');
 			$now=dol_now();
 
 			$sql = 'INSERT INTO '.MAIN_DB_PREFIX.'paiementfourn (';
-			$sql.= 'datec, datep, amount, fk_paiement, num_paiement, note, fk_user_author, fk_bank)';
-			$sql.= " VALUES ('".$this->db->idate($now)."',";
+			$sql.= 'ref, entity, datec, datep, amount, fk_paiement, num_paiement, note, fk_user_author, fk_bank)';
+			$sql.= " VALUES ('".$this->db->escape($ref)."', ".$conf->entity.", '".$this->db->idate($now)."',";
 			$sql.= " '".$this->db->idate($this->datepaye)."', '".$this->total."', ".$this->paiementid.", '".$this->num_paiement."', '".$this->db->escape($this->note)."', ".$user->id.", 0)";
 
 			dol_syslog("PaiementFourn::create", LOG_DEBUG);
@@ -513,4 +515,114 @@ class PaiementFourn extends Paiement
 		if ($withpicto != 2) $result.=$link.$text.$linkend;
 		return $result;
 	}
+	
+	/**
+	 *  Initialise an instance with random values.
+	 *  Used to build previews or test instances.
+	 *	id must be 0 if object instance is a specimen.
+	 *
+	 *	@param	string		$option		''=Create a specimen invoice with lines, 'nolines'=No lines
+	 *  @return	void
+	 */
+	function initAsSpecimen($option='')
+	{
+		global $user,$langs,$conf;
+
+		$now=dol_now();
+		$arraynow=dol_getdate($now);
+		$nownotime=dol_mktime(0, 0, 0, $arraynow['mon'], $arraynow['mday'], $arraynow['year']);
+
+		// Initialize parameters
+		$this->id=0;
+		$this->ref = 'SPECIMEN';
+		$this->specimen=1;
+		$this->facid = 1;
+		$this->datepaye = $nownotime;
+	}
+	
+	/**
+	 *      Return next reference of supplier invoice not already used (or last reference)
+	 *      according to numbering module defined into constant SUPPLIER_PAYMENT_ADDON
+	 *
+	 *      @param	   Societe		$soc		object company
+	 *      @param     string		$mode		'next' for next value or 'last' for last value
+	 *      @return    string					free ref or last ref
+	 */
+	function getNextNumRef($soc,$mode='next')
+	{
+		global $conf, $db, $langs;
+		$langs->load("bills");
+
+		// Clean parameters (if not defined or using deprecated value)
+		if (empty($conf->global->SUPPLIER_PAYMENT_ADDON)) $conf->global->SUPPLIER_PAYMENT_ADDON='mod_supplier_payment_bronan';
+		else if ($conf->global->SUPPLIER_PAYMENT_ADDON=='brodator') $conf->global->SUPPLIER_PAYMENT_ADDON='mod_supplier_payment_brodator';
+		else if ($conf->global->SUPPLIER_PAYMENT_ADDON=='bronan') $conf->global->SUPPLIER_PAYMENT_ADDON='mod_supplier_payment_bronan';
+
+		if (! empty($conf->global->SUPPLIER_PAYMENT_ADDON))
+		{
+			$mybool=false;
+
+			$file = $conf->global->SUPPLIER_PAYMENT_ADDON.".php";
+			$classname = $conf->global->SUPPLIER_PAYMENT_ADDON;
+
+			// Include file with class
+			$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
+
+			foreach ($dirmodels as $reldir) {
+
+				$dir = dol_buildpath($reldir."core/modules/supplier_payment/");
+
+				// Load file with numbering class (if found)
+				if (is_file($dir.$file) && is_readable($dir.$file))
+				{
+					$mybool |= include_once $dir . $file;
+				}
+			}
+
+			// For compatibility
+			if (! $mybool)
+			{
+				$file = $conf->global->SUPPLIER_PAYMENT_ADDON.".php";
+				$classname = "mod_supplier_payment_".$conf->global->SUPPLIER_PAYMENT_ADDON;
+				$classname = preg_replace('/\-.*$/','',$classname);
+				// Include file with class
+				foreach ($conf->file->dol_document_root as $dirroot)
+				{
+					$dir = $dirroot."/core/modules/supplier_payment/";
+
+					// Load file with numbering class (if found)
+					if (is_file($dir.$file) && is_readable($dir.$file)) {
+						$mybool |= include_once $dir . $file;
+					}
+				}
+			}
+
+			if (! $mybool)
+			{
+				dol_print_error('',"Failed to include file ".$file);
+				return '';
+			}
+
+			$obj = new $classname();
+			$numref = "";
+			$numref = $obj->getNextValue($soc,$this);
+
+			/**
+			 * $numref can be empty in case we ask for the last value because if there is no invoice created with the
+			 * set up mask.
+			 */
+			if ($mode != 'last' && !$numref) {
+				dol_print_error($db,"SupplierPayment::getNextNumRef ".$obj->error);
+				return "";
+			}
+
+			return $numref;
+		}
+		else
+		{
+			$langs->load("errors");
+			print $langs->trans("Error")." ".$langs->trans("ErrorModuleSetupNotComplete");
+			return "";
+		}
+	}
 }

+ 12 - 11
htdocs/install/mysql/migration/3.9.0-4.0.0.sql

@@ -112,26 +112,28 @@ INSERT INTO llx_c_format_cards (rowid, code, name, paper_size, orientation, metr
 
 ALTER TABLE llx_extrafields ADD COLUMN ishidden integer DEFAULT 0;
 
-CREATE TABLE IF NOT EXISTS llx_multicurrency 
+
+ALTER TABLE llx_paiementfourn ADD COLUMN ref varchar(30) AFTER rowid;
+ALTER TABLE llx_paiementfourn ADD COLUMN entity integer AFTER ref;
+
+
+CREATE TABLE llx_multicurrency 
 ( 
 	rowid integer AUTO_INCREMENT PRIMARY KEY, 
 	date_create datetime DEFAULT NULL, 
 	code varchar(255) DEFAULT NULL, 
 	name varchar(255) DEFAULT NULL, 
-	entity integer DEFAULT NULL,
-	fk_user integer DEFAULT NULL,
-	KEY code (code)
+	entity integer DEFAULT 1,
+	fk_user integer DEFAULT NULL
 ) ENGINE=innodb;
 
-CREATE TABLE IF NOT EXISTS llx_multicurrency_rate 
+CREATE TABLE llx_multicurrency_rate 
 ( 
 	rowid integer AUTO_INCREMENT PRIMARY KEY, 
 	date_sync datetime DEFAULT NULL,  
-	rate double NOT NULL DEFAULT '0', 
-	fk_multicurrency integer NOT NULL DEFAULT '0', 
-	entity integer NOT NULL DEFAULT '0', 
-	KEY fk_multicurrency (fk_multicurrency), 
-	KEY entity (entity) 
+	rate double NOT NULL DEFAULT 0, 
+	fk_multicurrency integer NOT NULL, 
+	entity integer NOT NULL DEFAULT 1
 ) ENGINE=innodb;
 
 ALTER TABLE llx_societe ADD COLUMN fk_multicurrency integer;
@@ -210,5 +212,4 @@ ALTER TABLE llx_propaldet ADD COLUMN multicurrency_subprice double(24,8) DEFAULT
 ALTER TABLE llx_propaldet ADD COLUMN multicurrency_total_ht double(24,8) DEFAULT 0;
 ALTER TABLE llx_propaldet ADD COLUMN multicurrency_total_tva double(24,8) DEFAULT 0;
 ALTER TABLE llx_propaldet ADD COLUMN multicurrency_total_ttc double(24,8) DEFAULT 0;
- 
  

+ 3 - 3
htdocs/install/mysql/tables/llx_multicurrency.sql

@@ -1,5 +1,6 @@
 -- ========================================================================
 -- Copyright (C) 2016		Pierre-Henry Favre		<phf@atm-consulting.fr>
+-- Copyright (C) 2016       Laurent Destailleur     <eldy@users.sourceforge.net>
 --
 -- This program is free software; you can redistribute it and/or modify
 -- it under the terms of the GNU General Public License as published by
@@ -22,7 +23,6 @@ CREATE TABLE llx_multicurrency
 	date_create datetime DEFAULT NULL, 
 	code varchar(255) DEFAULT NULL, 
 	name varchar(255) DEFAULT NULL, 
-	entity integer DEFAULT NULL,
-	fk_user integer DEFAULT NULL,
-	KEY code (code)
+	entity integer DEFAULT 1,
+	fk_user integer DEFAULT NULL
 ) ENGINE=innodb;

+ 4 - 5
htdocs/install/mysql/tables/llx_multicurrency_rate.sql

@@ -1,5 +1,6 @@
 -- ========================================================================
 -- Copyright (C) 2016		Pierre-Henry Favre		<phf@atm-consulting.fr>
+-- Copyright (C) 2016       Laurent Destailleur     <eldy@users.sourceforge.net>
 --
 -- This program is free software; you can redistribute it and/or modify
 -- it under the terms of the GNU General Public License as published by
@@ -20,9 +21,7 @@ CREATE TABLE llx_multicurrency_rate
 ( 
 	rowid integer AUTO_INCREMENT PRIMARY KEY, 
 	date_sync datetime DEFAULT NULL,  
-	rate double NOT NULL DEFAULT '0', 
-	fk_multicurrency integer NOT NULL DEFAULT '0', 
-	entity integer NOT NULL DEFAULT '0', 
-	KEY fk_multicurrency (fk_multicurrency), 
-	KEY entity (entity) 
+	rate double NOT NULL DEFAULT 0, 
+	fk_multicurrency integer NOT NULL, 
+	entity integer DEFAULT 1 
 ) ENGINE=innodb;

+ 2 - 0
htdocs/install/mysql/tables/llx_paiementfourn.sql

@@ -20,6 +20,8 @@
 create table llx_paiementfourn
 (
   rowid             integer AUTO_INCREMENT PRIMARY KEY,
+  ref				varchar(30),
+  entity			integer DEFAULT 1,
   tms               timestamp,
   datec             datetime,          -- date de creation de l'enregistrement
   datep             datetime,          -- date de paiement

+ 0 - 24
htdocs/langs/fr_FR/bills.lang

@@ -186,11 +186,7 @@ ShowInvoice=Afficher facture
 ShowInvoiceReplace=Afficher facture de remplacement
 ShowInvoiceAvoir=Afficher facture d'avoir
 ShowInvoiceDeposit=Afficher facture d'acompte
-<<<<<<< HEAD
 ShowInvoiceSituation=Afficher facture de situation
-=======
-ShowInvoiceSituation=Show situation invoice
->>>>>>> refs/remotes/origin/3.9
 ShowPayment=Afficher règlement
 AlreadyPaid=Déjà réglé
 AlreadyPaidBack=Déjà remboursé
@@ -306,16 +302,10 @@ RelatedSupplierInvoices=Factures fournisseurs liées
 LatestRelatedBill=Dernière facture en rapport
 WarningBillExist=Attention, une ou plusieurs factures existent déjà
 MergingPDFTool=Outil de fusion de PDF
-<<<<<<< HEAD
-ListOfPreviousSituationInvoices=Liste des précédentes factures de situation
-ListOfNextSituationInvoices=Liste des factures suivantes de situation
-=======
 AmountPaymentDistributedOnInvoice=Montant paiement affecté à la facture
 PaymentNote=Note du paiement
 ListOfPreviousSituationInvoices=List of previous situation invoices
 ListOfNextSituationInvoices=List of next situation invoices
->>>>>>> refs/remotes/origin/3.9
-
 # PaymentConditions
 PaymentConditionShortRECEP=À réception
 PaymentConditionRECEP=À réception de facture
@@ -424,11 +414,7 @@ NoteListOfYourUnpaidInvoices=Remarque: Cette liste ne contient que les factures
 RevenueStamp=Timbre fiscal
 YouMustCreateInvoiceFromThird=Cette option n'est disponible que lorsqu'on accède à la création de facture depuis l'onglet "Client" d'un Tiers.
 PDFCrabeDescription=Modèle de facture PDF complet (modèle recommandé par défaut)
-<<<<<<< HEAD
-PDFCrevetteDescription=Modèle de facture PDF pour les factures de situations
-=======
 PDFCrevetteDescription=Invoice PDF template Crevette. A complete invoice template for invoice situation
->>>>>>> refs/remotes/origin/3.9
 TerreNumRefModelDesc1=Renvoie le numéro sous la forme %syymm-nnnn pour les factures et factures de remplacement, %syymm-nnnn pour les avoirs et %syymm-nnnn pour les acomptes où yy est l'année, mm le mois et nnnn un compteur séquentiel sans rupture et sans remise à 0
 MarsNumRefModelDesc1=Renvoie le numéro sous la forme %syymm-nnnn pour les factures, %syymm-nnnn pour les factures de remplacement, %syymm-nnnn pour les acomptes et %syymm-nnnn pour les avoirs où yy est l'année, mm le mois et nnnn un compteur séquentiel sans rupture et sans remise à 0
 TerreNumRefModelError=Une facture commençant par $syymm existe déjà et est incompatible avec cet modèle de numérotation. Supprimez-la ou renommez-la pour activer ce module.
@@ -459,15 +445,6 @@ CantBeLessThanMinPercent=La progression ne peut être inférieure à la valeur d
 NoSituations=Pas de situations ouvertes
 InvoiceSituationLast=Dernière facture
 PDFCrevetteSituationNumber=Situation N°%s
-<<<<<<< HEAD
-PDFCrevetteSituationOrderTitle=Commande d'origine
-PDFCrevetteSituationInvoiceTitle=Facture de situation
-PDFCrevetteSituationInvoiceLineDecompte=Facture de situation - DECOMPTE
-PDFCrevetteSituationInvoiceLine=Situation N°%s : Fact. N°%s au %s
-TotalSituationInvoice=Total Situtation
-invoiceLineProgressError=La progression de la ligne de situation ne peut être égale ou supérieure à la ligne de situation suivante
-updatePriceNextInvoiceErrorUpdateline=Erreur de mise à jour d'un prix sur la facture : %s
-=======
 PDFCrevetteSituationInvoiceLineDecompte=Situation invoice - COUNT
 PDFCrevetteSituationInvoiceTitle=Situation invoice
 PDFCrevetteDescription=Invoice PDF template Crevette. A complete invoice template for invoice situation
@@ -475,4 +452,3 @@ PDFCrevetteSituationInvoiceLine=Situation N°%s : Inv. N°%s on %s
 TotalSituationInvoice=Total situation
 invoiceLineProgressError=Invoice line progress can't be egal or upper the next invoice line
 updatePriceNextInvoiceErrorUpdateline=Error : update price on invoice line : %s
->>>>>>> refs/remotes/origin/3.9

+ 27 - 3
test/phpunit/SqlTest.php

@@ -143,13 +143,16 @@ class SqlTest extends PHPUnit_Framework_TestCase
 
         $listofsqldir = array(DOL_DOCUMENT_ROOT.'/install/mysql/tables', DOL_DOCUMENT_ROOT.'/install/mysql/migration');
 
-        foreach ($listofsqldir as $dir) {
+        foreach ($listofsqldir as $dir) 
+        {
             print 'Process dir '.$dir."\n";
             $filesarray = scandir($dir);
-            foreach($filesarray as $key => $file) {
+        
+            foreach($filesarray as $key => $file) 
+            {
                 if (! preg_match('/\.sql$/',$file))
                     continue;
-
+                    
                 print 'Check sql file '.$file."\n";
                 $filecontent=file_get_contents($dir.'/'.$file);
 
@@ -164,6 +167,27 @@ class SqlTest extends PHPUnit_Framework_TestCase
                 $result=strpos($filecontent,'ON DELETE CASCADE');
                 print __METHOD__." Result for checking we don't have 'ON DELETE CASCADE' = ".$result."\n";
                 $this->assertTrue($result===false, 'Found ON DELETE CASCADE into '.$file.'. Bad.');
+                
+                if ($dir == DOL_DOCUMENT_ROOT.'/install/mysql/migration')
+                {
+                    // Test for migration files only
+
+                }
+                else
+                {
+                    if (preg_match('/\.key\.sql$/',$file))
+                    {                
+                        // Test for files key files only
+                    
+                    }
+                    else
+                    {
+                        // Test for files non key files only
+                        $result=(strpos($filecontent,'KEY ') && strpos($filecontent,'PRIMARY KEY ') == 0);
+                        print __METHOD__." Result for checking we don't have ' KEY ' instead of a sql file to create index = ".$result."\n";
+                        $this->assertTrue($result===false, 'Found KEY into '.$file.'. Bad.');
+                    }
+                }
             }
         }