Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

Sunday 7 April 2013

Programming the KwaMoja API - Error codes

In the last couple of parts of this tutorial which can be found here

API Client Part 1 and API Client Part 2

we produced a simple client application where a user selected a location, typed in a part code and the application fetched the info about how much stock was available from that location from our KwaMoja implementation.

This code can be fetched from here:

http://www.kwamoja.com/documentation/xml-rpc_tutorial.zip


However we did not touch on what would happen if something goes wrong. Load up the application, and you should see a screen similar to this one:


Now load index.php into our editor and change the password on line 38 from 'kwamoja' to 'wrong'. Now if we reload index.php we get this screen.

As you can see it cannot fetch any locations as the authentication does not work on this kwamoja instance. However it provides us with no information about why this has happened. If you recall from the tutorials regarding the writing of the client, the XML-RPC call returns an array containing two elements, the first - $Response[0] in our client - contains an integer code, and the second the result of the inquiry, if one is expected. If the integer code is zero, this indicates success. Any other code indicates an error. These error code can be found listed here.  As you can see error code 1 indicates 'NoAuthorisation' which will be the error returned if the user name or password is incorrect.

To catch the errors we create a session variable (not the best way I know, but convenient for this tutorial) to hold any error messages that happen, so that we can show the to the user. So the initialisation code at the top of index.php becomes:

<?php
    include 'xmlrpc/lib/xmlrpc.inc';
    $xmlrpc_internalencoding='UTF-8';
    include 'xmlrpc/lib/xmlrpcs.inc';
    $_SESSION['Errors'] = array();
?>


and then at the bottom of the output we have a loop to output these errors:

foreach ($_SESSION['Errors'] as $Error) {
    echo $Error;
}


Now we just need to capture that error. We need to put this code at the bottom of the GetLocations() function so that it now reads:

if ($ReturnValue[0] == 0) {
    return $ReturnValue[1];
} elseif ($ReturnValue[0] == 1) {
    $_SESSION['Errors'][] = 'Incorrect login/password credentials used';
}


Now run the index.php script again in your browser and you should get out put similar to this:

We just need to put this code at the bottom of our other functions, and then they will all be able to catch this error.

Now if we put the proper password back in index.php should work as before.

Now try entering a stock code that you know doesn't exist and see what happens. I entered a part code called 'wrong' and this is what I see.

This is not very helpful output so we need catch this error. A quick look here shows that error code 1047 is 'StockCodeDoesntExist' and this should be returned if the code we entered is wrong. So we need to capture error 1047 in the GetStockQuantity() function. The code at the end of this function now becomes:

} elseif ($ReturnValue[0] == 1) {
    $_SESSION['Errors'][] = 'Incorrect login/password credentials used';
} elseif ($ReturnValue[0] == 1047) {
    $_SESSION['Errors'][] = 'The stock code you entered does not exist';
}


So now the function is checking that the user/password is correct and also checking that the stock code is correct and providing useful feedback in the case of any problems. We could go on and check for other errors but this should be enough for now.

I have uploaded the new tutorial files to here.

Next time I will have a look at debugging the application when an error we haven't caught occurs.

Thursday 7 March 2013

Programming the KwaMoja API - A simple client part 2

This is the second part of the tutorial on building a PHP client to extract data from KwaMoja via the API. If you missed the first, read this first. In the last part we created a client that queried the KwaMoja installation and extracted a list of stock locations, we then used to populate a drop down list in our HTML page. What we then wanted to do, was to extract the full name of the location, rather than just showing the code.

To do this we need a function much like the one we used to extract the array of location codes. Here is the full code:

    function LocationName($LocationCode) {

        //Encode the data items
        $UserID = php_xmlrpc_encode("admin");
        $Password = php_xmlrpc_encode("kwamoja");
        $Code = php_xmlrpc_encode($LocationCode);

        //Create a client object to use for xmlrpc call and set its debug level to zero
        $Client = new xmlrpc_client("http://localhost/KwaMoja/api/api_xml-rpc.php");
        $Client->setDebug(0);


        //Create a message object, containing the parameters and the function name
        $Message = new xmlrpcmsg('kwamoja.xmlrpc_GetLocationDetails', array($Code, $UserID, $Password));


        //Use the client object to send the message object to the server, returning the response
        $Response = $Client->send($Message);


        //Decode the response and return the array
        $ReturnValue = php_xmlrpc_decode($Response->value());
        if ($ReturnValue[0] == 0) {
            return $ReturnValue[1]['locationname'];
        }
    }


