Dynamics AX Blog - Seite 43

Vorsicht beim Mandanten duplizieren

Daß man einen Mandanten/Unternehmen duplizieren kann, ist bekannt. Die Erfahrung der vergangenen Wochen hat mich in dem Zusammenhang folgendes gelehrt:

  • Man sollte der einzige Benutzer im System sein,
  • nur eine(!) aktive Client-Sitzung geöffnet haben und
  • ausreichend Zeit für den Vorgang eingeplant haben, während der das System im exklusiven Zugriff verbleibt.

Um sicherzustellen, daß man der einzige Benutzer im System ist, sollte man alle anderen deaktivieren.

Außerdem sollte man vor dem Kopiervorgang ein Datenbank-Backup anlegen und nach der erfolgten Aktion den Quell- und Zielmandant hinsichltich doppelter Datensätze vergleichen. Hierfür kann man sich der Funktion "Anzahl der Datensätze" bedienen.


 
 

Alle Felder einer Tabelle auflisten

Kurzes Codebeispiel, wie man alle Felder einer Tabelle auflistet:

static void ListFieldOfTable(Args _args)
{
    dictTable   dictTable;
    int         currFieldId = 0;
    counter     c = 0;
    ;
    dictTable = new dictTable(tableNum(custtable));

    do
    {
        currFieldId = dictTable.fieldNext(currFieldId);

        info(dictTable.fieldName(currFieldId));

        c++;
    }
    while (c < dictTable.fieldCnt());
}

 


 
 

Arbeiten mit dem aufrufenden Objekt einer Form (Caller)

Nachstehende Methode enthält einige Snippets, die in einem Formular verwendet werden können, um in Dynamics AX diverse Funktionen/Methoden des Aufrufenden Objektes aufzurufen.

Ändert man element.args() auf z.b. _args und übergibt der Methode diese als Parameter, kann die selbe Logik auch aus einer Klasse heraus verwendet werden.

void workWithCallingRecord()
{
    common          common;
    object          object;
    formDataSource  formDataSource;
    formRun         formRun;
    inventDim       inventDim;
    salesTable      salesTable;
    int             i;
    ;
    // Call method from calling record
    if( element.args() &&
        element.args().record() )
    {
        common = element.args().record();
        if(common.isFormDataSource())
        {
            info(tableId2Name(common.TableId));
            if(formDataSourceHasMethod(common.dataSource(), identifierStr("someMethod")))
            {
                object = common.dataSource();
                object.someMethod();
            }
        }
    }
 

    // Call method from calling form
    if(element.args() && element.args().caller() && element.args().caller().handle() == className2Id('formRun'))
    {
        formRun = element.args().caller();
        if(sysFormRun::hasMethod(formRun, identifierStr("someFormMethod")))
        {
            object = formRun;
            object.someFormMethod();
        }
    }

    // Get value from calling record
    if( element.args() &&
        element.args().record() )
    {
        common = element.args().record();
        if(common.TableId == tableNum(salesTable))
        {
            info(common.(fieldNum(salesTable, salesId)));
        }
    }

    // Get value from calling datasource (form with multiple datasources)
    if(element.args() && element.args().caller() && element.args().caller().handle() == className2Id('formRun'))
    {
        formRun = element.args().caller();
        for (i = 0; i <= formRun.dataSourceCount(); i++)
        {
            formDataSource = formRun.datasource(i);
            if (formDataSource && formDataSource.table() == tablenum(inventDim))    // Search for specific table
            {
                inventDim = formDataSource.cursor();
                break;
            }
        }
        if(inventDim)
        {
            info(inventDim.InventLocationId);
        }
    }

    // Change data in calling datasource
    if(element.args() && element.args().caller() && element.args().caller().handle() == className2Id('formRun'))
    {
        formRun = element.args().caller();
        for (i = 0; i <= formRun.dataSourceCount(); i++)
        {
            formDataSource = formRun.datasource(i);
            if (formDataSource && formDataSource.table() == tablenum(salesTable))    // Search for specific table
            {
                salesTable = formDataSource.cursor();
                break;
            }
        }
        if(salesTable)
        {
            // Update data
            salesTable.PurchOrderFormNum = "Some value";
            salesTable.update();
        }
    }

    // Refresh calling datasource
    if( element.args() &&
        element.args().record() )
    {
        common = element.args().record();
        if(common.isFormDataSource())
        {
            formDataSource = common.dataSource();
            formDataSource.research(true);
        }
    }
}

 
 

Dynamics AX mit einem bestimmten Windowslogin starten

