project QadFinancials > class BCountry > method ApiCheckVatNumber

Description

This method checks if the vat number is correct(format check)
This method is not used on ui, so the remoting flag can be set on false, the api is set on true, because this method is called from mfg/pro


Parameters


iiCountryIdinputintegercountry ID
icCountryCodeinputcharacterCountry Code
icVatNumberinputcharacterTax Format
ilMessageinputlogicalDo you want to see the errors or not ?
ocVatNumberShortoutputcharacterVat Number that you have to write into the database
ocVatNumberLongoutputcharacterVat Number that you have to show on you User Interface
So if you type 999999999 and in VAT Format there is for that country a format 999.999.999 then you have to show the last one
oiReturnStatusoutputintegerReturn status of the method.


Internal usage


QadFinancials
method BBusinessRelation.GetVatNumber
method BBusinessRelation.ValidateComponentPostAddress
method BBusinessRelation.ValVatNumber
method BCreditor.ValStateTax
method BDebtor.ValStateTax


program code (program7/bcountry.p)

/* ==================================================== */
    /* Skip Unknown-values and Convert the Code into the ID */
    /* Filled but non-existing code -> Error                */
    /* ==================================================== */
    if icCountryCode = ? then assign icCountryCode = "":U.

    /* ==================================================================== */
    /* give an error when the id and the code of the country are not filled */
    /* ==================================================================== */
    if iiCountryId = 0 and icCountryCode = "":U
    then do :
        assign vcMessage      = trim(#T-12'You must enter the country code for the tax format.':255(1403)T-12#)
               oiReturnStatus = -1.
        <M-1 run SetMessage (input  vcMessage (icMessage),
                     input  '':U (icArguments),
                     input  '':U (icFieldName),
                     input  '':U (icFieldValue),
                     input  'E':U (icType),
                     input  3 (iiSeverity),
                     input  '':U (icRowid),
                     input  'QADFIN-253':U (icFcMsgNumber),
                     input  '' (icFcExplanation),
                     input  '' (icFcIdentification),
                     input  '' (icFcContext),
                     output viFcReturnSuper (oiReturnStatus)) in BCountry>
        return.
    end.

    /* ================================================================= */
    /* by the next query, we get the countrycode and the related formats */
    /* ================================================================= */

     <Q-81 run CountryVatFormatByCountry (all) (Read) (NoCache)
        (input iiCountryId, (CountryId)
         input (if iiCountryId = 0 then icCountryCode else '':U), (CountryCode)
         output dataset tqCountryVatFormatByCountry) in BCountry>
    
    /* =============================================== */
    /* give an error when the vat number is not filled */
    /* =============================================== */
    
    find first tqCountryVatFormatByCountry no-error.
    if available tqCountryVatFormatByCountry and
                 icVatNumber = "":U 
    
    then do :
        assign vcMessage      = trim(substitute(#T-13'The State Tax Id is blank for this country (&1).':255(943688788)T-13#,icCountryCode)) + chr(10) +
                                trim(substitute(#T-14'Country: &1.':150(1405)T-14#, string(iiCountryId)))
               oiReturnStatus = 1.
        <M-4 run SetMessage
           (input  vcMessage (icMessage), 
            input  '':U (icArguments), 
            input  '':U (icFieldName), 
            input  '':U (icFieldValue), 
            input  'W':U (icType), 
            input  3 (iiSeverity), 
            input  '':U (icRowid), 
            input  'QADFIN-255':U (icFcMsgNumber), 
            input  '' (icFcExplanation), 
            input  '' (icFcIdentification), 
            input  '' (icFcContext), 
            output viFcReturnSuper (oiReturnStatus)) in BCountry>
        return.
    end.
 

    /* ======================================================== */
    /* give an error when no vat formats found for this country */
    /* ======================================================== */
    if not available tqCountryVatFormatByCountry and
                     icVatNumber <> "":U
    then do:
        assign vcMessage      = trim(substitute(#T-15'No tax format is defined for this country (country ID = &1, country code = &2).':255(1406)t-15#,string(iiCountryId),icCountryCode))
               oiReturnStatus = 1. /* Warning */
        <M-3 run SetMessage (input  vcMessage (icMessage), 
                     input  '':U (icArguments), 
                     input  '':U (icFieldName), 
                     input  '':U (icFieldValue), 
                     input  'W':U (icType), 
                     input  3 (iiSeverity), 
                     input  '':U (icRowid), 
                     input  'QADFIN-254':U (icFcMsgNumber), 
                     input  '' (icFcExplanation), 
                     input  '' (icFcIdentification), 
                     input  '' (icFcContext), 
                     output viFcReturnSuper (oiReturnStatus)) in BCountry>

        assign ocVatNumberLong  = icVatNumber
               ocVatNumberShort = icVatNumber.
        return.
    end.
    
    if available tqCountryVatFormatByCountry
    then assign icCountryCode    = tqCountryVatFormatByCountry.tcCountryCode.

    assign ocVatNumberShort = "":U.

    if icVatNumber <> "":U
    then do:

        VATBLOCK: 
        for each tqCountryVatFormatByCountry 
                 no-lock:
             assign viLength = length(tqCountryVatFormatByCountry.tcCountryVatFormat,"CHARACTER":U).
             if length(icVatNumber,"CHARACTER":U) = viLength
             then do:
                 assign ocVatNumberLong = icVatNumber
                        ocVatNumberShort = "":U.
                 do viCount = 1 to viLength :
                     assign vcChr1 = substring(tqCountryVatFormatByCountry.tcCountryVatFormat, viCount, 1,"CHARACTER":U)
                            vcChr2 = substring(icVatNumber, viCount, 1,"CHARACTER":U).
                     if vcChr1 = "9":U
                     then do:
                         /* ============== */
                         /* 9 = any number */
                         /* ============== */
                         if vcChr2 < "0":U or vcChr2 > "9":U
                         then do:
                             assign ocVatNumberShort = "":U.
                             next VATBLOCK.
                         end.
                         assign ocVatNumberShort = ocVatNumberShort + vcChr2.
                     end. /* end vcChr1 = "9":U */
                     else if vcChr1 = "!":U
                     then do:
                         /* ============== */
                         /* ! = any letter */
                         /* ============== */
                         if vcChr2 < "A":U or vcChr2 > "Z":U
                         then do:
                             assign ocVatNumberShort = "":U.
                             next VATBLOCK.
                         end.
                         assign ocVatNumberShort = ocVatNumberShort + vcChr2.
                     end. /* end vcChr1 = "!":U */
                     else if vcChr1 = "*":U /* any character */
                          then assign ocVatNumberShort = ocVatNumberShort + vcChr2.
                          else do:
                              /* ============================= */
                              /* both characters must be equal */
                              /* ============================= */
                              if vcChr1 <> vcChr2 
                              then do:
                                  assign ocVatNumberShort = "":U.
                                  next VATBLOCK.
                              end. /* end vcChr1 <> "*":U and */
                              
                              if vcChr1 >= "A":U and vcChr2 <= "Z":U
                              then assign ocVatNumberShort = ocVatNumberShort + vcChr1.
                          end. /* end else */
                 end. /* end do viCount = 1 to */
             end. /* end length(icVatNumber,"CHARACTER":U) = */
             else if length(icVatNumber,"CHARACTER":U) < viLength
             then do:
                 assign ocVatNumberLong = "":U
                        ocVatNumberShort = icVatNumber
                        viCount2    = 1.
                 do viCount = 1 to viLength:
                     assign vcChr1 = substring(tqCountryVatFormatByCountry.tcCountryVatFormat, viCount, 1,"CHARACTER":U)
                            vcChr2 = substring(icVatNumber, viCount2, 1,"CHARACTER":U).
                     if vcChr1 = "9":U
                     then do:
                         /* ============== */
                         /* 9 = any number */
                         /* ============== */
                         if vcChr2 < "0":U or vcChr2 > "9":U
                         then do:
                             assign ocVatNumberShort = "":U
                                    viCount     = (if ViCount2 > length(icVatNumber,"CHARACTER":U)
                                                   then 0
                                                   else viCount).
                             next VATBLOCK.
                         end.
                         assign ocVatNumberLong = ocVatNumberLong + vcChr2
                                viCount2 = viCount2 + 1.
                     end. /* end vcChr1 = "9":U */
                     else if vcChr1 = "!":U
                     then do:
                         /* ============== */
                         /* ! = any letter */
                         /* ============== */
                         if vcChr2 < "A":U or vcChr2 > "Z":U
                         then do:
                             assign ocVatNumberShort = "":U
                                    viCount     = (if ViCount2 > length(icVatNumber,"CHARACTER":U)
                                                   then 0
                                                   else viCount).
                             next VATBLOCK.
                         end.
                         assign ocVatNumberLong = ocVatNumberLong + vcChr2
                                viCount2    = viCount2 + 1.
                     end. /* end vcChr1 = "!":U */
                     else if vcChr1 = "*":U /* any character */
                     then do:
                         assign ocVatNumberLong = ocVatNumberLong + vcChr2
                                viCount2 = viCount2 + 1.
                     end.
                     else if vcChr1 >= "A":U and vcChr1 <= "Z":U
                     then do:
                         /* ================== */
                         /* A - Z fixed letter */
                         /* ================== */
                         if vcChr1 <> vcChr2
                         then do :
                             /* ============================ */
                             /* both character must be equal */
                             /* ============================ */
                             assign ocVatNumberShort = "":U
                                    viCount          = (if ViCount2 > length(icVatNumber,"CHARACTER":U)
                                                        then 0
                                                        else viCount).
                             next VATBLOCK.
                         end. /* end vcChr1 <> vcChr2 */
                         assign ocVatNumberLong = ocVatNumberLong + vcChr1
                                viCount2    = viCount2 + 1.
                     end. /* end if vcChr1 >= "A":U .. */
                     else do:
                         /* ======================== */
                         /* insert editing character */
                         /* ======================== */
                         assign ocVatNumberLong = ocVatNumberLong + vcChr1.
                              /* viCount2    = viCount2 + 1.*/ /* not necessary ? */
                     end.
                 end. /* end do viCount = 1 to */
                 if length(ocVatNumberLong,"CHARACTER":U) <> length(tqCountryVatFormatByCountry.tcCountryVatFormat,"CHARACTER":U) or
                    length(icVatNumber,"CHARACTER":U) + 1 <> viCount2
                 then do:
                     assign viCount     = 0
                            ocVatNumberShort = "":U.
                     next VATBLOCK.
                 end.
             end. /* end if length(icVatNumber,"CHARACTER":U) < */
             else do:
                 /* ============== */
                 /* invalid length */
                 /* ============== */
                 assign viCount = 0.
                 next VATBLOCK.
             end.
             leave.
        end. /* end for each tqCountryVatFormatByCountry */
    

        if ocVatNumberShort = "":U
        then do:
            assign ocVatNumberLong = icVatNumber.
            if ilMessage
            then do:
                assign vcMessage      = if viCount = 0
                                        then trim(substitute(#T-16'The tax number length is invalid for this country (ID = &1, code = &2).':255(1407)t-16#,string(iiCountryId),icCountryCode))
                                        else trim(substitute(#T-17'The tax number contains an invalid number of characters for this country (ID = &1, code = &2).':255(1408)t-17#,string(iiCountryId),icCountryCode))
                       oiReturnStatus = -1.
                <M-7 run SetMessage (input  vcMessage (icMessage),
                         input  '':U (icArguments),
                         input  '':U (icFieldName),
                         input  icVatNumber (icFieldValue),
                         input  'E':U (icType),
                         input  3 (iiSeverity),
                         input  '':U (icRowid),
                         input  'QADFIN-257':U (icFcMsgNumber),
                         input  '' (icFcExplanation),
                         input  '' (icFcIdentification),
                         input  '' (icFcContext),
                         output viFcReturnSuper (oiReturnStatus)) in BCountry>
            end.
        end.

    end. /*if icVatNumber <> "":U*/

    /* ================================================================================ */
    /* only on valid Belgian Vat numbers, do a modulus 97 check                         */
    /* the tqCountryVatFormatByCountry is still available because you have done a leave */
    /* ================================================================================ */
    if icCountryCode = "BE":U and
       ocVatNumberShort  <> "":U  and
      (tqCountryVatFormatByCountry.tcCountryVatFormat = "999.999.999":U or
       tqCountryVatFormatByCountry.tcCountryVatFormat = "999999999":U) 
    then do:
        if 97 - (integer(substring(ocVatNumberShort,1,7,"CHARACTER":U)) mod 97) <> integer(substring(ocVatNumberShort,8,2,"CHARACTER":U))
        then do:
            if ilMessage
            then do:
                assign vcMessage      = trim(substitute(#T-18'The check sum for the tax number for this country (country ID = &1, country code = &2, tax number = &3) is invalid.':255(17685)t-18#,string(iiCountryId),icCountryCode,icVatNumber))
                       oiReturnStatus = 1. /* warning */
                <M-10 run SetMessage
                   (input  vcMessage (icMessage), 
                    input  '':U (icArguments), 
                    input  '':U (icFieldName), 
                    input  '':U (icFieldValue), 
                    input  'W':U (icType), 
                    input  3 (iiSeverity), 
                    input  '':U (icRowid), 
                    input  'QADFIN-256':U (icFcMsgNumber), 
                    input  '' (icFcExplanation), 
                    input  '' (icFcIdentification), 
                    input  '' (icFcContext), 
                    output viFcReturnSuper (oiReturnStatus)) in BCountry>
            end.
            else assign ocVatNumberShort = "":U.
        end.
    end.
    


Sample code: how to call this method through RPCRequestService (QXtend Inbound)

define temp-table ttContext no-undo
    field propertyQualifier as character
    field propertyName as character
    field propertyValue as character
    index entityContext is primary unique
        propertyQualifier
        propertyName
    index propertyQualifier
        propertyQualifier.

define dataset dsContext for ttContext.

define variable vhContextDS as handle no-undo.
define variable vhExceptionDS as handle no-undo.
define variable vhServer as handle no-undo.
define variable vhInputDS as handle no-undo.
define variable vhInputOutputDS as handle no-undo.
define variable vhOutputDS as handle no-undo.
define variable vhParameter as handle no-undo.

/* Create context */
create ttContext.
assign ttContext.propertyName = "programName"
       ttContext.propertyValue = "BCountry".
create ttContext.
assign ttContext.propertyName = "methodName"
       ttContext.propertyValue = "ApiCheckVatNumber".
create ttContext.
assign ttContext.propertyName = "applicationId"
       ttContext.propertyValue = "fin".
create ttContext.
assign ttContext.propertyName = "entity"
       ttContext.propertyValue = "1000".
create ttContext.
assign ttContext.propertyName = "userName"
       ttContext.propertyValue = "mfg".
create ttContext.
assign ttContext.propertyName = "password"
       ttContext.propertyValue = "".

/* Create input dataset */
create dataset vhInputDS.
vhInputDS:read-xmlschema("file", "xml/bcountry.apicheckvatnumber.i.xsd", ?).
vhParameter = vhInputDS:get-buffer-handle("tParameterI").
vhParameter:buffer-create().
assign vhParameter::iiCountryId = <parameter value>
       vhParameter::icCountryCode = <parameter value>
       vhParameter::icVatNumber = <parameter value>
       vhParameter::ilMessage = <parameter value>.

/* Connect the AppServer */
create server vhServer.
vhServer:connect("-URL <appserver-url>").

if not vhServer:connected()
then do:
    message "Could not connect AppServer" view-as alert-box error title "Error".
    return.
end.

/* Run */
assign vhContextDS = dataset dsContext:handle.

run program/rpcrequestservice.p on vhServer
    (input-output dataset-handle vhContextDS by-reference,
           output dataset-handle vhExceptionDS,
     input        dataset-handle vhInputDS by-reference,
     input-output dataset-handle vhInputOutputDS by-reference,
           output dataset-handle vhOutputDS).

/* Handle output however you want, in this example, we dump it to xml */
if valid-handle(vhExceptionDS)
then vhExceptionDS:write-xml("file", "Exceptions.xml", true).

if valid-handle(vhOutputDS)
then vhOutputDS:write-xml("file", "Output.xml", true).

/* Cleanup */
vhServer:disconnect().
assign vhServer = ?.

if valid-handle(vhInputDS)
then delete object vhInputDS.

if valid-handle(vhOutputDS)
then delete object vhOutputDS.

if valid-handle(vhExceptionDS)
then delete object vhExceptionDS.