435 lines
12 KiB
PHP
435 lines
12 KiB
PHP
<?php
|
|
|
|
namespace BRSystems\Core\Library\cNumbers;
|
|
|
|
use BRSystems\Core\App\pubDocuments\inc\pubDocumentsModule;
|
|
use BRSystems\Core\Library\cDb\cDb;
|
|
|
|
/**
|
|
* cNumbers module
|
|
*
|
|
* @category LIB numbers
|
|
* @author Mareks Keišs <mareks.keiss@brsystems.lv>
|
|
* @since Version 1.0
|
|
*/
|
|
|
|
// Sequence procedure MYSQL
|
|
// ----------------------------------------------------------
|
|
//SET GLOBAL log_bin_trust_function_creators = 1$$
|
|
//CREATE FUNCTION `nextnum`(`seq_name` VARCHAR(100), `skip` INT)RETURNS BIGINT(20) NOT DETERMINISTIC
|
|
//BEGIN
|
|
// DECLARE
|
|
// cur_val int;
|
|
// SELECT
|
|
// next_index INTO cur_val
|
|
// FROM
|
|
// mod_sequences
|
|
// WHERE
|
|
// name = seq_name;
|
|
//
|
|
// IF skip IS NULL THEN
|
|
// set skip = 1;
|
|
// END IF;
|
|
// IF cur_val IS NOT NULL THEN
|
|
// UPDATE mod_sequences SET next_index = cur_val+skip WHERE name = seq_name;
|
|
// ELSE
|
|
// set cur_val = skip;
|
|
// INSERT INTO mod_sequences (name, next_index) VALUES (seq_name, 2);
|
|
// END IF;
|
|
//
|
|
// RETURN cur_val;
|
|
//END$$
|
|
// ----------------------------------------------------------
|
|
class cNumbers
|
|
{
|
|
private $db;
|
|
private $name;
|
|
|
|
const SEQ_PARTNER_CODE = 'SEQ_PARTNER_CODE';
|
|
const SEQ_ROUTES_CODE = 'SEQ_ROUTES';
|
|
|
|
/**
|
|
* Class constructor
|
|
* @param bool|string $sDbName - DB name to use in connection
|
|
*/
|
|
public function __construct($sDbName = false) {
|
|
|
|
$this->name = get_class();
|
|
$sDbName = (strlen($sDbName) ? $sDbName : DB_NAME);
|
|
$this->db = cDb::getInstance(DB_HOST, DB_USR, DB_PWD, DB_PORT, $sDbName);
|
|
|
|
}
|
|
|
|
/**
|
|
* Function to get sequence next id for numbers by name
|
|
*
|
|
* @author Mareks Keišs <mareks.keiss@brsystems.lv>
|
|
* @category cNumbers
|
|
* @param string $name - sequence name
|
|
* @param int $skip_nums - skip numbers in sequence
|
|
* @return int next valid value
|
|
*/
|
|
public function getSequenceByName($name, $skip_nums = 1)
|
|
{
|
|
$sSql = "SELECT nextnum('" . $name . "', " . $skip_nums . ");";
|
|
$this->db->query($sSql);
|
|
|
|
if ($val = $this->db->getOne()) {
|
|
return $val;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function to get bonus product number
|
|
*
|
|
* @author Mareks Keišs <mareks.keiss@brsystems.lv>
|
|
* @category cNumbers
|
|
* @param int $numLen - length of the num
|
|
* @return int next valid number
|
|
*/
|
|
public function getProductNumber($numLen = 6){
|
|
|
|
// 12X = date(260911) - number 00000N
|
|
$num = $this->getSequenceByName('SEQ_PRODUCT_NUMBER');
|
|
while (strlen($num)<$numLen) {
|
|
$num = '0' . $num;
|
|
}
|
|
return date('dmy') . $num;
|
|
}
|
|
|
|
/**
|
|
* Function to get bonus product number
|
|
*
|
|
* @author Mareks Keišs <mareks.keiss@brsystems.lv>
|
|
* @category cNumbers
|
|
* @param int $iType - bill type
|
|
* @param int $iNrLength - number length width leading zeros
|
|
* @return int next valid number
|
|
*/
|
|
public function getProductDocumentNumber($iType, $iNrLength = 4)
|
|
{
|
|
// 12X = date(260911) - number 00000N
|
|
$num = $this->getSequenceByName(pubDocumentsModule::SEQ_DOC_TYPES . $iType);
|
|
return str_pad($num, $iNrLength, '0', STR_PAD_LEFT);
|
|
}
|
|
|
|
/**
|
|
* Function to get advance invoice number
|
|
*
|
|
* X = number 00000N
|
|
*
|
|
*
|
|
* @author Aivars Žukovskis <info@brsystems.lv>
|
|
* @category cNumbers
|
|
* @return int next valid number
|
|
*/
|
|
public function getAdvanceInvoiceNumber(){
|
|
$num = $this->getSequenceByName('SEQ_ADVANCE_INVOICE_NUMBER');
|
|
while (strlen($num)<4) $num = '0' . $num;
|
|
return $num;
|
|
}
|
|
|
|
/**
|
|
* Function to get PNA number
|
|
*
|
|
* X = number 00000N
|
|
*
|
|
*
|
|
* @author Aivars Žukovskis <info@brsystems.lv>
|
|
* @category cNumbers
|
|
* @return int next valid number
|
|
*/
|
|
public function getPNANumber(){
|
|
$num = $this->getSequenceByName('SEQ_PNA_NUMBER');
|
|
while (strlen($num)<4) $num = '0' . $num;
|
|
return $num;
|
|
}
|
|
|
|
/**
|
|
* Function to get unique number by seq name
|
|
*
|
|
* @author Mareks Keišs <mareks.keiss@brsystems.lv>
|
|
* @category cNumbers
|
|
* @param string $sSeqTitle - sequence title to use
|
|
* @param int $iNrLength - number length width leading zeros
|
|
* @return int next valid formatted number
|
|
*/
|
|
public function getUniqueNumber($sSeqTitle = 'SEQ_DEFAULT', $iNrLength = 4){
|
|
|
|
// number 00000N
|
|
$num = $this->getSequenceByName($sSeqTitle);
|
|
return str_pad($num, $iNrLength, '0', STR_PAD_LEFT);
|
|
|
|
}
|
|
|
|
/**
|
|
* Function to get bonus product number
|
|
*
|
|
* @author Mareks Keišs <mareks.keiss@brsystems.lv>
|
|
* @category cNumbers
|
|
* @return int next valid number
|
|
*/
|
|
public function getBonusNumber(){
|
|
|
|
// Hx42 - B = 420000N
|
|
$num = $this->getSequenceByName('SEQ_BONUS_NUMBER');
|
|
while (strlen($num)<5) {
|
|
$num = '0' . $num;
|
|
}
|
|
return '42' . $num;
|
|
}
|
|
|
|
/**
|
|
* Function to get bonus product exchange number
|
|
*
|
|
* @author Mareks Keišs <mareks.keiss@brsystems.lv>
|
|
* @category cNumbers
|
|
* @return int next valid number
|
|
*/
|
|
public function getBonusExchangeNumber(){
|
|
|
|
// Hx45 - E = 450000N
|
|
$num = $this->getSequenceByName('SEQ_BONUS_EXCH_NUMBER');
|
|
while (strlen($num)<5) {
|
|
$num = '0' . $num;
|
|
}
|
|
return '45' . $num;
|
|
}
|
|
|
|
/**
|
|
* Function to get bonus product barcode
|
|
*
|
|
* @author Mareks Keišs <mareks.keiss@brsystems.lv>
|
|
* @category cNumbers
|
|
* @return int next valid number
|
|
*/
|
|
public function getBonusBarcode(){
|
|
|
|
// 12X = date(260911) - number 00000N
|
|
$num = $this->getSequenceByName('SEQ_BONUS_BARCODE');
|
|
while (strlen($num)<6) {
|
|
$num = '0' . $num;
|
|
}
|
|
return date('dmy') . $num;
|
|
}
|
|
|
|
/**
|
|
* Function to convert number to string
|
|
*
|
|
* @author Mareks Keišs <mareks.keiss@brsystems.lv>
|
|
* @category cNumbers
|
|
* @param array - $inst - instance for callable translation function
|
|
* @param array - $sum - number to translate
|
|
* @param string - $currKey - currency key to use
|
|
* @return string - number in words
|
|
*/
|
|
public static function num2words(&$inst, $sum, $currKey = 'euros'){
|
|
if($sum){
|
|
$words = self::translateWords($inst);
|
|
|
|
$num = number_format($sum, 2, '.', '');
|
|
$num = explode('.', $num);
|
|
if(count($num) > 1){
|
|
|
|
$prefix = '';
|
|
// Add negative sign prefix
|
|
if ((int)$num[0] < 0) {
|
|
$num[0] = (int)$num[0] * -1;
|
|
$prefix = $words['-'] . ' ';
|
|
}
|
|
|
|
$w1 = trim(self::no_to_words($words, (int)$num[0]));
|
|
$w1 = ($w1 ? $w1 : $words['zero']);
|
|
|
|
$decNum = (int)$num[1];
|
|
$w = trim(self::no_to_words($words, $decNum));
|
|
$w = ($w ? $w : $words['zero']);
|
|
|
|
return "{$prefix}{$w1} {$words[$currKey]} {$words['and']} {$w} " . self::getWordInflection($words['cents'], $decNum);
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Function to translate number words
|
|
*
|
|
* @author Mareks Keišs <mareks.keiss@brsystems.lv>
|
|
* @category cNumbers
|
|
* @param array - $words - translated arry
|
|
* @param array - $no - number to translate
|
|
* @return string - number in words
|
|
*/
|
|
private static function translateWords($inst){
|
|
|
|
$words = [
|
|
'-' => 'minus',
|
|
'euros' => 'euros',
|
|
'cents' => 'cents',
|
|
'and' => 'and',
|
|
'zero' => 'zero',
|
|
|
|
'0' => '',
|
|
'1' => 'one',
|
|
'2' => 'two',
|
|
'3' => 'three',
|
|
'4' => 'four',
|
|
'5' => 'five',
|
|
'6' => 'six',
|
|
'7' => 'seven',
|
|
'8' => 'eight',
|
|
'9' => 'nine',
|
|
'10' => 'ten',
|
|
'11' => 'eleven',
|
|
'12' => 'twelve',
|
|
'13' => 'thirteen',
|
|
'14' => 'fouteen',
|
|
'15' => 'fifteen',
|
|
'16' => 'sixteen',
|
|
'17' => 'seventeen',
|
|
'18' => 'eighteen',
|
|
'19' => 'nineteen',
|
|
'20' => 'twenty',
|
|
'30' => 'thirty',
|
|
'40' => 'fourty',
|
|
'50' => 'fifty',
|
|
'60' => 'sixty',
|
|
'70' => 'seventy',
|
|
'80' => 'eighty',
|
|
'90' => 'ninty',
|
|
'100' => 'hundred &',
|
|
'1000' => 'thousand',
|
|
'1000000' => 'million',
|
|
//'10000000' => 'crore',
|
|
];
|
|
|
|
foreach ($words as &$v) {
|
|
$v = $inst->gM($v);
|
|
}
|
|
|
|
unset($v);
|
|
return $words;
|
|
}
|
|
|
|
/**
|
|
* Function can only convert nos up to 999 millions
|
|
*
|
|
* @author Mareks Keišs <mareks.keiss@brsystems.lv>
|
|
* @category cNumbers
|
|
* @param array - $words - translated array
|
|
* @param array - $no - number to translate
|
|
* @return string - number in words
|
|
*/
|
|
private static function no_to_words(array &$words, $nr): string
|
|
{
|
|
if ($nr == 0) {
|
|
return ' ';
|
|
} elseif ($nr < 100) {
|
|
if (!isset($words[(string)$nr])) {
|
|
$highNr = ((int)($nr / 10)) * 10;
|
|
$remainNr = $nr % 10;
|
|
return $words[(string)$highNr] . ' ' . $words[(string)$remainNr];
|
|
} else {
|
|
return $words[(string)$nr];
|
|
}
|
|
} else {
|
|
|
|
$highNr = 0;
|
|
$remainNr = 0;
|
|
|
|
$start = 10;
|
|
$b1 = 100;
|
|
$b2 = 1000;
|
|
|
|
$w = '';
|
|
while ($nr > $start) {
|
|
if (($b1 <= $nr) && ($nr < $b2)) {
|
|
$highNr = (int)($nr / $b1);
|
|
$w = self::getWordInflection($words[(string)$b1], $highNr);
|
|
$remainNr = $nr % $b1;
|
|
break;
|
|
}
|
|
$start *= 10;
|
|
|
|
$b1 = $b2;
|
|
$b2 = $b1 * 1000;
|
|
}
|
|
|
|
// Set base number
|
|
if (!isset($words[(string)$highNr])) {
|
|
$sStr = self::no_to_words($words, $highNr) . " $w";
|
|
} else {
|
|
$sStr = $words[(string)$highNr] . " $w";
|
|
}
|
|
|
|
// Send remaining part for calculation
|
|
if (!isset($words[(string)$remainNr])) {
|
|
$sStr .= " " . self::no_to_words($words, $remainNr);
|
|
} else {
|
|
$w = self::getWordInflection($words[(string)$remainNr]);
|
|
$sStr .= " $w";
|
|
}
|
|
|
|
return $sStr;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function to generate word inflection
|
|
*
|
|
* @author Mareks Keišs <mareks.keiss@brsystems.lv>
|
|
* @category cNumbers
|
|
* @param string $word - word
|
|
* @param int $highNr - number before
|
|
* @return string - word in correct inflection
|
|
*/
|
|
private static function getWordInflection($word, $highNr = 0){
|
|
$nParts = explode("|", $word);
|
|
if(count($nParts) == 1){
|
|
$w = $word;
|
|
}elseIf(count($nParts) > 1 && $highNr == 1){
|
|
$w = $nParts[0] . $nParts[1];
|
|
}elseIf(count($nParts) > 1 && ($highNr > 1 || $highNr == 0)){
|
|
$w = $nParts[0] . $nParts[2];
|
|
}
|
|
return $w;
|
|
}
|
|
/**
|
|
* Function to generate random length string for passwords example
|
|
*
|
|
* @author Mareks Keišs <mareks.keiss@brsystems.lv>
|
|
* @category cNumbers
|
|
* @param int $length - length to create string
|
|
* @param bool $nums - include numbers
|
|
* @return string - number in words
|
|
*/
|
|
public static function getRandomChString($length = 8, $nums = false) {
|
|
|
|
$new_pass = "";
|
|
for($i=0;$i<$length;$i++){
|
|
switch (rand(0, ($nums?2:1))){
|
|
case 0:
|
|
$new_pass.= chr(rand(65,90)); // only big letters
|
|
break;
|
|
case 1:
|
|
$new_pass.= chr(rand(97,122)); // only small letters
|
|
break;
|
|
case 2:
|
|
$new_pass.= chr(rand(48,57)); // only small letters
|
|
break;
|
|
}
|
|
}
|
|
return $new_pass;
|
|
}
|
|
|
|
public function getProductBillNumber(): string
|
|
{
|
|
// 12X = date(260911) - number 00000N
|
|
$num = $this->getSequenceByName('SEQ_BILL_NUMBER');
|
|
while (strlen($num) < 4) {
|
|
$num = '0' . $num;
|
|
}
|
|
return date('ym') . $num;
|
|
}
|
|
}
|