From 9322113b8081e2df3771d45b0da3afe2d9cf3fd1 Mon Sep 17 00:00:00 2001 From: sparkyx Date: Sun, 26 Oct 2025 13:33:05 +0100 Subject: [PATCH] ICheck_IBAN Number : check bank account (iban) improve code CARD_PROPERTY --- html/ajax_misc.php | 2 + html/js/ajax_fiche.js | 145 ++++++++++++++++-------- include/ajax/ajax_check_ibannumber.php | 50 ++++++++ include/ajax/ajax_check_vatnumber.php | 1 + include/class/card_property.class.php | 14 ++- include/constant.php | 3 +- include/lib/ac_common.php | 65 +++++++++++ include/lib/iban_number.class.php | 87 ++++++++++++++ unit-test/include/lib/ac_commonTest.php | 34 +++++- 9 files changed, 350 insertions(+), 51 deletions(-) create mode 100644 include/ajax/ajax_check_ibannumber.php create mode 100644 include/lib/iban_number.class.php diff --git a/html/ajax_misc.php b/html/ajax_misc.php index da2459024..4ab518a6c 100644 --- a/html/ajax_misc.php +++ b/html/ajax_misc.php @@ -374,6 +374,8 @@ $path = array( , 'payment_status'=>'ajax_payment_status' // email setting , 'email_setting'=>'ajax_email_setting' + // check iban number + , 'check_ibannumber'=>'ajax_check_ibannumber' ) ; if (array_key_exists($op, $path)) { diff --git a/html/js/ajax_fiche.js b/html/js/ajax_fiche.js index a0a0d542e..e0436f857 100644 --- a/html/js/ajax_fiche.js +++ b/html/js/ajax_fiche.js @@ -316,56 +316,109 @@ category_card.remove_attribut=function (p_dossier,p_fiche_def_ref,p_object_name, * @param p_domid string domid of the IText * @see ivatnumber.class.php */ -category_card.check_vatnumber=function(p_domid) { - try - { - var dgbox="info"+p_domid; - waiting_box(); +category_card.check_vatnumber = function (p_domid) { + try + { + var dgbox = "info" + p_domid; + waiting_box(); - // For form , most of the parameters are in the FORM - // method is then POST - //var queryString=id$(p_form_id).serialize(true); + // For form , most of the parameters are in the FORM + // method is then POST + //var queryString=id$(p_form_id).serialize(true); - var queryString = { - op: 'check_vatnumber', - vatnr:id$(p_domid).value, - boxid: dgbox, - p_domid:p_domid - }; - var action = new Ajax.Request( - "ajax_misc.php" , - { - method:'GET', - parameters:queryString, - onFailure:ajax_misc_failure, - onSuccess:function(req){ - remove_waiting_box(); - if (req.responseText == 'NOCONX') { - reconnect(); - return; - } - var answer=req.responseJSON; + var queryString = { + op: 'check_vatnumber', + vatnr: id$(p_domid).value, + boxid: dgbox, + p_domid: p_domid + }; + var action = new Ajax.Request( + "ajax_misc.php", + { + method: 'GET', + parameters: queryString, + onFailure: ajax_misc_failure, + onSuccess: function (req) { + remove_waiting_box(); + if (req.responseText == 'NOCONX') { + reconnect(); + return; + } + var answer = req.responseJSON; - if ( answer.status == 'OK') - { - id$(dgbox).update(answer.html); - id$(p_domid).value=answer.vat; - id$(p_domid).removeClassName("notice") - id$(p_domid).addClassName("valid") - } else { - id$(p_domid).addClassName("notice"); - id$(p_domid).removeClassName("valid"); - id$(dgbox).update(answer.html); - } + if (answer.status == 'OK') + { + id$(dgbox).update(answer.html); + id$(p_domid).value = answer.vat; + id$(p_domid).removeClassName("notice") + id$(p_domid).addClassName("valid") + } else { + id$(p_domid).addClassName("notice"); + id$(p_domid).removeClassName("valid"); + id$(dgbox).update(answer.html); + } - } - } - ); - }catch( e) - { - remove_waiting_box(); - console.error(e.message); - } + } + } + ); + } catch (e) + { + remove_waiting_box(); + console.error(e.message); + } +} +category_card.check_ibannumber = function (p_domid) { + try + { + var dgbox = "info" + p_domid; + waiting_box(); + + // For form , most of the parameters are in the FORM + // method is then POST + //var queryString=id$(p_form_id).serialize(true); + + var queryString = { + op: 'check_ibannumber', + iban: id$(p_domid).value, + boxid: dgbox, + p_domid: p_domid + }; + var action = new Ajax.Request( + "ajax_misc.php", + { + method: 'GET', + parameters: queryString, + onFailure: ajax_misc_failure, + onSuccess: function (req) { + remove_waiting_box(); + if (req.responseText == 'NOCONX') { + reconnect(); + return; + } + var answer = req.responseJSON; + + if (answer.status == 'OK') + { + id$(p_domid).value = answer.data; + id$(p_domid).removeClassName("notice"); + id$(p_domid).addClassName("valid"); + + } else { + id$(p_domid).addClassName("notice"); + id$(p_domid).removeClassName("valid"); + } + + } + } + ); + } catch (e) + { + remove_waiting_box(); + console.error(e.message); + } +} +category_card.search_peppol_participant=function(p_domid) { + } //--> diff --git a/include/ajax/ajax_check_ibannumber.php b/include/ajax/ajax_check_ibannumber.php new file mode 100644 index 000000000..4db45297a --- /dev/null +++ b/include/ajax/ajax_check_ibannumber.php @@ -0,0 +1,50 @@ +get("iban"); + $p_domid = $http->get("p_domid"); + if (check_iban($iban) == true ){ + $obj->status = 'OK'; + $obj->html=_('valide'); + $obj->data=$iban; + echo json_response($obj); + return; + } + $obj->status = 'NOK'; + $obj->html=_('Erreur'); + echo json_response($obj); +} catch (\Exception $e) { + $obj->status = 'NOK'; + $obj->html=$e->getMessage(); + record_log($e); + return; +} diff --git a/include/ajax/ajax_check_vatnumber.php b/include/ajax/ajax_check_vatnumber.php index 120eaa850..5fbc7a17c 100644 --- a/include/ajax/ajax_check_vatnumber.php +++ b/include/ajax/ajax_check_vatnumber.php @@ -32,6 +32,7 @@ try { $p_domid = $http->get("p_domid"); } catch (\Exception $e) { echo $e->getMessage(); + record_log($e); return; } $vatnr = strtoupper($vatnr); diff --git a/include/class/card_property.class.php b/include/class/card_property.class.php index 01e364ee5..20f691cd4 100644 --- a/include/class/card_property.class.php +++ b/include/class/card_property.class.php @@ -196,19 +196,27 @@ class Card_Property return $result; } - elseif ($this->ad_id == ATTR_DEF_NUMTVA) { + if($this->ad_id == ATTR_DEF_BQ_NO) + { + $result['input']=new IBan_Number("av_text{$this->ad_id}",$this->av_text); + $result['label']=$this->ad_text; + return $result; + } + if ($this->ad_id == ATTR_DEF_NUMTVA) { /// Propose a button to check VAT $result['input']=new IVATNumber( "av_text" . $this->ad_id,$this->av_text); $result['label']=$this->ad_text; return $result; - }elseif ( $this->ad_id == ATTR_DEF_QUANTITY_TYPE){ + } + if ( $this->ad_id == ATTR_DEF_QUANTITY_TYPE){ $result['input']=new IText( "av_text" . $this->ad_id,$this->av_text); $array=$this->cn->get_array("select qc_code,format('%s %s',qc_code,qc_label) label from quantity_code_ref order by qc_label",p_mode: PGSQL_NUM); $result['input']->set_datalist($array); $result['label']=$this->ad_text; return $result; } - elseif ($this->ad_id == ATTR_DEF_TVA) { + + if ($this->ad_id == ATTR_DEF_TVA) { $result['input'] = new ITva_Popup('popup_tva'); $result['input']->table = 0; $result['input']->value = $this->av_text; diff --git a/include/constant.php b/include/constant.php index 9d9123be0..e9d5c9053 100644 --- a/include/constant.php +++ b/include/constant.php @@ -440,7 +440,8 @@ function noalyss_class_autoloader($class) "noalyss\invoice_pdf"=>"class/invoice_pdf.class.php", 'noalyss\xmldocument\xmlinvoice_reader'=>'XMLDocument/xmlinvoice_reader.class.php', 'noalyss\mail_parameter'=>'lib/mail_parameter.class.php', - 'noalyss\smtpmail'=>'lib/smtpmail.class.php' + 'noalyss\smtpmail'=>'lib/smtpmail.class.php', + 'noalyss\iban_number'=>'lib/iban_number.class.php' ); if (isset ($aClass[$class])) { require_once NOALYSS_INCLUDE . "/" . $aClass[$class]; diff --git a/include/lib/ac_common.php b/include/lib/ac_common.php index 09b1b730c..ae4a3396f 100644 --- a/include/lib/ac_common.php +++ b/include/lib/ac_common.php @@ -1894,3 +1894,68 @@ function find_idx($array,$key,$value) { } return -1; } + +function compute_letter_value() + { + global $aLetter,$aLetterValue; + + static $make_string=null; + if ( $make_string == null ) { + for ($i=65;$i!=91;$i++) { + $make_string[chr($i)]=$i-55; + } + $aLetter=array_keys($make_string); + $aLetterValue=array_values($make_string); + } + } +/** + * @brief check that an IBAN is valid + * @param $iban string, this parameter will change:remove of space, comma,... + * @return bool false the IBAN is invalid, true IBAN is VALID + */ +function check_iban(&$iban): bool +{ + global $aLetter, $aLetterValue; + if (trim($iban ?? "") == "") + return false; + + //------------------------------------------------ + // Make the letter + //------------------------------------------------ + static $make_string,$aLetter, $aLetterValue=null; + + if ( $make_string == null ) + { + for ($i=65;$i!=91;$i++) + { + $make_string[chr($i)]=$i-55; + } + $aLetter=array_keys($make_string); + $aLetterValue=array_values($make_string); + } + + $iban = strtoupper($iban); + $iban=str_replace([" ", ",", ".", "-"], '', $iban); + + $first = substr($iban, 0, 4); + $chain = substr($iban, 4) . $first; + + $replaced = str_replace($aLetter, $aLetterValue, $chain); + + // computed by slice of 10: mod function is limited + $start = 0; + $slice = 10; + $result = ""; + $length = strlen($replaced); + while ($start < $length) + { + $slice_string = $result . substr($replaced, $start, $slice); + $result = $slice_string % 97; + $start += $slice; + } + + if ($result == 1) + return true; + + return false; +} diff --git a/include/lib/iban_number.class.php b/include/lib/iban_number.class.php new file mode 100644 index 000000000..32ff72c37 --- /dev/null +++ b/include/lib/iban_number.class.php @@ -0,0 +1,87 @@ +itext = new IText($name,$value,$p_id); + $this->itext->title = _("IBAN"); + $this->itext->placeholder = "9999999999"; + $this->itext->extra = ""; + $this->itext->style = ' class="input_text" '; + $this->autofocus = false; + } + + function input() + { + if ( $this->readOnly==true) return $this->display(); + + $return = $this->itext->input(); + $return .= $this->button_check_iban(); + $return.=sprintf('
',$this->itext->id); + return $return; + } + + public function getIText(): IText + { + return $this->itext; + } + + public function setIText(IText $itext): IBan_Number + { + $this->itext = $itext; + return $this; + } + + function button_check_iban() + { + $button=new \IButton(uniqid()); + $button->javascript=sprintf("category_card.check_ibannumber('%s')", + $this->itext->id); + $button->extra='style="padding-bottom:0px"'; + $button->label=_("Vérifie"); + return $button->input(); + + + } + function display() + { + return $this->itext->display(); + + } + + static function testme() + { + $iban_number=new IBan_Number("av_text13"); + + echo $iban_number->input(); + } +} + diff --git a/unit-test/include/lib/ac_commonTest.php b/unit-test/include/lib/ac_commonTest.php index 97e3ff611..9a84be6c5 100644 --- a/unit-test/include/lib/ac_commonTest.php +++ b/unit-test/include/lib/ac_commonTest.php @@ -474,5 +474,37 @@ EOF; ,"error cannot generate strong password get $pass"); } } - + public static function dataCheck_Iban() + { + return array( + ['FR2617569000405121911339Y14', true] + , ['FR8917569000504392936779O14', true] + , ['FR7214508000702383844671J92', true] + , ['FR26169000405121911339Y14', false] + , ['FR89569000504392936779O14', false] + , ['FR72508000702383844671J92', false] + , ['NL13ABNA2859176594', true] + , ['NL51RABO8584700412', true] + , ['NL03ABNA4880983179', true] + , ['NL13ABNA285917694', false] + , ['NL51RABO858470012', false] + , ['N03ABNA488098379L', false] + , ['BE59561771574126', true] + , ['BE02631697478740', true] + , ['BE92519646539923', true] + , ['BE92519646539923', true] + , ['111459561771574126', false] + , ['1114026316974787401114', false] + , ['1114925196465399231114', false] + ); + } + /** + * @testDoc test the iban_check function + * @dataProvider dataCheck_Iban() + */ + #[DataProvider('dataCheck_Iban')] + function testCheck_Iban($iban,$result) + { + $this->assertTrue(check_iban($iban) == $result," fails for {$iban} receives {$result}"); + } }