Sunday, 6 February 2022

Spot The Bug: Runaway Stock Code

Good day to you, bug-hunters. And welcome to another edition of Spot The Bug!

Let's get busy,
bug-hunters.

Today's problem revolves around PHP. My task was to read from a vendor database that stored data about inventory operations. The frustrating thing was that they didn't have transaction data such as stock code and quantities, but rather a table of comments generated whenever a transaction took place.

Stock (XLL2323) removed. Qty: -2
Stock (XLL2323) removed. Qty: -22
Stock (FRU551100) removed. Qty: -10
Stock (FRU551100) added. Qty: 25
Stock (SMQ010080) added. Qty: 9


So basically I had to retrieve a list of comments generated during a certain date range for a certain stock code, and deduce quantities and direction (in or out) of each transaction. To that end, I basically wrote some test code using a nested Foreach loop. If the Stock Code was inside the comment, then I would obtain the quantity from the comment with a strategic use of some string functions.
$skus = ["XMB2311"];

foreach ($skus as $sku)
{
    echo $sku;
    echo "<br />";
    $inv = 0;

    foreach ($logs as $log)
    {
        if (strpos($log, $sku))
        {
            $split = explode("Qty: ", $log);
            $qty = $split[1];
            $inv += $qty;
            echo $inv;
            echo "<hr />";
        }    
    }
}


What went wrong

This was the result. For the Stock Code XMB2311, which I was investigating, the quantity of the product was increasing over time.. This was despite the fact that a cursory examination of the database showed that there were very few transactions for XMB2311, and none of them involved amounts that would push the inventory up to 88, assuming we started off with a base amount of 0.



Why it went wrong

I added to the test code by displaying the log statements.
foreach ($skus as $sku)
{
    echo $sku;
    echo "<br />";
    $inv = 0;

    foreach ($logs as $log)
    {
        echo $sku . ":" . $log;
        echo "<br />";


        if (strpos($log, $sku))
        {
            $split = explode("Qty: ", $log);
            $qty = $split[1];
            $inv += $qty;
            echo $inv;
            echo "<hr />";
        }    
    }
}


And here, I discovered that not only were the log statements for XMB2311 matching, so were the ones for XMB231109!


The problem was that the some of the Stock Codes were subsets of each other. For instance, "XMB2311" was a subset of "XMB231109". So if I was doing a search for "XMB2311" in a comment that featured Stock Code XMB231109, the result would be true, and the code in the If block would be fired off erroneously!

How I fixed it

Adding a ")" in the argument to be searched. This way, the strpos() function would search specifically for the Stock Code and only that Stock Code (because all the Stock Codes in the comments ended in a ")"!
if (strpos($log, $sku . ")"))


There it was!


Moral of the story

Sometimes it's not so much that your code is completely wrong, but that it is not exact enough for that particular use case. In this instance, a closer look had to be taken at the data in order to see exactly what went wrong.

Warm_regards . ")",
T___T

No comments:

Post a Comment