Das Erstellen von Produktionsaufträgen sollte an sich kein Problem darstellen. Leider ist dem nicht ganz so.
Anders als in anderen Modulen (z.B. Aufträge) von Dynamics AX, existiert hierfür keine Klassenstruktur, welche die entsprechenden Funktionen bereit stellt. Der Dynamics AX Standard erstellt Produktionsaufträge immer über die Maske „ProdTableCreate“. Es gibt aber Situationen, wo für die Erstellung eines Produktionsauftrages keine Maske verwendet werden kann. Ein Beispiel hierfür könnte eine Schnittstelle sein, welche über eine Textdatei die zu produzierenden Waren einließt und entsprechende Produktionsaufträge im System generiert.
Die Frage ist nun, wie erstellt man Produktionsaufträge per Quellcode, damit diese auch „richtig“ im System erzeugt werden (inkl. Stückliste, Arbeitsplan und Lagerbuchung).
- Zuerst muss der Produktionsauftrag mit den Daten des zu produzierenden Artikels initialisiert werden.
- Weiterhin müssen Produktionsmenge und Lieferdatum festgelegt werden.
- Ebenfalls sind die zu verwendende Stückliste und der Arbeitsplan zu definieren.
- Und als letzter Schritt muss der Produktionsauftrag noch erzeugt werden.
Hierbei gilt es aber zu beachten, dass die Erstellung (Speichern in der Datenbank) nicht mit der Methode „insert“ der Tabelle „ProdTable“ geschieht, sondern dass hierfür die Klasse „ProdTableType“ und deren Methode „insert“ verwendet wird. Nur so wird die entsprechende Lagerbewegung / Lagerbuchung im System erzeugt und wenn notwendig Referenzen zu einem Verkaufsauftrag oder einer anderen Produktion hinterlegt.
Um dies zu veranschaulichen ein kurzes Beispiel, in welchem ein neuer Produktionsauftrag erstellt wird.
static void CreateProductionOrder(Args _args) { //Die zu produzierende Menge ProdQtySched productionQty = 1; //Der zu produzierende Artikel ItemId productionItem = "Artikelnummer";
ProdTable prodTable; InventTable inventTable; ; inventTable = InventTable::find(productionItem);
//Initialisierung des Produktionsauftrags prodTable.initValue(); prodTable.ItemId = inventTable.ItemId; prodTable.initFromInventTable(inventTable);
//Lieferdatum festlegen prodTable.DlvDate = today();
prodTable.QtySched = productionQty; prodTable.RemainInventPhysical = prodTable.QtySched;
//Die zu verwendende Stückliste und Arbeitsplan bestimmen prodTable.initRouteVersion(); prodTable.initBOMVersion();
//Produktionsauftrag erstellen prodTable.type().insert(); }
Selbstverständlich sind auch weitere Angaben bei der Erstellung des Produktionsauftrags möglich. Z.B. kann ein Produktionsauftrag auch aus einer Verkaufsauftragsposition erzeugt werden (bei Verwendung der Methode "initFromSalesLine").
Das Buchen von Bestellungen in Microsoft Dynamics AX geschieht über die Klasse „PurchFormLetter“ bzw. einer ihrer konkretisierten (abgeleiteten) Klassen. Jeder Buchungstyp (z.B. Bestätigung oder Rechnung) ist durch eine eigene Klasse abgebildet, welche von der Basisklasse „PurchFormLetter“ abgeleitet ist (siehe Abbildung).

Abbildung 1 - Klassenhierarchie der Klasse „PurchFormLetter“
Vergleicht man die Klassenhierarchie der „PurchFormLetter“ Klassen mit der Klassenhierarchie der „SalesFormLetter“ Klassen, so ist zu erkennen, dass auch das Buchen von Bestellungen vom Prinzip her genau so funktioniert wie das Buchen von Aufträgen (Vergleiche hierzu: Microsoft Dynamics AX API – Teil 3 „Buchen von Aufträgen“).
Deswegen sind auch für das Buchen von Bestellungen im Wesentlichen nur zwei Schritte notwendig.
- Über die Methode „construct“ der Klasse „PurchFormLetter“ ein dem Buchungstyp einsprechendes Objekt erzeugen.
- Über den Aufruf der Methode „update“ die Bestellung buchen.
Hierzu ein Beispiel (Buchen des Lieferscheins für eine Bestellung):
static void PurchPostPackingSlip(Args _args) { PurchFormLetter purchFormLetter; PurchTable purchTable; PurchId purchId; Num packingSlipId; ; //Angabe der Bestellung, für welche der Lieferschein gebucht werden soll. purchId = "00244_049"; purchTable = PurchTable::find(purchId);
//Bestimmen des Buchungstyps durch Angabe des DocumentStatus (Lieferschein). purchFormLetter = PurchFormLetter::construct(DocumentStatus::PackingSlip);
//Festlegen der externen Lieferscheinnummer. packingSlipId = "EXT-100155L";
//Buchen des Lieferscheins. purchFormLetter.update(purchTable, packingSlipId, SystemDateGet(), PurchUpdate::All, AccountOrder::Auto, NoYes::No, NoYes::No, NoYes::No, NoYes::No); }
Einziger Unterschied zu den Auftragsbuchen ist, dass bei der Buchung einer Bestellung die „externe“ Nummer des Belegs (Lieferscheinnummer, Rechnungsnummer, etc.) angegeben werden muss.
Analog zu den Auftragsbuchen, sind auch beim Buchen von Bestellungen umfangreichere oder etwas speziellere Buchungsszenarien möglich (Vergleiche hierzu: Microsoft Dynamics AX API – Teil 3 „Buchen von Aufträgen“).
Das Buchen von Aufträgen in Microsoft Dynamics AX geschieht über die Klasse „SalesFormLetter“ bzw. einer ihrer konkretisierten (abgeleiteten) Klassen. Jeder Buchungstyp (z.B. Bestätigung, Lieferschein, Rechnung) ist durch eine eigene Klasse abgebildet, welche von der Basisklasse „SalesFormLetter“ abgeleitet ist (siehe Abbildung).

Um einen Auftrag per Programmcode zu buchen, muss ein Objekt der Klasse „SalesFormLetter“ erstellt werden.
salesFormLetter = SalesFormLetter::construct(DocumentStatus::Confirmation);
Dies geschieht, wie Allgemein in Microsoft Dynamics AX üblich, über die “construct” Methode der Klasse. Als Parameter muss dieser Methode die gewünschte Art der Buchung (z.B. Bestätigung, Lieferschein, Rechnung) angegeben werden. Die „construct“ Methode erzeugt ein,der Buchungsart entsprechendes, Objekt und gibt dieses zurück (In diesem Fall wird ein „SalesFormLetter_Confirm“ Objekt erzeugt). Die eigentliche Buchung wird über die Methode „update“ aufgerufen. Da dieser Methode alle für die Buchung notwendigen Daten als Parameter übergeben werden können, ist eine einzelne Zuweisung von z.B. dem Auftrag, welcher gebucht werden soll, nicht notwendig.
Hierzu ein Beispiel:
// --- Buchen ohne Ausdruck --- static void PostingConfimation(Args _args) { SalesFormLetter salesFormLetter; SalesTable salesTable; SalesId salesId; PrintJobSettings printJobSettings; ; //Angabe des Auftrags, welcher gebucht werden soll. salesId = "00423_036"; salesTable = SalesTable::find(salesId);
// Bestimmen des Buchungstyps durch Angabe des DocumentStatus salesFormLetter = SalesFormLetter::construct(DocumentStatus::Confirmation);
//Buchen des Auftrags (aber nicht Drucken). salesFormLetter.update(salesTable, SystemDateGet(), SalesUpdate::All, AccountOrder::None, NoYes::No, NoYes::No); }
Bei diesem Beispiel ist gut zu sehen, dass für die Buchung eines Auftrags im Wesentlichen nur zwei Schritte notwendig sind.
-
Über die Methode „construct“ ein dem Buchungstyp einsprechendes Objekt erzeugen.
-
Über den Aufruf der Methode „update“ den Auftrag buchen.
Natürlich können auch noch umfangreichere oder etwas speziellere Buchungsszenarien mit der Klasse „salesFormLetter“ abgebildet werden. So ist es z.B. möglich, gleich bei der Buchung entsprechende Dokumente auszudrucken (einmal, mehrfach und in verschiedene Formate), die Maske für die Buchung zu öffnen (damit der Benutzer Einfluss auf die Buchung nehmen kann) oder die Buchung nicht direkt auszuführen, sondern diese für die Stapelverarbeitung bereit zu stellen.
Damit es nicht zu komplex wird, kurz noch ein Beispiel zum Buchung und gleichzeitigen ausdrucken entsprechender Dokumente.
// --- Buchen mit Ausdruck --- static void PostingConfimation(Args _args) { SalesFormLetter salesFormLetter; SalesTable salesTable; SalesId salesId; PrintJobSettings printJobSettings; ; //Angabe des Auftrags, welcher gebucht werden soll. salesId = "00423_036"; salesTable = SalesTable::find(salesId); salesFormLetter = SalesFormLetter::construct(DocumentStatus::Confirmation);
//Buchen des Auftrags und drucken (Druckmedium aus Std. Einstellung). salesFormLetter.update(salesTable, SystemDateGet(), SalesUpdate::All, AccountOrder::None, NoYes::No, NoYes::Yes);
//2ter Ausdruck. printJobSettings = new PrintJobSettings(salesFormLetter.printerSettingsFormletter( PrintSetupOriginalCopy::Original)); //Wohin möchten wir drucken (hier Datei). printJobSettings.setTarget(PrintMedium::File);
//In welches Format soll gedruckt werden (hier PDF). printJobSettings.format(PrintFormat::PDF); printJobSettings.fileName(@"C:\Test_Order.pdf");
//Übergabe der Druckoptionen an das SalesFormLetter Objekt. salesFormLetter.updatePrinterSettingsFormLetter(printJobSettings.packPrintJobSettings());
salesFormLetter.printJournal(); }
Eine Bestellung umfasst in Microsoft Dynamics AX immer einen Datensatz der Tabelle „PurchTable“ und wenn die Bestellung einen Artikel enthält, auch einen Datensatz in der Tabelle „PurchLine“. Zusätzlich werden in Abhängigkeit von den Daten der Bestellung (Einmallieferant: Ja/Nein, Intercompany: Ja/Nein, etc.) zusätzliche Datensätze in anderen Tabellen erzeugt bzw. geändert. Beispielhaft sei hier die Tabelle „VendTable“ genannt. In dieser wird ein neuer Lieferant erstellt, wenn beim Erstellen der Bestellung angegeben wurde, dass es sich um einen Einmallieferanten handelt. Ein weiteres Beispiel wäre die Tabelle „MarkupTrans“ in der in Abhängigkeit von den Einstellungen für sonstige Zuschläge ebenfalls weitere Datensätze erzeugt werden.
Die Logik, die das Erstellen der einzelnen Datensätze der verschiedenen Tabellen steuert wird in Microsoft Dynamics AX durch die Klassen „PurchTableType“ (Abbildung 1) und „PurchLineType“ (Abbildung 2), sowie deren abgeleiteten Klassen abgebildet. Diese Klassen steuern das Verhalten bei Anlage, Änderung und Löschung einer Bestellung. Dies beinhaltet auch, welche Werte ein Feld bei welchem Bestellungstyp annehmen darf, was geschieht wenn ein Feld geändert wird, was wird wie gebucht und so weiter.


Diese Klassen werden von überschriebenen Methoden der Tabellen „PurchTable“ und „PurchLine“ aufgerufen. So ruft zum Beispiel die Methode „Insert“ der Tabelle „PurchTable“, die Methode „Insert“ der Klasse „PurchTableType“ auf. Abhängig vom Bestellungstyp wird über die Methode „construct“ bei der Initialisierung eines „PurchTableType“ Objekts gesteuert, welches konkrete Objekt erzeugt wird („PurchTableType_Purch“, „PurchTableType_ReturnItem“, etc.). Dies erfolgt in der Methode „type“ der Tabelle „PurchTable“ oder „PurchLine“. Unter anderem sind weiterhin die Methoden „Update“, „Delete“, „InitValue“, „ValidateField“ und „Delete“ auf die gleiche Weise überschrieben. Ein Blick in die Methoden der Tabelle „PurchTable“ sollte dies verdeutlichen.
Somit ist die Logik, die für die Steuerung von Bestellungen in Microsoft Dynamics AX verantwortlich ist, vom Prinzip her vergleichbar mit der Logik welche die Aufträge „steuert“ (vergleiche hierzu: Microsoft Dynamics AX API – Teil 1 „Erstellen von Aufträgen“).
Deswegen ist das Erstellen einer Bestellung genau so einfach wie das Erstellen eines Auftrags. Um eine neue Bestellung zu erstellen muss im Wesentlichen nur:
- Eine neue Nummer des entsprechenden Nummernkreises gezogen werden.
- Die Methode „InitValue“ der Tabelle „PurchTable“ aufgerufen werden.
- Die Methode „InitFromVendTable“ der Tabelle „PurchTable“ mit Angabe des Lieferanten Datensatzes aufgerufen werden.
- Die Methode „Insert“ der Tabelle „PurchTable“ aufgerufen werden.
Soll für diese gerade erzeugte Bestellung nun noch eine Artikelposition erzeugt werden, muss im Wesentlichen nur die Methode „CreateLine“ der Tabelle „PurchLine“, mit vorheriger Definition von Bestellungsnummer („PurchLine.PurchId“) und Artikelnummer („PurchLine.ItemId“), aufgerufen werden.
Hierzu ein Beispiel:
void createPurchTableAndLine() { VendAccount vendAccount = "<yourVendAccount>"; ItemId itemId = "<yourItemId>";
PurchTable purchTable; PurchLine purchLine; NumberSeq numberSeq; InventTable inventTable; ; //Bestellungskopf (PurchTable) //Neue Bestellungsnummer aus Nummernkreis erzeugen NumberSeq = NumberSeq::newGetNumFromCode( PurchParameters::numRefPurchId().numberSequence); purchTable.PurchId = NumberSeq.num();
//Bestellungskopf initialisieren purchTable.initValue();
//Initialisierung der lieferantenspezifischen Bestellungsdaten purchTable.initFromVendTable(VendTable::find(vendAccount));
//Bestellungskopf erstellen purchTable.insert();
//Bestellungsposition (PurchLine) purchLine.clear();
//Zuweisen von Bestellungsnummer und Artikelnummer purchLine.purchId = purchTable.PurchId; purchLine.ItemId = itemId;
//Bestellungsposition erstellen (ruft PurchLine.insert auf) purchLine.createLine(NoYes::Yes, NoYes::Yes, NoYes::Yes, NoYes::Yes, NoYes::Yes, NoYes::Yes); }
Ein Auftrag umfasst in Microsoft Dynamics AX immer einen Datensatz in der Tabelle „SalesTable“ (Auftragskopf) und wenn der Auftrag einen Artikel enthält (Auftragsposition), auch einen Datensatz in der Tabelle „SalesLine“. Zusätzlich werden in Abhängigkeit von den Daten des Auftrags (Einmalkunde: Ja/Nein, Intercompany: Ja/Nein, etc.) zusätzliche Datensätze in anderen Tabellen erzeugt bzw. geändert. Beispielhaft sei hier die Tabelle „CustTable“ genannt. In dieser wird ein neuer Kunde erstellt, wenn beim Erstellen des Auftrags angegeben wurde, dass es sich um einen Einmalkunden handelt. Ein weiteres Beispiel wäre die Tabelle „MarkupTrans“ in der in Abhängigkeit von den Einstellungen für Sonstige Zuschläge ebenfalls weitere Datensätze erzeugt werden.
Die Logik, die das Erstellen der einzelnen Datensätze der verschiedenen Tabellen steuert (die so genannte Geschäftslogik) wird in Microsoft Dynamics AX durch die Klassen „SalesTableType“ (Abbildung 1) und „SalesLineType“ (Abbildung 2), sowie deren abgeleiteten Klassen abgebildet. Diese Klassen steuern das Verhalten bei Anlage, Änderung und Löschung eines Auftrags. Dies beinhaltet auch, welche Werte ein Feld bei welchem Auftragstyp annehmen darf, was geschieht wenn ein Feld geändert wird, was wird wie gebucht und so weiter.


Diese Klassen werden von überschriebenen Methoden der Tabellen „SalesTable“ und „SalesLine“ aufgerufen. So ruft zum Beispiel die Methode „Insert“ der Tabelle „SalesTable“, die Methode „Insert“ der Klasse „SalesTableType“ auf. Abhängig vom Auftragstyp wird über die Methode „construct“ bei der Initialisierung eines „SalesTableType“ Objekts gesteuert, welches konkrete Objekt erzeugt wird („SalesTableType_Sales“, „SalesTableType_ItemReq“, etc.). Unter anderem sind weiterhin die Methoden „Update“, „Delete“, „InitValue“, „ValidateField“ und „Delete“ auf die gleiche Weise überschrieben. Ein Blick in die Methoden der Tabelle „SalesTable“ oder „SalesLine“ sollte dies verdeutlichen.
Somit gestaltet sich das Erstellen eines neuen Auftrags sehr einfach, da die gesamte Geschäftslogik die hinter einem Auftrag steht, automatisch aufgerufen wird.
Um einen neuen Auftrag zu erstellen muss im Wesentlichen nur
- Eine neue Nummer des entsprechenden Nummernkreises gezogen werden.
- Die Methode „InitValue“ der Tabelle „SalesTable“ aufgerufen werden.
- Die Kundennummer zugewiesen werden.
- Die Methode „InitFromCustAccount“ der Tabelle „SalesTable“ aufgerufen werden.
- Die Methode „Insert“ der Tabelle „SalesTable“ aufgerufen werden.
Soll für diesem gerade erzeugten Auftrag nun noch eine Artikelposition erzeugt werden, muss im Wesentlichen nur die Methode „CreateLine“ der Tabelle „SalesLine“, mit vorheriger Definition von Auftragsnummer („SalesLine.SalesId“) und Artikelnummer („SalesLine.ItemId“), aufgerufen werden.
Hierzu ein Beispiel:
void createSalesTableAndLine() { AccountNum custAccount = <yourCustAccount>; ItemId itemId = <yourItemId>;
SalesTable salesTable; SalesLine salesLine; NumberSeq NumberSeq; ; //Auftragskopf (SalesTable) //Neue Auftragsnummer aus Nummernkreis erzeugen NumberSeq = NumberSeq::newGetNumFromCode( SalesParameters::numRefSalesId().numberSequence); salesTable.SalesId = NumberSeq.num();
//Auftragskopf initialisieren salesTable.initValue(); salesTable.CustAccount = custAccount;
//Initialisierung der kundenspezifischen Auftragsdaten salesTable.initFromCustTable();
//Auftragskopf erstellen salesTable.insert();
//Auftragsposition (SalesLine) salesLine.clear();
//Zuweisen von Auftragsnummer und Artikelnummer salesLine.SalesId = salesTable.SalesId; salesLine.ItemId = itemId;
//Auftragsposition erstellen (ruft SalesLine.insert auf) salesLine.createLine(NoYes::Yes, NoYes::Yes, NoYes::Yes, NoYes::Yes, NoYes::Yes, NoYes::Yes); }
|