In order to meet the KSA GAZT regulations, it is mandatory to print a QR code containing 5 fields including Company name, VAT registration number, Invoice date/time, VAT Amount, and Invoice Amount including VAT on any customer invoice.
In order to meet above requirements, you need to first declare two variables on global level using X++ such as:
//global variable
//PKR qr code
int qrCodeByteArrIndex;
System.Byte[] qrCodeByteArray;
Then there need to be two methods, one is used to populate the global byte array and the other one as display method to display QR code on a bitmap control:
/// <summary>
/// The method takes TLV structure for KSA QR code and sets into byte array containing data for QR code.
/// </summary>
/// <param name="_tag">
/// The serial number of structure.
/// </param>
/// <param name="_length">
/// The length of value of field.
/// </param>
/// <param name="[System.Byte[]]_byteArrayStr">
/// The value of a field.
/// </param>
/// <remarks>
/// Various field values such as VAT number, company name, VAT Amount, Invoice Amount including VAT, and Transaction date
/// and time need to be printed as QR code. The method serves as setting each TLV structure into a byte array.
/// </remarks>
void pkr_QRCodeFillByteArray(int _tag, int _length, System.Byte[] _byteArrayStr)
{
int counter;
qrCodeByteArray.SetValue( System.Convert::ToByte(_tag), qrCodeByteArrIndex);
qrCodeByteArrIndex++;
qrCodeByteArray.SetValue(System.Convert::ToByte(_length), qrCodeByteArrIndex);
qrCodeByteArrIndex++;
for (counter=0; counter < CLRInterOp::getAnyTypeForObject(_byteArrayStr.get_Length()); counter++)
{
qrCodeByteArray.SetValue(_byteArrayStr.GetValue(counter), qrCodeByteArrIndex);
qrCodeByteArrIndex++;
}
}
The display method as below:
public display container qrcode()
{
str strCompanyName, strVATNum, strDateTime, strTotalVATAmount, strTotalAmountIncVAT, strQrCodeBase64;
int qrByteArrayLength;
Bindata bindata = new Bindata();
System.Drawing.Bitmap obj;
Filepath filePath;
container con;
Microsoft.Dynamics.QRCode.Encoder encoder;
Set permissionSet;
System.Text.Encoding encodingUTF8;
;
filePath = @"C:\temp\newQRCode.bmp";
permissionSet = new Set(Types::Class);
permissionSet.add(new FileIOPermission(filePath,'rw'));
permissionSet.add(new InteropPermission(InteropKind::ClrInterop));
CodeAccessPermission::assertMultiple(permissionSet);
encoder = new Microsoft.Dynamics.QRCode.Encoder();
encodingUTF8 = System.Text.Encoding::get_UTF8();
qrCodeByteArrIndex = 0;
strCompanyName = companyInfo.Name;
strVATNum = companyInfo.CoRegNum;
strDateTime = date2Str(custInvoiceJour.InvoiceDate,321,DateDay::Digits2,DateSeparator::Hyphen, DateMonth::Digits2, DateSeparator::Hyphen, DateYear::Digits4)+ "T12:00:00Z";
strTotalVATAmount = strfmt("%1", totalamount+totalVATAmount);
strTotalAmountIncVAT = strfmt("%1", totalVATAmount);
qrByteArrayLength = strlen(strfmt("%1%2%3%4%5", strCompanyName, strVATNum, strDateTime, strTotalVATAmount, strTotalAmountIncVAT)) + 10;
qrCodeByteArray = new System.Byte[qrByteArrayLength](); //initialize global byte array as per length of all TLV structures plus 2 chars per each struct for TL.
element.pkr_QRCodeFillByteArray(1, strlen(strCompanyName), encodingUTF8.GetBytes(strCompanyName));
element.pkr_QRCodeFillByteArray(2, strlen(strVATNum), encodingUTF8.GetBytes(strVATNum));
element.pkr_QRCodeFillByteArray(3, strlen(strDateTime), encodingUTF8.GetBytes(strDateTime));
element.pkr_QRCodeFillByteArray(4, strlen(strTotalVATAmount), encodingUTF8.GetBytes(strTotalVATAmount));
element.pkr_QRCodeFillByteArray(5, strlen(strTotalAmountIncVAT), encodingUTF8.GetBytes(strTotalAmountIncVAT));
strQrCodeBase64 = System.Convert::ToBase64String(qrCodeByteArray);
info(strfmt("%1", strQrCodeBase64));
obj = new System.Drawing.Bitmap(encoder.Encode(strQrCodeBase64));
obj.Save(filePath, System.Drawing.Imaging.ImageFormat::get_Bmp());
bindata.loadFile(filePath);
con = bindata.getData();
CodeAccessPermission::revertAssert();
return con;
}
Lastly, place a bitmap control on an appropriate place on report design and then call display method from the control's properties.
The implementation may vary but the above code used for AX 2009 may be utilized with small changes.