Dynamics AX Blog - Microsoft Dynamics AX (Axapta) - Seite 2

In den letzten Jahren, in denen ich mich fast hauptsächlich mit der Entwicklung im Umfeld von Microsoft Dynamics AX (vormals Axapta) beschäftigt habe, ist das eine oder andere Code-Fragment entstanden, von dem ich mir vorstellen könnte, daß es auch für andere AX-Entwickler ganz nützlich sein könnte. Aber auch Tips und Tricks zu dem mächtigen ERP-System werde ich in dieser Kategorie präsentieren.
RSS-Feed dieser KategorieAufträge an Lagerort freigebenUm für einen oder mehrere Aufträge per Code die Funktion "Für Lagerort freigeben" aufzurufen, kann man sich des folgende Codes bedienen.
![]() |
Eintrag "RPC exception 1702 occurred" im Eventlog
Dieser Eintrag kann auf die Verwendung von client-seitigem Code am Server hindeuten, beispielsweise den Aufruf einer WinApi-Funktion aus einem Stapeljob heraus. Sie kann aber auch durch den Aufruf von info(), Warning() oder error() innerhalb eines Stapeljobs ausgelöst werden, wenn am jeweiligen AOS die Option "Enable global breakpoint" aktiviert ist. |
SQL-Fehler beim Synchronisieren nach Update von AX 2012 auf CU13Während des Upgrades einer AX 2012 R3 CU9-Instanz auf CU13 (February Release) hatte ich beim Punkt Datenbank synchronisieren der Upgrade-Checklist folgenden Fehler:
Die Lösung ist, diesen fehler fürs erste so zu belassen und mit dem nächsten Schritt der Checklist, dem Data upgrade zu starten. Einer der auszuführenden Jobs bereinigt nämlich jene Datensätze, die zu dem genannten Fehler führen. Nach dem Datenupgrade kann man nun die Datenbank fehlerfrei synchronisieren. |
SysOperation-Framework: ExecutionMode und auszuführende Servermethode über das MenuItem steuernWenn man in einem SysOperation-Konstrukt den SysOperationExecutionMode und/oder die auszuführende Servermethode über das MenuItem steuern möchte, kann man dies über die Eigenschaften des MenuItems steuern. Szenario: Ohne eigenen ControllerDie folgenden beiden MenuItems zeigen, wie man dafür die Eigenschaften setzen kann: Dieses MenuItem ruft die Methode runService() einer Serviceklasse auf und setzt den SysOperationExecutionMode auf Synchronous: |
SysOperation-Framework: Stapelverarbeitung erzwingenWenn man sicherstellen möchte, daß eine Funktion die über das SysOperation-Framework umgesetzt wurde, immer über die Stapelverarbeitung ausgeführt wird, kann man den SysOperationExecutionMode auf ScheduledBatch setzen (beispielsweise über das MenuItem des Controllers - siehe hier). Handelt es sich dabei um eine Funktion, die einen Benutzerdialog erfordert, hat man allerdings das Problem, daß standardmässig der Register "Stapel" eingeblendet wird und dort aber beispielsweise das Kontrollkästchen Stapel nicht aktiviert ist. Natürlich kann man dieses Kontrollkästchen nun aktivieren, in dem man einen Aufruf von parmBatchExecute() im UIBuilder integriert: public void build() { super(); this.controller().batchInfo().parmBatchExecute(this.controller().parmExecutionMode() == SysOperationExecutionMode::ScheduledBatch); } |
Erstellen und Buchen einer Freitextrechnung per CodeDer nachstehende Job soll zeigen, wie man per Code eine Freitextrechnung erstellen und buchen kann. static void createAndPostFreeTextInvoice(Args _args) { CustInvoiceTable custInvoiceTable; CustInvoiceLine custInvoiceLine; DimensionDefault dimensionDefault; LedgerDimensionAccount ledgerDimensionAccount; CustPostInvoice custPostInvoice; try { ttsBegin; // Create header custInvoiceTable.clear(); custInvoiceTable.initValue(); custInvoiceTable.OrderAccount = "US-004"; custInvoiceTable.modifiedField( fieldNum(CustInvoiceTable, OrderAccount)); custInvoiceTable.insert(); // Create line custInvoiceLine.clear(); custInvoiceLine.initValue(); custInvoiceLine.ParentRecId = custInvoiceTable.RecId; custInvoiceLine.initFromCustInvoiceTable(custInvoiceTable); custInvoiceLine.Description = "Test"; custInvoiceLine.Quantity = 10; custInvoiceLine.modifiedField( fieldNum(CustInvoiceLine, Quantity)); custInvoiceLine.UnitPrice = 200; custInvoiceLine.modifiedField( fieldNum(CustInvoiceLine, UnitPrice)); ledgerDimensionAccount = DimensionDefaultingService::serviceCreateLedgerDimension( DimensionStorage::getDefaultAccountForMainAccountNum( "110110"), dimensionDefault); custInvoiceLine.LedgerDimension = ledgerDimensionAccount; custInvoiceLine.modifiedField( fieldNum(CustInvoiceLine, LedgerDimension)); custInvoiceLine.insert(); // Post custPostInvoice = new CustPostInvoice(custInvoiceTable); custPostInvoice.run(); ttsCommit; } catch { throw error(error::wrongUseOfFunction(funcName())); } } So sieht eine wie oben erstellte Freitextrechnung aus: |
Debuggen von SSRS-Dataprovider die von SrsReportDataProviderPreProcess abgeleitet sindIn diesem Beitrag habe ich schon einmal beschrieben, wie man einen DataProvider "debuggen" kann, der von SRSReportDataProviderBase abgeleitet ist. Der folgende Job macht prinzipiell das gleiche, allerdings für vorverarbeitete Reports, also welche wo der DataProvider von SrsReportDataProviderPreProcess abgeleitet ist. Im Beispiel verwende ich den DataProvider einer Ausgangsrechnung (SalesInvoice). static void testSSRSDataProvider_SalesInvoice(Args _args) { SalesInvoiceTmp salesInvoiceTmp; SalesInvoiceDP dataProvider = new SalesInvoiceDP(); SalesInvoiceContract contract; CustInvoiceJour CustInvoiceJour = CustInvoiceJour::findRecId(35637191172); UserConnection UserConnection; try { ttsBegin; UserConnection = new UserConnection(); contract = new SalesInvoiceContract(); contract.parmFormLetterRecordId(CustInvoiceJour.RecId); contract.parmRecordId(CustInvoiceJour.RecId); dataProvider = new SalesInvoiceDP(); dataProvider.parmDataContract(contract); dataProvider.parmUserConnection(UserConnection); dataProvider.processReport(); salesInvoiceTmp = dataProvider.getSalesInvoiceTmp(); while select salesInvoiceTmp where SalesInvoiceTmp.createdTransactionId == appl.curTransactionId() { info(strFmt("%1 %2", SalesInvoiceTmp.InvoiceId, SalesInvoiceTmp.ItemId)); } ttsCommit; } catch (Exception::Break) { info("Aborted"); } }
|
|
|
|
|
|
|