Resulta que el tópico "cuantomás, mejor" no siempre es cierto, ni apropiado. Por ejemplo, en lo que respecta al tráfico, las hipotecas, los "influencers" de IG y... el número de clics de ratón necesarios para completar una actividad en un sistema de software, más no es mejor.
Cuando los sistemas se implantan en almacenes grandes y con mucho movimiento, a menudo la preferencia de los usuarios es pasar directamente de la pantalla de Acumatica a la impresora en un solo clic. En Acumatica, por defecto, este proceso requiere al menos un par de clics adicionales y unos segundos de espera mientras se carga la ventana de vista previa antes de que el documento se imprima realmente.
A partir de la versión 2018 R1, Acumatica incluyó la función Device Hub, que es un proceso que se ejecuta constantemente en segundo plano sondeando los nuevos documentos que se van a imprimir, para que puedan pasar de Acumatica a la cola de impresión en un solo clic.
En esta entrada del blog revisaremos el proceso necesario para que esto suceda mediante la revisión de la instalación, configuración y algunos buenos ejemplos de código antiguo.
Instalación del concentrador de dispositivos de impresión
Cuando se ejecuta el asistente de configuración de Acumatica ERP durante el proceso de instalación, una de las funciones de configuración disponibles es Instalar DeviceHub. Asegúrate de que esta casilla de verificación esté seleccionada y luego continúa con el resto de la instalación como se haría normalmente.
Configuración de la impresora en el servidor
Dado que toda esta configuración se está realizando en un servidor nuevo, necesitamos asegurarnos de que al menos una impresora está correctamente configurada y operativa. En este caso, utilizaremos la impresora Microsoft Printer to PDF (redirigida 2)
Verificamos que un documento de prueba se añade correctamente a la cola de impresión:
Configuración del entorno
En la página Activar/Desactivar funciones (CS100000), asegúrese de que la opción DeviceHub está seleccionada:
La propia aplicación DeviceHub tiene 2 pestañas para configurar: el sitio y las impresoras.
Tenga en cuenta que debido a que el DeviceHub es un proceso que se ejecuta continuamente en segundo plano preguntando al sistema si hay nueva información que añadir a la cola de impresión, es conveniente tener un usuario específico creado para este fin.
Tras pulsar OK, el DeviceHub empezará a funcionar y a sondear nuevos documentos para imprimir.
Ten en cuenta también que si se cierra la ventana de DeviceHub, el proceso seguirá ejecutándose en segundo plano. Para detenerlo, se debe utilizar el administrador de tareas.
Configuración de Acumatica
Lo primero que debe hacerse es hacer que la impresora esté disponible en Acumatica. Esto se logra desde la página Impresoras (SM206510).
En esta página, el botón Actualizar lista de impresoras se utiliza para rellenar la cuadrícula con las impresoras previamente definidas en el DeviceHub.
De nuevo, observe que si no hay resultados visibles en la cuadrícula después de pulsar el botón Actualizar lista de impresoras, deberá utilizar el botón Cancelar para actualizar la cuadrícula.
Al hacerlo, se actualizará la lista de impresoras disponibles en el DeviceHub.
Teniendo las impresoras ya disponibles en Acumatica, el siguiente paso es asignar los diferentes usuarios a diferentes impresoras. Por ejemplo, esto permitirá que el equipo administrativo utilice una impresora y que el equipo de recolectores del almacén utilice otra impresora separada en una ubicación diferente. Esto se hace en la página Acceso a impresoras (SM106000).
Esta página consta de dos pestañas: los usuarios y las impresoras asociadas.
Tenga en cuenta que los usuarios seleccionados en el grupo no requieren la inclusión del usuario DeviceHub creado previamente, ya que tienen propósitos diferentes: el primero se utiliza para identificar la impresora que se va a utilizar y el segundo se utiliza para el sondeo de trabajos en la cola.
Observe también que las impresoras y los usuarios pueden pertenecer a varios grupos. El efecto de esta configuración es visible en el campo GroupMask de la tabla RelationGroup, donde una combinación de valores binarios permite al sistema identificar correctamente qué impresora utilizar.
Con todos los ajustes y configuraciones completados, a continuación ampliaremos la página de Inventario y se añadirá un nuevo botón para imprimir un informe:
Paso 1 - Se crea un gráfico para gestionar la lógica de impresión:
using System;
using System.Collections.Generic;
using PX.SM;
using PX.Data;
using PX.Objects.CS;
using PX.Objects.IN;
using PX.Objects.CR;
using PX.Objects.AR;
namespace AcumaticaDeviceHub
{
public class PEPrintSLMaint : PXGraph<PEPrintSLMaint>
{
#region DAC PrintParameters
[System.SerializableAttribute]
public partial class PrintParameters : IBqlTable, PX.SM.IPrintable
{
#region PrintWithDeviceHub
public abstract class printWithDeviceHub : IBqlField
{
}
[PXDBBool]
[PXDefault(typeof(FeatureInstalled<FeaturesSet.deviceHub>))]
[PXUIField(DisplayName = "Print with DeviceHub")]
public virtual bool? PrintWithDeviceHub { get; set; }
#endregion
#region DefinePrinterManually
public abstract class definePrinterManually : IBqlField
{
}
[PXDBBool]
[PXDefault(true)]
[PXUIField(DisplayName = "Define Printer Manually")]
public virtual bool? DefinePrinterManually { get; set; }
#endregion
#region Printer
public abstract class printerName : PX.Data.IBqlField { }
[PX.SM.PXPrinterSelector]
public virtual string PrinterName { get; set; }
#endregion
}
#endregion
public static class Parameters
{
public const string Inventory_ID = "Inventory_ID";
}
public static class Fields
{
public static readonly string Inventory_ID = string.Format("{0}.{1}", nameof(InventoryItem), nameof(Parameters.Inventory_ID));
}
#region Methods
public void PrintReportInDeviceHub(string reportID, string actualReportID, List<string> nameGroupsList, Dictionary<string, string> parametersDictionary, string printerName, int numberPrint)
{
Guid loggedUser = this.Accessinfo.UserID;
Users usersRow = PXSelect<Users,
Where<Users.pKID, Equal<Required<Users.pKID>>>>
.Select(this, loggedUser);
string BinaryGroupMask = Convert.ToString(usersRow.GroupMask[0], 2);
List<string> ListGroupsUser = new List<string>();
for (int i = 0; i < BinaryGroupMask.Length; i++)
{
if (BinaryGroupMask.Substring(i, 1) != "0")
{
String BinaryGroup = (BinaryGroupMask.Substring(i, 1).PadLeft(i + 1, '0')).PadRight(BinaryGroupMask.Length, '0');
ListGroupsUser.Add(Convert.ToString(Convert.ToDecimal(Convert.ToByte(BinaryGroup, 2))));
}
}
Dictionary<string, string> groupsUserDictionary = new Dictionary<string, string>();
foreach (String GroupUser in ListGroupsUser)
{
foreach (RelationGroup relationGroupRow in PXSelect<RelationGroup, Where<RelationGroup.active, Equal<Required<RelationGroup.active>>>>.Select(this, 1))
{
if (Convert.ToString(relationGroupRow.GroupMask[0]) == GroupUser)
{
groupsUserDictionary[relationGroupRow.GroupName] = Convert.ToString(relationGroupRow.GroupMask[0]);
break;
}
}
}
foreach (SMPrinter printersRow in PXSelect<SMPrinter, Where<SMPrinter.isActive, Equal<Required<SMPrinter.isActive>>>>.Select(this, 1))
{
foreach (string nameGroup in nameGroupsList)
{
if (groupsUserDictionary.ContainsKey(nameGroup))
{
if (groupsUserDictionary[nameGroup] == Convert.ToString(printersRow.GroupMask[0]))
{
printerName = printersRow.PrinterName;
break;
}
}
}
}
if (String.IsNullOrEmpty(printerName))
{
throw new PXException(Convert.ToString("The user is not active in an impression group"));
}
Dictionary<string, PXReportRequiredException> reportsToPrint = new Dictionary<string, PXReportRequiredException>();
PrintParameters filter = new PrintParameters();
filter.PrintWithDeviceHub = true;
filter.DefinePrinterManually = true;
filter.PrinterName = printerName;
for (int i = 0; i < numberPrint; i++)
{
reportsToPrint = PX.SM.SMPrintJobMaint.AssignPrintJobToPrinter(reportsToPrint, parametersDictionary, filter,
new NotificationUtility(this).SearchPrinter, ARNotificationSource.Customer, reportID, actualReportID, 16);
}
if (reportsToPrint != null)
{
PX.SM.SMPrintJobMaint.CreatePrintJobGroups(reportsToPrint);
}
}
#endregion
}
}
Paso 2 - Lógica extendida para añadir el botón de impresión
using System.Collections;
using System.Collections.Generic;
using PX.Data;
using PX.Objects.IN;
namespace AcumaticaDeviceHub
{
public class InventoryItemMaintSKExt : PXGraphExtension<InventoryItemMaint>
{
public PXAction<InventoryItem> printLabel;
[PXUIField(DisplayName = "Print Item Balance", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
[PXButton(CommitChanges = true)]
public virtual IEnumerable PrintLabel(PXAdapter adapter)
{
PEPrintSLMaint tGPrintGraph = PXGraph.CreateInstance<PEPrintSLMaint>();
Dictionary<string, string> parametersDictionary = new Dictionary<string, string>();
parametersDictionary[PEPrintSLMaint.Fields.Inventory_ID] = this.Base.Item.Current.InventoryCD.Trim();
List<string> ListGroupsFilter = new List<string> { "Group1", "Group2", "Group3" };
tGPrintGraph.PrintReportInDeviceHub("IN615000", "IN615000", ListGroupsFilter, parametersDictionary, null, 1);
return adapter.Get();
}
}
}
Ejemplo Resultado
Cuando el usuario pulsa sobre el nuevo botón Imprimir saldo de elementos, el informe se añade directamente en la cola de impresión:
Y el DeviceHub indica el trabajo que se está imprimiendo:
La lista de las solicitudes de impresión pendientes y procesadas se encuentra en la página Trabajos de impresión:
Conclusión
Aproveche la función Device Hub de Acumatica R1 y versiones posteriores. Imprimir unos pocos documentos al día con esta función no tiene un efecto significativo en muchos casos. Sin embargo, para los almacenes bulliciosos en los que se montan continuamente nuevos palés, cajas y paquetes, unos pocos segundos ahorrados, por solicitud de impresión, suman al final del día. Esto se traduce directamente en una mayor eficiencia y rendimiento. Porque ya sabe lo que dicen: "el tiempo es oro".
*Haga clic en el enlace para descargar el código de ejemplo C# del artículo.