Gegenüber früheren Versionen von Dynamics AX hat man - dank Integration des Active Directories - in AX 2009 kaum Möglichkeiten, die Anwendung als ein bestimmter Benutzer zu starten. Gerade dies ist aber notwendig, wenn man z.B. Änderungen in den Sicherheitseinstellungen/Berechtigungen überprüfen möchte.

Für solche Fälle habe ich mir eine Batch-Datei (*.bat) geschrieben, die mir eine lokale AX-Installation mit einem bestimmten Windows-Login startet. Diese Batch-Datei öffnet ein Windows-Kommandozeilen-Fenster in welchem man zur Eingabe des Windows-Passworts aufgefordert wird.

runas /user:domain\username
    "C:\Programme\Microsoft Dynamics AX\50\Client\Bin\Ax32.exe
    "C:\Programme\Microsoft Dynamics AX\50\MyConfigurationfile.axc""

Wenn man diese Befehlszeile direkt in der Eingabeaufforderung eingeben will, muss man den Befehl wie folgt leicht abwandeln:

runas /user:domain\username
    "C:\Programme\Microsoft Dynamics AX\50\Client\Bin\Ax32.exe
    \"C:\Programme\Microsoft Dynamics AX\50\MyConfigurationfile.axc\""

Muss man ausser der Konfigurationsdatei noch weitere Parameter übergeben, kann man die Batch-Datei wie folgt erweitern:

runas /user:domain\username
    "C:\Programme\Microsoft Dynamics AX\50\Client\Bin\Ax32.exe 
    "C:\Programme\Microsoft Dynamics AX\50\MyConfigurationfile.axc"
    -aol=var
    -aolcode=j+eA4566458bsZReSO1Q=="

Der selbe Befehl sähe, wenn man ihn über die Eingabeaufforderung eingeben wollte, wie folgt aus:

runas /user:domain\username
    "C:\Programme\Microsoft Dynamics AX\50\Client\Bin\Ax32.exe 
    \"C:\Programme\Microsoft Dynamics AX\50\MyConfigurationfile.axc\"
    -aol=var
    -aolcode=j+eA4566458bsZReSO1Q=="

Alternativ dazu kann man sich auch der hier beschriebenen Lösung bedienen.

Übrigens: Sollte die Konfigurationsdatei auf einem Netzlaufwerk liegen, so sollte man bei der Angabe des Dateipfades nicht dessen Laufwerksbuchstaben verwenden, sondern den vollen UNC-Pfad. Denn möglicherweise hat der Benutzer, mit dem ich die Applikation starten möchte, den einzelnen Netzwerklaufwerken andere Laufwerksbuchstaben zugewiesen als man selbst ;-)


 
 

Geänderte oder neue Methoden von Klassen auflisten

Im folgenden findet ihr einen Job, der in einer adaptierten Applikation alle Methoden von Klassen auflistet, die entweder erstellt wurden oder gegenüber dem Standard verändert wurden.

static void ListChangedOrCreatedClassesMethods(Args _args)
{
    SysDictClass    SysDictClass;
    treeNode        treeNode;
    treeNode        treeNodeBase;
    treeNode        treeNodeCustom;
    treeNode        treeNodeClasses;
    UtilEntryLevel  CurrentUtilEntryLevel;

    #AOT
    ;
    treeNodeClasses = TreeNode::findNode(#ClassesPath + #AOTRootPath);
    treeNodeClasses = treeNodeClasses.AOTfirstChild();

    SysDictClass = new SysDictClass((treeNodeClasses.applObjectId()));

    setPrefix('List changed/created classes');

    while(treeNodeClasses)
    {
        SysDictClass = new SysDictClass((treeNodeClasses.applObjectId()));

        setPrefix(SysDictClass.name());

        treeNode = TreeNode::findNode(#ClassesPath + #AOTRootPath + SysDictClass.name() + #AOTRootPath);
        treeNode = treeNode.AOTfirstChild();
        while(treeNode)
        {

            treeNodeBase    = null;
            treeNodeCustom  = null;

            // Partner
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::bup);
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::bus);
            // Solutions
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::sl3);
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::sl2);
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::sl1);
            // Hotfix
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::hfx);
            // Microsoft
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::glp);
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::gls);
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::syp);
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::sys);

            // Custom layers
            if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::vap);   CurrentUtilEntryLevel = UtilEntryLevel::vap; }
            if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::var);   CurrentUtilEntryLevel = UtilEntryLevel::var; }
            if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::cup);   CurrentUtilEntryLevel = UtilEntryLevel::cup; }
            if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::cus);   CurrentUtilEntryLevel = UtilEntryLevel::cus; }
            if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::usp);   CurrentUtilEntryLevel = UtilEntryLevel::usp; }
            if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::usr);   CurrentUtilEntryLevel = UtilEntryLevel::usr; }

            // Changed methods
            if(treeNodeBase)
            {
                if( treeNodeBase.AOTgetSource() != treeNode.AOTgetSource())
                {
                    warning(strFmt( "Method '%1' was changed in layer '%2'.",
                                    treeNode.treeNodeName(),
                                    enum2str(CurrentUtilEntryLevel)));
                }
            }

            // New created methods
            if( !treeNodeBase)
            {
                info(strFmt( "Method '%1' was created in layer '%2'.",
                             treeNode.treeNodeName(),
                             enum2str(CurrentUtilEntryLevel)));
            }

            treeNode = treeNode.AOTnextSibling();
        }

        treeNodeClasses = treeNodeClasses.AOTnextSibling();
    }
}

