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

Conflicts:
	htdocs/core/lib/functionsnumtoword.lib.php
This commit is contained in:
Laurent Destailleur
2020-08-06 02:52:54 +02:00

View File

@@ -13,125 +13,142 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
* or see http://www.gnu.org/ * or see https://www.gnu.org/
*/ */
/** /**
* \file htdocs/core/lib/functionsnumbertoword.lib.php * \file htdocs/core/lib/functionsnumtoword.lib.php
* \brief A set of functions for Dolibarr * \brief A set of functions for Dolibarr
* This file contains all frequently used functions. * This file contains all frequently used functions.
*/ */
/** /**
* Function to return number in text. * Function to return a number into a text.
* May use module NUMBERWORDS if found.
* *
* * @param float $num Number to convert (must be a numeric value, like reported by price2num())
* @param float $num Number to convert
* @param Translate $langs Language * @param Translate $langs Language
* @param boolean $currency 0=number to translate | 1=currency to translate * @param boolean $currency 0=number to translate | 1=currency to translate
* @param boolean $centimes 0=no centimes | 1=centimes to translate * @param boolean $centimes 0=no cents/centimes | 1=there is cents/centimes to translate
* @return string|false Text of the number * @return string|false Text of the number
*/ */
function dol_convertToWord($num, $langs, $currency = false, $centimes = false) function dol_convertToWord($num, $langs, $currency = false, $centimes = false)
{ {
global $conf; global $conf;
$num = str_replace(array(',', ' '), '', trim($num)); //$num = str_replace(array(',', ' '), '', trim($num)); This should be useless since $num MUST be a php numeric value
if (! $num) { if (!$num) {
return false; return false;
} }
if ($centimes && strlen($num) == 1) { if ($centimes && strlen($num) == 1) {
$num = $num*10; $num = $num * 10;
}
$TNum = explode('.', $num);
$num = (int) $TNum[0];
$words = array();
$list1 = array(
'',
$langs->transnoentitiesnoconv('one'),
$langs->transnoentitiesnoconv('two'),
$langs->transnoentitiesnoconv('three'),
$langs->transnoentitiesnoconv('four'),
$langs->transnoentitiesnoconv('five'),
$langs->transnoentitiesnoconv('six'),
$langs->transnoentitiesnoconv('seven'),
$langs->transnoentitiesnoconv('eight'),
$langs->transnoentitiesnoconv('nine'),
$langs->transnoentitiesnoconv('ten'),
$langs->transnoentitiesnoconv('eleven'),
$langs->transnoentitiesnoconv('twelve'),
$langs->transnoentitiesnoconv('thirteen'),
$langs->transnoentitiesnoconv('fourteen'),
$langs->transnoentitiesnoconv('fifteen'),
$langs->transnoentitiesnoconv('sixteen'),
$langs->transnoentitiesnoconv('seventeen'),
$langs->transnoentitiesnoconv('eighteen'),
$langs->transnoentitiesnoconv('nineteen')
);
$list2 = array(
'',
$langs->transnoentitiesnoconv('ten'),
$langs->transnoentitiesnoconv('twenty'),
$langs->transnoentitiesnoconv('thirty'),
$langs->transnoentitiesnoconv('forty'),
$langs->transnoentitiesnoconv('fifty'),
$langs->transnoentitiesnoconv('sixty'),
$langs->transnoentitiesnoconv('seventy'),
$langs->transnoentitiesnoconv('eighty'),
$langs->transnoentitiesnoconv('ninety'),
$langs->transnoentitiesnoconv('hundred')
);
$list3 = array(
'',
$langs->transnoentitiesnoconv('thousand'),
$langs->transnoentitiesnoconv('million'),
$langs->transnoentitiesnoconv('billion'),
$langs->transnoentitiesnoconv('trillion'),
$langs->transnoentitiesnoconv('quadrillion')
);
$num_length = strlen($num);
$levels = (int) (($num_length + 2) / 3);
$max_length = $levels * 3;
$num = substr('00' . $num, -$max_length);
$num_levels = str_split($num, 3);
$nboflevels = count($num_levels);
for ($i = 0; $i < $nboflevels; $i++) {
$levels--;
$hundreds = (int) ($num_levels[$i] / 100);
$hundreds = ($hundreds ? ' ' . $list1[$hundreds] . ' '.$langs->transnoentities('hundred') . ( $hundreds == 1 ? '' : 's' ) . ' ': '');
$tens = (int) ($num_levels[$i] % 100);
$singles = '';
if ( $tens < 20 ) {
$tens = ($tens ? ' ' . $list1[$tens] . ' ' : '' );
} else {
$tens = (int) ($tens / 10);
$tens = ' ' . $list2[$tens] . ' ';
$singles = (int) ($num_levels[$i] % 10);
$singles = ' ' . $list1[$singles] . ' ';
}
$words[] = $hundreds . $tens . $singles . ( ( $levels && ( int ) ( $num_levels[$i] ) ) ? ' ' . $list3[$levels] . ' ' : '' );
} //end for loop
$commas = count($words);
if ($commas > 1) {
$commas = $commas - 1;
}
$concatWords = implode(' ', $words);
// Delete multi whitespaces
$concatWords = trim(preg_replace('/[ ]+/', ' ', $concatWords));
if(!empty($currency)) {
$concatWords .= ' '.$currency;
} }
// If we need to write cents call again this function for cents if (!empty($conf->global->MAIN_MODULE_NUMBERWORDS)) {
if(!empty($TNum[1])) { if ($currency) {
if(!empty($currency)) $concatWords .= ' '.$langs->transnoentities('and'); $type = 1;
$concatWords .= ' '.dol_convertToWord($TNum[1], $langs, $currency, true); } else {
if(!empty($currency)) $concatWords .= ' '.$langs->transnoentities('centimes'); $type = 0;
}
$concatWords = $langs->getLabelFromNumber($num, $type);
return $concatWords;
} else {
$TNum = explode('.', $num);
$num = (int) $TNum[0];
$words = array();
$list1 = array(
'',
$langs->transnoentitiesnoconv('one'),
$langs->transnoentitiesnoconv('two'),
$langs->transnoentitiesnoconv('three'),
$langs->transnoentitiesnoconv('four'),
$langs->transnoentitiesnoconv('five'),
$langs->transnoentitiesnoconv('six'),
$langs->transnoentitiesnoconv('seven'),
$langs->transnoentitiesnoconv('eight'),
$langs->transnoentitiesnoconv('nine'),
$langs->transnoentitiesnoconv('ten'),
$langs->transnoentitiesnoconv('eleven'),
$langs->transnoentitiesnoconv('twelve'),
$langs->transnoentitiesnoconv('thirteen'),
$langs->transnoentitiesnoconv('fourteen'),
$langs->transnoentitiesnoconv('fifteen'),
$langs->transnoentitiesnoconv('sixteen'),
$langs->transnoentitiesnoconv('seventeen'),
$langs->transnoentitiesnoconv('eighteen'),
$langs->transnoentitiesnoconv('nineteen')
);
$list2 = array(
'',
$langs->transnoentitiesnoconv('ten'),
$langs->transnoentitiesnoconv('twenty'),
$langs->transnoentitiesnoconv('thirty'),
$langs->transnoentitiesnoconv('forty'),
$langs->transnoentitiesnoconv('fifty'),
$langs->transnoentitiesnoconv('sixty'),
$langs->transnoentitiesnoconv('seventy'),
$langs->transnoentitiesnoconv('eighty'),
$langs->transnoentitiesnoconv('ninety'),
$langs->transnoentitiesnoconv('hundred')
);
$list3 = array(
'',
$langs->transnoentitiesnoconv('thousand'),
$langs->transnoentitiesnoconv('million'),
$langs->transnoentitiesnoconv('billion'),
$langs->transnoentitiesnoconv('trillion'),
$langs->transnoentitiesnoconv('quadrillion')
);
$num_length = strlen($num);
$levels = (int) (($num_length + 2) / 3);
$max_length = $levels * 3;
$num = substr('00'.$num, -$max_length);
$num_levels = str_split($num, 3);
$nboflevels = count($num_levels);
for ($i = 0; $i < $nboflevels; $i++) {
$levels--;
$hundreds = (int) ($num_levels[$i] / 100);
$hundreds = ($hundreds ? ' '.$list1[$hundreds].' '.$langs->transnoentities('hundred').($hundreds == 1 ? '' : 's').' ' : '');
$tens = (int) ($num_levels[$i] % 100);
$singles = '';
if ($tens < 20) {
$tens = ($tens ? ' '.$list1[$tens].' ' : '');
} else {
$tens = (int) ($tens / 10);
$tens = ' '.$list2[$tens].' ';
$singles = (int) ($num_levels[$i] % 10);
$singles = ' '.$list1[$singles].' ';
}
$words[] = $hundreds.$tens.$singles.(($levels && (int) ($num_levels[$i])) ? ' '.$list3[$levels].' ' : '');
} //end for loop
$commas = count($words);
if ($commas > 1) {
$commas = $commas - 1;
}
$concatWords = implode(' ', $words);
// Delete multi whitespaces
$concatWords = trim(preg_replace('/[ ]+/', ' ', $concatWords));
if (!empty($currency)) {
$concatWords .= ' '.$currency;
}
// If we need to write cents call again this function for cents
$decimalpart = $TNum[1];
$decimalpart = preg_replace('/0+$/', '', $decimalpart);
if ($decimalpart) {
if (!empty($currency)) $concatWords .= ' '.$langs->transnoentities('and');
$concatWords .= ' '.dol_convertToWord($decimalpart, $langs, '', true);
if (!empty($currency)) $concatWords .= ' '.$langs->transnoentities('centimes');
}
return $concatWords;
} }
return $concatWords;
} }
@@ -150,81 +167,82 @@ function dolNumberToWord($numero, $langs, $numorcurrency = 'number')
if ($numero < 0) $numero *= -1; if ($numero < 0) $numero *= -1;
if ($numero >= 1000000000001) if ($numero >= 1000000000001)
return -1; return -1;
// Get 2 decimals to cents, another functions round or truncate
$strnumber = number_format($numero, 10);
$len=strlen($strnumber);
for ($i=0; $i<$len; $i++)
{
if ($strnumber[$i]=='.') {
$parte_decimal = $strnumber[$i+1].$strnumber[$i+2];
break;
}
}
/*In dolibarr 3.6.2 (my current version) doesn't have $langs->default and // Get 2 decimals to cents, another functions round or truncate
in case exist why ask $lang like a parameter?*/ $strnumber = number_format($numero, 10);
if (((is_object($langs) && $langs->default == 'es_MX') || (! is_object($langs) && $langs == 'es_MX')) && $numorcurrency == 'currency') $len = strlen($strnumber);
{ for ($i = 0; $i < $len; $i++)
if ($numero>=1 && $numero<2) { {
return ("UN PESO ".$parte_decimal." / 100 M.N."); if ($strnumber[$i] == '.') {
} $parte_decimal = $strnumber[$i + 1].$strnumber[$i + 2];
elseif ($numero>=0 && $numero<1){ break;
return ("CERO PESOS ".$parte_decimal." / 100 M.N.");
}
elseif ($numero>=1000000 && $numero<1000001){
return ("UN MILL&OacuteN DE PESOS ".$parte_decimal." / 100 M.N.");
}
elseif ($numero>=1000000000000 && $numero<1000000000001){
return ("UN BILL&OacuteN DE PESOS ".$parte_decimal." / 100 M.N.");
}
else {
$entexto ="";
$number = $numero;
if ($number >= 1000000000){
$CdMMillon = (int) ($numero / 100000000000);
$numero = $numero - $CdMMillon * 100000000000;
$DdMMillon = (int) ($numero / 10000000000);
$numero = $numero - $DdMMillon * 10000000000;
$UdMMillon = (int) ($numero / 1000000000);
$numero = $numero - $UdMMillon * 1000000000;
$entexto .= hundreds2text($CdMMillon, $DdMMillon, $UdMMillon);
$entexto .= " MIL ";
} }
if ($number >= 1000000){ }
$CdMILLON = (int) ($numero / 100000000);
$numero = $numero - $CdMILLON * 100000000; /*In dolibarr 3.6.2 (my current version) doesn't have $langs->default and
$DdMILLON = (int) ($numero / 10000000); in case exist why ask $lang like a parameter?*/
$numero = $numero - $DdMILLON * 10000000; if (((is_object($langs) && $langs->default == 'es_MX') || (!is_object($langs) && $langs == 'es_MX')) && $numorcurrency == 'currency')
$udMILLON = (int) ($numero / 1000000); {
$numero = $numero - $udMILLON * 1000000; if ($numero >= 1 && $numero < 2) {
$entexto .= hundreds2text($CdMILLON, $DdMILLON, $udMILLON); return ("UN PESO ".$parte_decimal." / 100 M.N.");
if (!$CdMMillon && !$DdMMillon && !$UdMMillon && !$CdMILLON && !$DdMILLON && $udMILLON==1)
$entexto .= " MILL&OacuteN ";
else
$entexto .= " MILLONES ";
} }
if ($number >= 1000) { elseif ($numero >= 0 && $numero < 1) {
$cdm = (int) ($numero / 100000); return ("CERO PESOS ".$parte_decimal." / 100 M.N.");
$numero = $numero - $cdm * 100000; }
$ddm = (int) ($numero / 10000); elseif ($numero >= 1000000 && $numero < 1000001) {
$numero = $numero - $ddm * 10000; return ("UN MILL&OacuteN DE PESOS ".$parte_decimal." / 100 M.N.");
$udm = (int) ($numero / 1000); }
$numero = $numero - $udm * 1000; elseif ($numero >= 1000000000000 && $numero < 1000000000001) {
$entexto .= hundreds2text($cdm, $ddm, $udm); return ("UN BILL&OacuteN DE PESOS ".$parte_decimal." / 100 M.N.");
if ($cdm || $ddm || $udm) }
else {
$entexto = "";
$number = $numero;
if ($number >= 1000000000) {
$CdMMillon = (int) ($numero / 100000000000);
$numero = $numero - $CdMMillon * 100000000000;
$DdMMillon = (int) ($numero / 10000000000);
$numero = $numero - $DdMMillon * 10000000000;
$UdMMillon = (int) ($numero / 1000000000);
$numero = $numero - $UdMMillon * 1000000000;
$entexto .= hundreds2text($CdMMillon, $DdMMillon, $UdMMillon);
$entexto .= " MIL "; $entexto .= " MIL ";
}
if ($number >= 1000000) {
$CdMILLON = (int) ($numero / 100000000);
$numero = $numero - $CdMILLON * 100000000;
$DdMILLON = (int) ($numero / 10000000);
$numero = $numero - $DdMILLON * 10000000;
$udMILLON = (int) ($numero / 1000000);
$numero = $numero - $udMILLON * 1000000;
$entexto .= hundreds2text($CdMILLON, $DdMILLON, $udMILLON);
if (!$CdMMillon && !$DdMMillon && !$UdMMillon && !$CdMILLON && !$DdMILLON && $udMILLON == 1)
$entexto .= " MILL&OacuteN ";
else
$entexto .= " MILLONES ";
}
if ($number >= 1000) {
$cdm = (int) ($numero / 100000);
$numero = $numero - $cdm * 100000;
$ddm = (int) ($numero / 10000);
$numero = $numero - $ddm * 10000;
$udm = (int) ($numero / 1000);
$numero = $numero - $udm * 1000;
$entexto .= hundreds2text($cdm, $ddm, $udm);
if ($cdm || $ddm || $udm)
$entexto .= " MIL ";
}
$c = (int) ($numero / 100);
$numero = $numero - $c * 100;
$d = (int) ($numero / 10);
$u = (int) $numero - $d * 10;
$entexto .= hundreds2text($c, $d, $u);
if (!$cdm && !$ddm && !$udm && !$c && !$d && !$u && $number > 1000000)
$entexto .= " DE";
$entexto .= " PESOS ".$parte_decimal." / 100 M.N.";
} }
$c = (int) ($numero / 100); return $entexto;
$numero = $numero - $c * 100;
$d = (int) ($numero / 10);
$u = (int) $numero - $d * 10;
$entexto .= hundreds2text($c, $d, $u);
if (!$cdm && !$ddm && !$udm && !$c && !$d && !$u && $number>1000000)
$entexto .= " DE";
$entexto .= " PESOS ".$parte_decimal." / 100 M.N.";
} }
return $entexto;
}
} }
/** /**
@@ -237,40 +255,40 @@ function dolNumberToWord($numero, $langs, $numorcurrency = 'number')
*/ */
function hundreds2text($hundreds, $tens, $units) function hundreds2text($hundreds, $tens, $units)
{ {
if ($hundreds==1 && $tens==0 && $units==0){ if ($hundreds == 1 && $tens == 0 && $units == 0) {
return "CIEN"; return "CIEN";
} }
$centenas = array("CIENTO","DOSCIENTOS","TRESCIENTOS","CUATROCIENTOS","QUINIENTOS","SEISCIENTOS","SETECIENTOS","OCHOCIENTOS","NOVECIENTOS"); $centenas = array("CIENTO", "DOSCIENTOS", "TRESCIENTOS", "CUATROCIENTOS", "QUINIENTOS", "SEISCIENTOS", "SETECIENTOS", "OCHOCIENTOS", "NOVECIENTOS");
$decenas = array("","","TREINTA ","CUARENTA ","CINCUENTA ","SESENTA ","SETENTA ","OCHENTA ","NOVENTA "); $decenas = array("", "", "TREINTA ", "CUARENTA ", "CINCUENTA ", "SESENTA ", "SETENTA ", "OCHENTA ", "NOVENTA ");
$veintis = array("VEINTE","VEINTIUN","VEINTID&OacuteS","VEINTITR&EacuteS","VEINTICUATRO","VEINTICINCO","VEINTIS&EacuteIS","VEINTISIETE","VEINTIOCHO","VEINTINUEVE"); $veintis = array("VEINTE", "VEINTIUN", "VEINTID&OacuteS", "VEINTITR&EacuteS", "VEINTICUATRO", "VEINTICINCO", "VEINTIS&EacuteIS", "VEINTISIETE", "VEINTIOCHO", "VEINTINUEVE");
$diecis = array("DIEZ","ONCE","DOCE","TRECE","CATORCE","QUINCE","DIECIS&EacuteIS","DIECISIETE","DIECIOCHO","DIECINUEVE"); $diecis = array("DIEZ", "ONCE", "DOCE", "TRECE", "CATORCE", "QUINCE", "DIECIS&EacuteIS", "DIECISIETE", "DIECIOCHO", "DIECINUEVE");
$unidades = array("UN","DOS","TRES","CUATRO","CINCO","SEIS","SIETE","OCHO","NUEVE"); $unidades = array("UN", "DOS", "TRES", "CUATRO", "CINCO", "SEIS", "SIETE", "OCHO", "NUEVE");
$entexto = ""; $entexto = "";
if ($hundreds!=0){ if ($hundreds != 0) {
$entexto .= $centenas[$hundreds-1]; $entexto .= $centenas[$hundreds - 1];
} }
if ($tens>2){ if ($tens > 2) {
if ($hundreds!=0) $entexto .= " "; if ($hundreds != 0) $entexto .= " ";
$entexto .= $decenas[$tens-1]; $entexto .= $decenas[$tens - 1];
if ($units!=0){ if ($units != 0) {
$entexto .= " Y "; $entexto .= " Y ";
$entexto .= $unidades[$units-1]; $entexto .= $unidades[$units - 1];
} }
return $entexto; return $entexto;
} }
elseif ($tens==2){ elseif ($tens == 2) {
if ($hundreds!=0) $entexto .= " "; if ($hundreds != 0) $entexto .= " ";
$entexto .= " ".$veintis[$units]; $entexto .= " ".$veintis[$units];
return $entexto; return $entexto;
} }
elseif ($tens==1){ elseif ($tens == 1) {
if ($hundreds!=0) $entexto .= " "; if ($hundreds != 0) $entexto .= " ";
$entexto .= $diecis[$units]; $entexto .= $diecis[$units];
return $entexto; return $entexto;
} }
if ($units!=0) { if ($units != 0) {
if ($hundreds!=0 || $tens!=0) $entexto .= " "; if ($hundreds != 0 || $tens != 0) $entexto .= " ";
$entexto .= $unidades[$units-1]; $entexto .= $unidades[$units - 1];
} }
return $entexto; return $entexto;
} }