Compartir a través de


Generar códigos QR e imprimirlos en recibos para Arabia Saudí

Nota

La funcionalidad descrita en este artículo está destinada a respaldar los requisitos de la Fase 1 de la implementación de la facturación electrónica en el Reino de Arabia Saudita. Para obtener información sobre las funciones heredadas destinadas a respaldar los requisitos de la Fase 2 de la implementación de la facturación electrónica en el Reino de Arabia Saudí, consulte Generar y enviar facturas electrónicas simplificadas para Arabia Saudí.

Este artículo proporciona una visión general de la funcionalidad para imprimir códigos QR que está disponible para Arabia Saudí en Microsoft Dynamics 365 Commerce.

En una tienda que está vinculada a una entidad jurídica que tiene su dirección principal en Arabia Saudí, los usuarios pueden imprimir un código QR en el recibo de una transacción de venta al contado o pedido de cliente. Este código QR contiene la siguiente información.

Secuencia Campo Origen de datos
1 Nombre de la compañía El nombre de la entidad jurídica
2 Número de registro DE IVA de la empresa El número de registro fiscal de la persona jurídica
3 Fecha y hora de transacción Fecha y hora de la transacción en el comercio minorista
4 Importe total del recibo (incluido el impuesto sobre el valor añadido [IVA]) Importe total de la transacción en el comercio minorista
5 Importe total de IVA incluido en el recibo El importe total de impuestos de la transacción en el comercio minorista

Nota

Cuando se crean transacciones de pedidos de cliente, el importe total del recibo se calcula sumando los importes totales de todas las líneas de transacción que usan el modo de entrega para llevar.

El código QR se genera aplicando la transformación base64 a la información de la transacción codificada en el formato Etiqueta-Longitud-Valor (TLV). La Autoridad de Zakat, Impuestos y Aduanas (ZATCA) proporciona herramientas que pueden utilizarse para validar el código QR. Para más información sobre los requisitos de facturación electrónica y las capacidades de validación de códigos QR, consulte el portal de facturación electrónica de ZATCA.

Configurar códigos QR

Para generar códigos QR e imprimirlos en recibos para Arabia Saudí, debe completar las siguientes tareas.

  1. Configurar campos personalizados para que se puedan usar en formatos de recibo para recibos de ventas
  2. Configurar formatos de recibo.
  3. Especificar las dimensiones de código QR en parámetros de Comercio.
  4. Habilitar las extensiones de Commerce Runtime (CRT).

Configure campos personalizados para que se puedan usar en formatos de recibo para recibos de ventas

Puede configurar el texto del idioma y los campos personalizados que se utilizan en los puntos de venta (PDV). Sobre la página Texto de idioma, agregue los siguientes registros para las etiquetas de los campos personalizados para diseños de recibos. Tenga en cuenta que los valores ID de idioma, ID de texto y Texto que se muestran en la tabla son solo ejemplos. Puede cambiarlos fácilmente para satisfacer sus necesidades. Sin embargo, los valores ID de texto que use deben ser únicos y deben ser iguales o mayores que 900001.

Id. de idioma Id. de texto Texto
es-es 900001 Código QR (SA)

Nota

La empresa predeterminada del usuario que crea la configuración del recibo debe ser la misma entidad legal donde se crea la configuración del texto del idioma. Alternativamente, los textos en el mismo idioma deben crearse tanto en la empresa predeterminada del usuario como en la entidad legal de la tienda para la que se creó la configuración.

Sobre la página Campos personalizados, agregue los siguientes registros para los campos personalizados para diseños de recibos. Tenga en cuenta que los valores ID de texto de subtítulo deben corresponder a los valores de ID de texto que especificó en la página Texto de idioma.

Name Tipo Id. de texto de leyenda
INVOICEQRCODE_SA Recepción 900001

Configurar formatos de recibo

Para cada formato de recibo requerido, cambie el valor del campo Comportamiento de impresión a Imprimir siempre.

En el diseñador de formato de recibo, agregue los siguientes campos personalizados a la sección Pie de página. Tenga en cuenta que los nombres de los campos corresponden a los textos de idioma que definió en la sección anterior.

  • Código QR (SA) – Este campo imprime el código QR para el recibo.

