Configuration du concentrateur d'appareils

Fernando Amadoz | 25 mars 2022

Il s'avère que le cliché "plus on est defous, plus on rit" n'est pas toujours vrai - ni approprié d'ailleurs. Par exemple, en ce qui concerne le trafic, les hypothèques, les "influenceurs" d'IG et... le nombre de clics de souris nécessaires pour réaliser une activité dans un système logiciel, plus n'est certainement pas mieux.

Lorsque les systèmes sont déployés dans de grands entrepôts très fréquentés, les utilisateurs préfèrent souvent passer directement de l'écran Acumatica à l'imprimante en un seul clic. Dans Acumatica, par défaut, ce processus nécessite au moins quelques clics supplémentaires et quelques secondes d'attente pendant le chargement de la fenêtre de prévisualisation avant que le document ne soit réellement imprimé.

Configuration du concentrateur d'appareils

À partir de la version 2018 R1, Acumatica a inclus la fonctionnalité Device Hub qui est un processus fonctionnant constamment en arrière-plan, interrogeant les nouveaux documents à imprimer, afin qu'ils puissent passer d'Acumatica à la file d'attente de l'imprimante en un seul clic.

Dans cet article de blog, nous allons passer en revue le processus nécessaire pour y parvenir en examinant l'installation, la configuration et quelques bons vieux exemples de code.

Installation du concentrateur de périphériques d'impression

Lorsque l'assistant de configuration d'Acumatica ERP est lancé au cours du processus d'installation, l'une des fonctions de configuration disponibles est Install DeviceHub. Assurez-vous que cette case est cochée et poursuivez ensuite le reste de l'installation comme il se doit.

Installer DeviceHub

Configuration de l'imprimante dans le serveur

Étant donné que toute cette configuration est effectuée sur un nouveau serveur, nous devons nous assurer qu'au moins une imprimante est correctement configurée et opérationnelle. Dans ce cas, nous utiliserons l'imprimante Microsoft Printer to PDF (redirected 2 ).

Configuration de l'imprimante dans le serveur

Nous vérifions qu'un document test est correctement ajouté à la file d'attente de l'imprimante :

Vérifier qu'un document test est correctement ajouté à la file d'attente de l'imprimante

Configuration de l'environnement

Dans la page Enable/Disable Features (CS100000), assurez-vous que l'option DeviceHub est sélectionnée :

Configuration de l'environnement

L'application DeviceHub elle-même comporte deux onglets à configurer : le site et les imprimantes.

Configuration du DeviceHub
Configuration du DeviceHub

Veuillez noter que le DeviceHub étant un processus exécuté en permanence en arrière-plan pour demander au système s'il y a de nouvelles informations à ajouter à la file d'attente de l'imprimante, il est pratique de créer un utilisateur spécifique à cette fin.

Après avoir appuyé sur OK, le DeviceHub commence à fonctionner et à interroger les nouveaux documents à imprimer.

DeviceHub est en cours d'exécution et interroge les nouveaux documents à imprimer.

Notez également que si la fenêtre DeviceHub est fermée, le processus continuera à s'exécuter en arrière-plan. Pour l'arrêter, il convient d'utiliser le gestionnaire de tâches.

Statut du DeviceHub

Configuration Acumatica

La première chose à faire est de rendre l'imprimante disponible dans Acumatica. Cela se fait à partir de la page Imprimantes (SM206510).

Dans cette page, le bouton Mettre à jour la liste des imprimantes est utilisé pour remplir la grille avec les imprimantes précédemment définies dans le DeviceHub.

Configuration Acumatica

Si aucun résultat n'est visible dans la grille après avoir appuyé sur le bouton " Mettre à jour la liste des imprimantes ", le bouton "Annuler" doit être utilisé pour rafraîchir la grille.

Cette opération met à jour la liste des imprimantes disponibles dans le DeviceHub.

Liste des imprimantes disponibles dans le DeviceHub

Les imprimantes étant déjà disponibles dans Acumatica, l'étape suivante consiste à affecter les différents utilisateurs aux différentes imprimantes. Par exemple, cela permettra à l'équipe administrative d'utiliser une imprimante, et à l'équipe des préparateurs de commandes de l'entrepôt d'utiliser une autre imprimante séparée dans un endroit différent. Cette opération s'effectue dans la page d'accès à l'imprimante (SM106000).

Cette page est composée de deux onglets : les utilisateurs et les imprimantes associées.

Les utilisateurs et les imprimantes associées

Notez que les utilisateurs sélectionnés dans le groupe ne nécessitent pas l'inclusion de l'utilisateur DeviceHub précédemment créé, car ils ont des objectifs différents : le premier est utilisé pour identifier l'imprimante à utiliser et le second est utilisé pour interroger les travaux dans la file d'attente.

Notez également que les imprimantes et les utilisateurs peuvent appartenir à plusieurs groupes. L'effet de cette configuration est visible dans le champ GroupMask de la table RelationGroup, où une combinaison de valeurs binaires permet au système d'identifier correctement l'imprimante à utiliser.

Une fois tous les réglages et configurations terminés, nous allons étendre la page Inventaire et ajouter un nouveau bouton permettant d'imprimer un rapport :

Étape 1 - Un graphique est créé pour gérer la logique d'impression :


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
    }
}

Étape 2 - Logique étendue pour ajouter le bouton d'impression


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();
        }
    }
}

Exemple de résultat

Imprimer la balance des postes

Lorsque l'utilisateur appuie sur le nouveau bouton Imprimer le solde de l'élément, le rapport est ajouté directement dans la file d'attente de l'imprimante :

File d'attente de l'imprimante

Et le DeviceHub indique le travail en cours d'impression :

DeviceHub indique le travail en cours d'impression

La liste des demandes d'impression en attente et traitées se trouve dans la page Travaux d'impression:

Page des travaux d'impression

Conclusion

Tirez parti de la fonction Device Hub dans Acumatica R1 et les versions ultérieures. L'impression de quelques documents par jour à l'aide de cette fonctionnalité n'a pas d'effet significatif dans de nombreux cas. Cependant, pour les entrepôts en pleine effervescence où de nouvelles palettes, boîtes et paquets sont continuellement assemblés, les quelques secondes gagnées, par demande d'impression, s'additionnent à la fin de la journée. Cela se traduit directement par une augmentation de l'efficacité et des performances. Car vous savez ce que l'on dit : "le temps, c'est de l'argent".


*Cliquez sur le lien pour télécharger l'exemple de code C# de l'article.

 

 

Auteur du blog

Fondateur et PDG de SkyKnack, un fournisseur de solutions ERP qui aide les partenaires Acumatica à développer des personnalisations, des intégrations et de nouveaux produits, ainsi que des services de mise en œuvre et de formation.

Recevez les mises à jour du blog dans votre boîte de réception.