Topic: Numeric BarCode restriction / Valid Alphanumeric filter

A recent commit restricts BarCodes to be generated only if the stock_id is an integer.

This was done since the Barcode generation routine generated errors on malformed input as a stop-gap arrangement since the auto generation of Barcode stock_id was restricted to a random / sequential available number.

The file /reporting/includes/barcodes.php manages Barcode generation and is taken from the TCPDF Library.

In the said library above, each type of barcode is properly generated with the appropriate methods listing the valid ASCII codes and size range / limits along with check-digit computations and verification where enabled.

The following links in reference are in order:
1. Make BarCode
2. BarCode Resource
3. Keyence

Clearly, the stock_id and item_code fields are VARCHAR in the FA DB and several BarCode formats support alphanumeric characters (CODE128, Codabar, etc) and some even symbols too.

Currently available libraries:
1. A Zend Library Validation of BarCode "code" input is also available.
2. A JavaScript Validation of a few barcode formats are available here.

The need now is to hammer out a function to validate the stock_id before allowing the generation of the barcode in pure PHP without external dependancies so that errors don't get generated while doing so during generation.

Any suggestions?

Blindly suppressing all errors during Barcode generation and leaving it blank when not possible to generate on for whatever reason is a simplistic but effective choice for many.

Re: Numeric BarCode restriction / Valid Alphanumeric filter

I found this class for Barcode validation on github. Maybe we could extract a function or use the class for validation:

Barcode validator.

I wonder if this could be used.

/Joe

Re: Numeric BarCode restriction / Valid Alphanumeric filter

Or this one. Taken from PHP Classes.  It is a class, but I extracted the function.

<?php
/* Check length of barcode for validity via the checkdigit calculation
 * We split the barcode into it's constituent digits, offset them into the GTIN
 * calculation tuple (x1, x3, x1, x3, x1, etc, etc), multiply the digits and add
 * them together, then modulo them on 10, and you get the calculated check digit.
 * For more information see GS1 website: https://www.gs1.org/check-digit-calculator
 * @param string gtin
 * @return bool */
function Checkgtin($gtin) 
{
    /* Checks the length of the GTIN
     * @param string gtin
     * @return bool */
    // Check length is ok
    if (strlen($gtin) < 8 || strlen($gtin) > 14)
        return false;

    // Check whether is a number
    preg_match("/\d+/", $gtin, $m, PREG_OFFSET_CAPTURE, 0);
    if (empty($m))
        return false;

    // Define fixed variables
    $CheckDigitArray = [];
    $gtinMaths = [3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3];
    $modifier = 17 - (strlen($gtin) - 1);  // Gets the position to place first digit in array
    $gtinCheckDigit = substr($gtin, -1); // Get provided check digit
    $BarcodeArray = str_split($gtin);  // Split barcode at each digit into array
    $gtinLength = strlen($gtin);
    $tmpCheckDigit = 0;
    $tmpCheckSum = 0;
    $tmpMath = 0;

    // Run through and put digits into multiplication table
    for ($i = 0; $i < ($gtinLength - 1); $i++) {
        $CheckDigitArray[$modifier + $i] = $BarcodeArray[$i];  // Add barcode digits to Multiplication Table
    }

    // Calculate "Sum" of barcode digits
    for ($i = $modifier; $i < 17; $i++) {
        $tmpCheckSum += ($CheckDigitArray[$i] * $gtinMaths[$i]);
    }

    // Difference from Rounded-Up-To-Nearest-10 - Fianl Check Digit Calculation
    $tmpCheckDigit = (ceil($tmpCheckSum / 10) * 10) - $tmpCheckSum;

    // Check if last digit is same as calculated check digit
    if ($gtinCheckDigit == $tmpCheckDigit)
        return true;
    return false;
}
  
$gtin = "00abcd";
if (Checkgtin($gtin))
    echo "$gtin is ok<br />";
else    
    echo "$gtin is NOT ok<br />";

/Joe

Re: Numeric BarCode restriction / Valid Alphanumeric filter

Maybe we can use the class TCPDFBarcode in /reporting/includes/barcodes.php för testing of valid barcodes. I will give it a try.

Joe

Re: Numeric BarCode restriction / Valid Alphanumeric filter

No, I couldn't get it to work. So I will have to leave it as is.

/Joe

Re: Numeric BarCode restriction / Valid Alphanumeric filter

The following should do the trick:

include $path_to_root."reporting/includes/barcode.php";

function is_valid_barcode($code, $type) {
    $barcode = new TCPDFBarcode($code, $type);
    $chk = $barcode->getBarcodeArray();
    return ($chk !== false);
}

The possible barcode types that tcpdf supports in FA are:

$barcode['C39']['name']     = 'CODE 39';
$barcode['C39+']['name']    = 'CODE 39 with checksum';
$barcode['C39E']['name']    = 'CODE 39 EXTENDED';
$barcode['C39E+']['name']   = 'CODE 39 EXTENDED with checksum';
$barcode['I25']['name']     = 'Interleaved 2 of 5';
$barcode['C128A']['name']   = 'CODE 128 A';
$barcode['C128B']['name']   = 'CODE 128 B';
$barcode['C128C']['name']   = 'CODE 128 C';
$barcode['EAN2']['name']    = '2-Digits UPC-Based Extension';
$barcode['EAN5']['name']    = '5-Digits UPC-Based Extension';
$barcode['EAN8']['name']    = 'EAN 8';
$barcode['EAN13']['name']   = 'EAN 13';
$barcode['UPCA']['name']    = 'UPC-A';
$barcode['UPCE']['name']    = 'UPC-E';
$barcode['POSTNET']['name'] = 'POSTNET';
$barcode['CODABAR']['name'] = 'CODABAR';

Re: Numeric BarCode restriction / Valid Alphanumeric filter

We don't have a $type when calling is_valid_barcode.

I have been trying this:

function is_valid_barcode($code)
{
    $types = array("EAN2", "EAN5", "EAN8", "EAN13", "UPCA", "UPCE", "C39", "C39+", "C39E", "C39E+", "I25", 
        "C128A", "C128B", "C128C", "POSTNET", "CODABAR");

    foreach ($types as $type)
    {
        if (substr($type, 0, 3) === "EAN" || substr($type, 0, 3) == "UPC")
        {
            if (!preg_match("/^[0-9]+$/", $code))
                continue;
        }        
           $barcode = new TCPDFBarcode($code, $type);
        $chk = $barcode->getBarcodeArray();
        if ($chk !== false)
            return true;
    }
    return false;
}

But if alphanumerical characters it is still testing. It shouldn't if EAN of UPC. Please try it.

Maybe I have overseen something, so please help.

/Joe

Re: Numeric BarCode restriction / Valid Alphanumeric filter

We have now established a Barcode Checker for the following types:

EAN, EAN-8, EAN-13, GTIN-8, GTIN-12, GTIN-14, UPC, UPC-12 coupon code, JAN 

This will be committed in a while.
If we later find som further testing of barcode types we will add these as well.

/Joe

Re: Numeric BarCode restriction / Valid Alphanumeric filter

CODE128 supports the entire ASCII set (Type B has lower and upper case as well) and would be useful if a mere character check is inculcated till a complete induction occurs. Also choice of Barcode Type may be included in the sys_prefs table. That would ofcourse preclude the use of multiple types of Barcodes in the same company.

The above test will fail if CODE128 or those other than the leading ones like EAN% and UPC% are checked since the foreach() traverses the array in order of the array elements. The earliest "true" when returned may not be right!

Whilst testing is in progress, a flag to suppress Barcode validation may be preferred.