Para obtener más información sobre cómo trabajar con formatos de recibo, consulte Configurar y diseñar formatos de recibos.

Especificar dimensiones de código QR en parámetros de Commerce

En la pestaña Parámetros de configuración de la página Parámetros de comercio, añada los siguientes parámetros de configuración:

  • QrCodeWidth. La anchura de la imagen del código QR, en píxeles. Especifique un valor adecuado para el parámetro.
  • QrCodeHeight. La altura de la imagen del código QR, en píxeles. Especifique un valor adecuado para el parámetro.

Nota

Es obligatorio especificar los valores de estos parámetros de configuración para imprimir códigos QR en los recibos. Es posible que en futuras actualizaciones se agregue compatibilidad con valores predeterminados de los parámetros.

Permitir extensiones CRT

Advertencia

Esta funcionalidad de localización no puede utilizarse con el nuevo modelo independiente de empaquetado y ampliación y el kit de desarrollo de software (SDK) de Commerce. Debe utilizar la versión anterior de Retail SDK en una máquina virtual (VM) de desarrollador en Microsoft Dynamics Lifecycle Services (LCS). Para obtener información sobre las características de localización para Arabia Saudí disponibles en el SDK de Commerce, consulte Generar y enviar facturas electrónicas simplificadas para Arabia Saudí

Entorno de desarrollo

Siga estos pasos para configurar un entorno de desarrollo para que pueda probar y ampliar la funcionalidad de localización.

  1. Busque el archivo de configuración de la extensión para CRT:

    • Retail Server: El archivo se llama commerceruntime.ext.config y está en la carpeta bin\ext en la ubicación del sitio de IIS Retail Server.
    • CRT local en Modern POS: El archivo se llama CommerceRuntime.MPOSOffline.Ext.config y está en la ubicación del agente del cliente de CRT local.
  2. Registre el cambio de CRT en el archivo de configuración de la extensión, como se muestra en el siguiente ejemplo.

    <add source="assembly" value="Microsoft.Dynamics.Commerce.Runtime.ReceiptsSaudiArabia" />
    <add source="assembly" value="Microsoft.Dynamics.Commerce.Runtime.ElectronicReporting" />
    

Entorno de producción

Siga estos pasos para crear paquetes desplegables que contengan componentes de Commerce y aplicar esos paquetes en un entorno de producción.

  1. En los archivos de configuración de los paquetes commerceruntime.ext.config y CommerceRuntime.MPOSOffline.Ext.config de la carpeta RetailSdk\Assets, añada las siguientes líneas a la sección de composición.

    <add source="assembly" value="Microsoft.Dynamics.Commerce.Runtime.ReceiptsSaudiArabia" />
    <add source="assembly" value="Microsoft.Dynamics.Commerce.Runtime.ElectronicReporting" />
    
  2. Abra el símbolo del sistema de MSBuild para la utilidad Visual Studio y ejecute msbuild en la carpeta Retail SDK para crear paquetes implementables.

  3. Aplique los paquetes a través de LCS o manualmente. Para obtener más información, consulte Crear paquetes implementables.

Al utilizar una impresora con la vinculación e incrustación de objetos para Retail POS (OPOS), es posible que deba implementar personalizaciones adicionales para admitir los requisitos específicos de la impresora para la imagen del código QR. Por ejemplo, puede que tenga que convertir la imagen del código QR del formato PNG al formato BMP. En esta sección se muestra un ejemplo de este tipo de personalización.

Nota

Este ejemplo de personalización se probó con la impresora EPSON TM-T88V OPOS. Es posible que tenga que modificarse para admitir diferentes marcas o modelos de impresoras.