Ein ähnlicher Job der prinzipiell das Gleiche erledigt, allerdings für alle Tabellenmethoden, ist hier zu finden.


 
 

Geänderte oder neue Methoden von Tabellen auflisten

Im folgenden findet ihr einen Job, der in einer adaptierten AX 2009er-Applikation alle Tabellenmethoden auflistet, die entweder erstellt wurden oder gegenüber dem Standard verändert wurden.

static void ListChangedOrCreatedTableMethods(Args _args)
{
    SysDictTable    SysDictTable;
    treeNode        treeNode;
    treeNode        treeNodeBase;
    treeNode        treeNodeCustom;
    treeNode        treeNodeTables;
    UtilEntryLevel  CurrentUtilEntryLevel;
    #AOT
    ;
    treeNodeTables = TreeNode::findNode(#TablesPath + #AOTRootPath);
    treeNodeTables = treeNodeTables.AOTfirstChild();

    setPrefix('List changed/created tablemethods');

    while(treeNodeTables)
    {
        SysDictTable = SysDictTable::newTableId(tableName2Id(treeNodeTables.treeNodeName()));

        setPrefix(SysDictTable.name());

        treeNode = TreeNode::findNode(#TablesPath + #AOTRootPath + SysDictTable.name() + #AOTRootPath + "Methods");
        treeNode = treeNode.AOTfirstChild();
        while(treeNode)
        {
            treeNodeBase    = null;
            treeNodeCustom  = null;

            // Partner
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::bup);
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::bus);
            // Solutions
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::sl3);
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::sl2);
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::sl1);
            // Hotfix
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::hfx);
            // Microsoft
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::glp);
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::gls);
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::syp);
            if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::sys);

            // Custom layers
            if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::vap);   CurrentUtilEntryLevel = UtilEntryLevel::vap; }
            if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::var);   CurrentUtilEntryLevel = UtilEntryLevel::var; }
            if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::cup);   CurrentUtilEntryLevel = UtilEntryLevel::cup; }
            if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::cus);   CurrentUtilEntryLevel = UtilEntryLevel::cus; }
            if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::usp);   CurrentUtilEntryLevel = UtilEntryLevel::usp; }
            if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::usr);   CurrentUtilEntryLevel = UtilEntryLevel::usr; }

            // Changed methods
            if(treeNodeBase)
            {
                if( treeNodeBase.AOTgetSource() != treeNode.AOTgetSource())
                {
                    warning(strFmt( "Method '%1' was changed in layer '%2'.",
                                    treeNode.treeNodeName(),
                                    enum2str(CurrentUtilEntryLevel)));
                }
            }

            // New created methods
            if( !treeNodeBase)
            {
                info(strFmt( "Method '%1' was created in layer '%2'.",
                             treeNode.treeNodeName(),
                             enum2str(CurrentUtilEntryLevel)));
            }

            treeNode = treeNode.AOTnextSibling();
        }

        treeNodeTables = treeNodeTables.AOTnextSibling();
    }
}

Ein ähnlicher Job der prinzipiell das Gleiche erledigt, allerdings für alle Klassenmethoden, ist hier zu finden.


 
 

Erstellen und Buchen eines Umlagerungsjournal in AX 2009 mit Erfassung und Entnahme

In einem früheren Beitrag habe ich anhand eines kurzen Code-Beispiels demonstriert, wie man in AX 2009 ein Umlagerungsjournal per Code erstellen und buchen kann. Im folgenden findet Ihr ein Beispiel welches, soferne es die Lagersteuerungsgruppe des Artikel erfordert, sich auch um die zugehörige Entnahme- und -Erfassungsbuchung kümmert.