The first section encodes the parameters as XML. The first two parameters are always the userid/password combination, and for this function call we need a third parameter, which is the code of the location that we require the name of. The second section is identical to the previous function and creates an instance of the XML-RPC client class. The third section then creates an instance of the message class, with the first parameter being the full name of the API function being called, in this case kwamoja.xmlrpc_GetLocationDetails, and then the second parameter is an array of the encoded parameters, (location code, userid, password). This message is then sent to the server, and the response decoded into an array called $ReturnValue.

As last time the first element of the array signifies whether the function was successful (a zero), or any other integer for an error code. The second element is an associative array of details for that location. The key of each element is the field name for that value. In our case we just want the location name, so we return the element ['locationname']. If it was the telephone number we were interested in we would just return the ['tel'] element.

Changing the line in the HTML where we fill the drop down box to:

echo '<option value="'.$LocationCode.'">'.LocationName($LocationCode).'</option>';

we can see that the web page in our browser now looks a little better.

The full name of the location appears in the drop down the list, but the value returned by the form is still just the code.

All that is left to complete our client, is to type a stock code in the text box, submit the form and return the amount of stock for that code at the chosen location. First we need to insert some PHP code in the HTML to handle the form being sent:

<?php
        if (isset($_POST['submit'])) {
            echo 'The quantity of '.$_POST['StockID'].' at '.$_POST['location'] . ' is : ''.GetStockQuantity($_POST['StockID'], $_POST['location']);
        }
 ?>


As you can see this calls another PHP function - GetStockQuantity() - that retrieves the stock quantity for the required item at the required location. Looking at the API function reference in the manual the API function we require is kwamoja.xmlrpc_GetStockBalance. However this time there is a small addition we require as this function returns an array containing the stock balances at all the locations for the given stock item.

The full code for the PHP function is:


    function GetStockQuantity($StockID, $LocationCode) {
        //Encode the data items
        $UserID = php_xmlrpc_encode("admin");
        $Password = php_xmlrpc_encode("kwamoja");
        $StockCode = php_xmlrpc_encode($StockID);

        //Create a client object to use for xmlrpc call and set its debug level to zero
        $Client = new xmlrpc_client("http://localhost/KwaMoja/api/api_xml-rpc.php");
        $Client->setDebug(0);
        //Create a message object, containing the parameters and the function name
        $Message = new xmlrpcmsg('kwamoja.xmlrpc_GetStockBalance', array($StockCode, $UserID, $Password));
        //Use the client object to send the message object to the server, returning the response
        $Response = $Client->send($Message);
        //Decode the response and return the array
        $ReturnValue = php_xmlrpc_decode($Response->value());
        if ($ReturnValue[0] == 0) {
            $Items = $ReturnValue[1];
            for ($i=0; $i<sizeOf($Items); $i++) {
                if ($Items[$i]['loccode']==$LocationCode) {
                    return $Items[$i]['quantity'];
                }
            }
        }
    }


I wont go through this in details as it is mostly the same as the previous functions. The key section is the last:

        $ReturnValue = php_xmlrpc_decode($Response->value());
        if ($ReturnValue[0] == 0) {
            $Items = $ReturnValue[1];
            for ($i=0; $i<sizeOf($Items); $i++) {
                if ($Items[$i]['loccode']==$LocationCode) {
                    return $Items[$i]['quantity'];
                }
            }
        }


Here the RPC returns an array of locations with the stock quantities for each location, and we filter out the location we need.

Putting all this together we get the following when we run the script in our browser:

Looking at the stock status in KwaMoja we see:

Showing that we have returned the correct numbers.

I have uploaded the source for this tutorial to http://www.kwamoja.com/documentation/xml-rpc_tutorial.zip please feel free to download and try it out.

In the next part I will introduce some error checking into the code.