Siga estos pasos para crear una nueva extensión y añadirla a su entorno.

  1. Instale el SDK de Retail. Para obtener más información, consulte Kit de desarrollo de software (SDK) para minoristas.

  2. En el SDK de Retail, use el siguiente código, basado en su versión de Commerce, para crear un proyecto de C# en la solución CommerceRuntimeSamples.sln en RetailSdk\SampleExtensions\CommerceRuntime.

    <Project Sdk="Microsoft.NET.Sdk">
        <Import Project="..\..\..\BuildTools\Microsoft.Dynamics.RetailSdk.Build.props" />
        <Import Project="..\..\..\BuildTools\Common.props" />
        <Import Project="..\..\..\BuildTools\Microsoft.Dynamics.RetailSdk.Build.settings" />
    
        <PropertyGroup>
            <TargetFramework>netstandard2.0</TargetFramework>
            <AssemblyName>$(AssemblyNamePrefix).Commerce.Runtime.QrCodeExtension</AssemblyName>
            <RootNamespace>Contoso.Commerce.Runtime.QrCodeExtension</RootNamespace>
            <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
        </PropertyGroup>
    
        <Import Project="..\..\..\BuildTools\Microsoft.Dynamics.RetailSdk.Build.targets" />
    
        <ItemGroup>
            <PackageReference Include="Microsoft.Dynamics.Commerce.Runtime.Framework" Version="$(FrameworkRepoPackagesVersion)" />
            <PackageReference Include="Microsoft.Dynamics.Commerce.Runtime.Services.Messages" Version="$(ChannelRepoPackagesVersion)" />
            <PackageReference Include="System.Drawing.Common" Version="4.7.0" />
        </ItemGroup>
    
        <ItemGroup>
            <Reference Include="Microsoft.Dynamics.Commerce.Runtime.ElectronicReporting">
                <HintPath>..\..\..\..\..\nuget packages\microsoft.dynamics.commerce.runtime.electronicreporting.9.35.21321.4\lib\netstandard2.0\Microsoft.Dynamics.Commerce.Runtime.ElectronicReporting.dll</HintPath>
            </Reference>
        </ItemGroup>
    
        <ItemGroup>
            <Folder Include="Properties\" />
        </ItemGroup>
    </Project>
    

    También debe cambiar el valor del elemento HintPath para hacer referencia a la biblioteca Microsoft.Dynamics.Commerce.Runtime.ElectronicReporting.dll en la ubicación del sitio IIS Retail Server.

  3. Utilice el siguiente código, según su versión de Commerce, para crear una clase de extensión.

    /**
     * SAMPLE CODE NOTICE
     * 
     * THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
     * OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
     * THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
     * NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
     */
    
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    
    namespace Contoso
    {
        namespace Commerce.Runtime.QrCodeExtension
        {
            using System;
            using System.Collections.Generic;
            using System.Threading.Tasks;
            using Microsoft.Dynamics.Commerce.Runtime;
            using Microsoft.Dynamics.Commerce.Runtime.Messages;
            using Microsoft.Dynamics.Commerce.Runtime.Services.Messages;
    
            /// <summary>
            /// The extension for QR code printing.
            /// </summary>
            internal class QrCodeServiceExtension : IRequestHandlerAsync
            {
                /// <summary>
                /// Printer horizontal resolution for image.
                /// </summary>
                private const float PrinterXDpi = 60f;
    
                /// <summary>
                /// Printer vertical resolution for image.
                /// </summary>
                private const float PrinterYDpi = 90f;
    
                /// <summary>
                /// Printer pixel format for image.
                /// </summary>
                private const PixelFormat PrinterPixelFormat = PixelFormat.Format8bppIndexed;
    
                /// <summary>
                /// Gets the collection of supported request types by this service.
                /// </summary>
                public IEnumerable<Type> SupportedRequestTypes
                {
                    get => new[] {typeof(EncodeQrCodeServiceRequest)};
                }
    
                /// <summary>
                /// Processes the request.
                /// </summary>
                /// <param name="request">The request.</param>
                /// <returns>The response.</returns>
                public async Task<Response> Execute(Request request)
                {
                    ThrowIf.Null(request, nameof(request));
    
                    switch (request)
                    {
                        case EncodeQrCodeServiceRequest encodeQrCodeServiceRequest:
                        {
                            EncodeQrCodeServiceResponse nextResponse = await this.ExecuteNextAsync<EncodeQrCodeServiceResponse>(encodeQrCodeServiceRequest).ConfigureAwait(false);
    
                            if (nextResponse != null)
                            {
                                var qrCodeBmp = string.IsNullOrWhiteSpace(nextResponse.QRcode) ? nextResponse.QRcode : ConvertToGenericCompatibilityImage(nextResponse.QRcode);
                                return new EncodeQrCodeServiceResponse(qrCodeBmp);
                            }
    
                            return nextResponse;
                        }
                    }
    
                    return new NotHandledResponse();
                }
    
                /// <summary>
                /// Converts QR code image from any format to compatible with printer.
                /// </summary>
                /// <param name="base64data">Base64 image.</param>
                /// <returns>Image that Compatible with printer.</returns>
                private static string ConvertToGenericCompatibilityImage(string base64data)
                {
                    string convertedQrCode = base64data;
                    byte[] imageBytes = Convert.FromBase64String(convertedQrCode);
                    using (MemoryStream msOriginal = new MemoryStream(imageBytes))
                    using (MemoryStream msConverted = new MemoryStream())
                    {
                        var bitmapOriginal = new Bitmap(msOriginal);
                        if (!IsFormatCompatible(bitmapOriginal) || !AreResolutionAndPixelFormatCompatible(bitmapOriginal))
                        {
                            var bitmapConverted = bitmapOriginal;
    
                            if (!AreResolutionAndPixelFormatCompatible(bitmapOriginal))
                            {
                                var rectangle = new Rectangle(0, 0, bitmapOriginal.Width, bitmapOriginal.Height);
                                bitmapConverted = bitmapOriginal.Clone(rectangle, PrinterPixelFormat);
                                bitmapConverted.SetResolution(PrinterXDpi, PrinterYDpi);
                            }
    
                            bitmapConverted.Save(msConverted, ImageFormat.Bmp);
                        }
    
                        convertedQrCode = Convert.ToBase64String(msConverted.ToArray());
                    }
    
                    return convertedQrCode;
                }
    
                /// <summary>
                /// Verifies if the resolution and pixel format of bitmap are compatible with printer requirements.
                /// </summary>
                /// <param name="source">Bitmap.</param>
                /// <returns>True if compatible; otherwise false.</returns>
                private static bool AreResolutionAndPixelFormatCompatible(Bitmap source)
                {
                    return source.VerticalResolution == PrinterYDpi &&
                           source.HorizontalResolution == PrinterXDpi &&
                           source.PixelFormat == PrinterPixelFormat;
                }
    
                /// <summary>
                /// Verifies if the format of bitmap is compatible with printer requirements.
                /// </summary>
                /// <param name="source">Bitmap.</param>
                /// <returns>True if compatible; otherwise false.</returns>
                private static bool IsFormatCompatible(Bitmap source)
                {
                    return source.RawFormat.Equals(ImageFormat.Bmp);
                }
            }
        }
    }
    
  4. En los archivos de configuración commerceruntime.ext.config y CommerceRuntime.MPOSOffline.Ext.config de la carpeta RetailSdk\Assets, añada las siguientes líneas a la sección de composición.

    <add source="assembly" value="Contoso.Commerce.Runtime.QrCodeExtension" />
    <add source="assembly" value="Microsoft.Dynamics.Commerce.Runtime.ReceiptsSaudiArabia" />
    <add source="assembly" value="Microsoft.Dynamics.Commerce.Runtime.ElectronicReporting" />
    
  5. En el archivo de configuración de personalización del paquete de Ajustes de personalización en la carpeta BuildTools, agregue las siguientes líneas para incluir las extensiones de CRT en los paquetes desplegables.

    <ISV_CommerceRuntime_CustomizableFile Include="$(SdkReferencesPath)\Contoso.Commerce.Runtime.QrCodeExtension.dll" />
    
  6. Inicie el símbolo del sistema de MSBuild para la utilidad Visual Studio y ejecute msbuild en la carpeta Retail SDK para crear paquetes implementables.

  7. Aplique los paquetes a través de LCS o manualmente. Para obtener más información, consulte Crear paquetes implementables.