static void createAndPostInventJournalTransfer_II(Args _args)
{
    inventJournalTable  inventJournalTable;
    inventJournalTrans  inventJournalTrans;
    journalCheckPost    journalCheckPost;
    itemId              _itemId             = "9992";
    qty                 _qty                = 1;
    inventDimId         _fromInventDimId    = "00008328_069";
    inventDimId         _toInventDimId      = "00008342_069";

    tmpInventTransWMS   tmpInventTransWMS;
    inventTRans         inventTRans;

    InventTransWMS_Pick     inventTransPick;
    InventTransWMS_Register inventTransRegister;
    ;

    try
    {
        ttsbegin;

        // Create header
        inventJournalTable.clear();
        inventJournalTable.initValue();

        inventJournalTable.initFromInventJournalName(
            InventJournalName::find(InventJournalName::standardJournalName(InventJournalType::Transfer)));

        inventJournalTable.SystemBlocked    = NoYes::Yes;
        inventJournalTable.BlockUserId      = curUserId();

        inventJournalTable.insert();

        // Create line
        inventJournalTrans.clear();

        inventJournalTrans.initValue();
        inventJournalTrans.initFromInventJournalTable(inventJournalTable);

        inventJournalTrans.ItemId           = _itemId;
        inventJournalTrans.initFromInventTable(inventTable::find(inventJournalTrans.ItemId));

        inventJournalTrans.Qty              = _qty;

        inventJournalTrans.inventMovement().journalSetCostPrice();

        inventJournalTrans.inventDimId      = _fromInventDimId;
        inventJournalTrans.toinventDimId    = _toInventDimId;

        inventJournalTrans.voucher          = numberSeq::newGetVoucherFromCode(
                                                    InventJournalName::find(inventJournalTable.JournalNameId).VoucherSeqId).voucher();

        inventJournalTrans.insert();

        if(inventModelGroup::find(inventTable::find(_itemId).ModelGroupId).MandatoryPick)
        {
            // Picking
            inventTrans.clear();
            inventTrans = inventTrans::findTransId(inventJournalTrans.InventTransId);

            tmpInventTransWMS.clear();
            tmpInventTransWMS.initFromInventTrans(inventTrans);

            tmpInventTransWMS.InventQty = inventTrans.StatusIssue == StatusIssue::Picked ? inventTrans.Qty : -inventTrans.Qty;
            if (tmpInventTransWMS.validateWrite())
            {
                tmpInventTransWMS.write();
            }

            inventTranspick = new InventTransWMS_Pick(inventTRans.inventMovement(),tmpInventTransWMS);
            inventTranspick.writeTmp(tmpInventTransWMS,tmpInventTransWMS.orig(),false);

            InventTransWMS_Pick::updateInvent(inventTransPick, tmpInventTransWMS);
        }

        if(inventModelGroup::find(inventTable::find(_itemId).ModelGroupId).MandatoryRegister)
        {
            // Registration
            inventTrans.clear();
            inventTrans = inventTrans::findTransId(inventJournalTrans.toInventTransId);

            tmpInventTransWMS.clear();
            tmpInventTransWMS.initFromInventTrans(inventTrans);

            tmpInventTransWMS.InventQty = inventTrans.StatusReceipt == StatusReceipt::Ordered ? inventTrans.Qty : -inventTrans.Qty;
            if (tmpInventTransWMS.validateWrite())
            {
                tmpInventTransWMS.write();
            }

            inventTransRegister = new InventTransWMS_Register(inventTrans.inventMovement(),tmpInventTransWMS);
            inventTransRegister.writeTmp(tmpInventTransWMS,tmpInventTransWMS.orig(),false);

            InventTransWMS_Register::updateInvent(inventTransRegister, tmpInventTransWMS);
        }

        // Post journal
        journalCheckPost = InventJournalCheckPost::newJournalCheckPost(JournalCheckPostType::Post, inventJournalTable);
        journalCheckPost.run();

        ttscommit;
    }
    catch (Exception::Error)
    {
        throw exception::Error;
    }
}

 
 
Seiten « 1 ... 40 41 42 43 44 45 46 ... 53 » 

 

 
 
 
Beiträge des aktuellen Monats
Mai 2024
MoDiMiDoFrSaSo
 12345
6789101112
13141516171819
20212223242526
2728293031 
 
© 2006-2024 Heinz Schweda | Impressum | Kontakt | English version | Mobile Version
Diese Webseite verwendet Cookies, um Benutzern einen besseren Service anzubieten. Wenn Sie weiterhin auf der Seite bleiben, stimmen Sie der Verwendung von Cookies zu.  Mehr dazu