dolibarr/htdocs/core/lib/functionsnumtoword.lib.php

307 lines
10 KiB
PHP
Raw Permalink Normal View History

2024-09-06 20:28:06 +08:00
<?php
/* Copyright (C) 2015 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2015 Víctor Ortiz Pérez <victor@accett.com.mx>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
*
* 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 <https://www.gnu.org/licenses/>.
* or see https://www.gnu.org/
*/
/**
* \file htdocs/core/lib/functionsnumtoword.lib.php
* \brief A set of functions for Dolibarr
* This file contains all frequently used functions.
*/
/**
* 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 Translate $langs Language
* @param string $currency ''=number to translate | 'XX'=currency code to use into text
* @param boolean $centimes false=no cents/centimes | true=there is cents/centimes
* @return string|false Text of the number
*/
function dol_convertToWord($num, $langs, $currency = '', $centimes = false)
{
global $conf;
//$num = str_replace(array(',', ' '), '', trim($num)); This should be useless since $num MUST be a php numeric value
if (!$num) {
return false;
}
if ($centimes && strlen((string) $num) == 1) {
$num *= 10;
}
if (isModEnabled('numberwords')) {
if ($currency) {
$type = '1';
} else {
$type = '0';
}
$concatWords = $langs->getLabelFromNumber($num, $type);
return $concatWords;
} else {
$TNum = explode('.', (string) $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((string) $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) ((int) $num_levels[$i] / 100);
$hundreds = ($hundreds ? ' '.$list1[$hundreds].' '.$langs->transnoentities('hundred').($hundreds == 1 ? '' : 's').' ' : '');
$tens = (int) ((int) $num_levels[$i] % 100);
$singles = '';
if ($tens < 20) {
$tens = ($tens ? ' '.$list1[$tens].' ' : '');
} else {
$tens = (int) ($tens / 10);
$tens = ' '.$list2[$tens].' ';
$singles = (int) ((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 -= 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 = empty($TNum[1]) ? '' : preg_replace('/0+$/', '', $TNum[1]);
if ($decimalpart) {
if (!empty($currency)) {
$concatWords .= ' '.$langs->transnoentities('and');
}
$concatWords .= ' '.dol_convertToWord($decimalpart, $langs, '', true);
if (!empty($currency)) {
$concatWords .= ' '.$langs->transnoentities('centimes');
}
}
return $concatWords;
}
}
/**
* Function to return number or amount in text.
*
* @deprecated
* @param float $numero Number to convert
* @param Translate $langs Language
* @param string $numorcurrency 'number' or 'amount'
* @return string|int Text of the number or -1 in case TOO LONG (more than 1000000000000.99)
*/
function dolNumberToWord($numero, $langs, $numorcurrency = 'number')
{
// If the number is negative convert to positive and return -1 if it is too long
if ($numero < 0) {
$numero *= -1;
}
if ($numero >= 1000000000001) {
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
in case exist why ask $lang like a parameter?*/
if (((is_object($langs) && $langs->getDefaultLang(0) == 'es_MX') || (!is_object($langs) && $langs == 'es_MX')) && $numorcurrency == 'currency') {
if ($numero >= 1 && $numero < 2) {
return ("UN PESO ".$parte_decimal." / 100 M.N.");
} elseif ($numero >= 0 && $numero < 1) {
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 -= $CdMMillon * 100000000000;
$DdMMillon = (int) ($numero / 10000000000);
$numero -= $DdMMillon * 10000000000;
$UdMMillon = (int) ($numero / 1000000000);
$numero -= $UdMMillon * 1000000000;
$entexto .= hundreds2text($CdMMillon, $DdMMillon, $UdMMillon);
$entexto .= " MIL ";
}
if ($number >= 1000000) {
$CdMILLON = (int) ($numero / 100000000);
$numero -= $CdMILLON * 100000000;
$DdMILLON = (int) ($numero / 10000000);
$numero -= $DdMILLON * 10000000;
$udMILLON = (int) ($numero / 1000000);
$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 -= $cdm * 100000;
$ddm = (int) ($numero / 10000);
$numero -= $ddm * 10000;
$udm = (int) ($numero / 1000);
$numero -= $udm * 1000;
$entexto .= hundreds2text($cdm, $ddm, $udm);
if ($cdm || $ddm || $udm) {
$entexto .= " MIL ";
}
}
$c = (int) ($numero / 100);
$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;
}
return -1;
}
/**
* hundreds2text
*
* @param integer $hundreds Hundreds
* @param integer $tens Tens
* @param integer $units Units
* @return string
*/
function hundreds2text($hundreds, $tens, $units)
{
if ($hundreds == 1 && $tens == 0 && $units == 0) {
return "CIEN";
}
$centenas = array("CIENTO", "DOSCIENTOS", "TRESCIENTOS", "CUATROCIENTOS", "QUINIENTOS", "SEISCIENTOS", "SETECIENTOS", "OCHOCIENTOS", "NOVECIENTOS");
$decenas = array("", "", "TREINTA ", "CUARENTA ", "CINCUENTA ", "SESENTA ", "SETENTA ", "OCHENTA ", "NOVENTA ");
$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");
$unidades = array("UN", "DOS", "TRES", "CUATRO", "CINCO", "SEIS", "SIETE", "OCHO", "NUEVE");
$entexto = "";
if ($hundreds != 0) {
$entexto .= $centenas[$hundreds - 1];
}
if ($tens > 2) {
if ($hundreds != 0) {
$entexto .= " ";
}
$entexto .= $decenas[$tens - 1];
if ($units != 0) {
$entexto .= " Y ";
$entexto .= $unidades[$units - 1];
}
return $entexto;
} elseif ($tens == 2) {
if ($hundreds != 0) {
$entexto .= " ";
}
$entexto .= " ".$veintis[$units];
return $entexto;
} elseif ($tens == 1) {
if ($hundreds != 0) {
$entexto .= " ";
}
$entexto .= $diecis[$units];
return $entexto;
}
if ($units != 0) {
if ($hundreds != 0 || $tens != 0) {
$entexto .= " ";
}
$entexto .= $unidades[$units - 1];
}
return $entexto;
}