Lagerplatzbuchung per DCM überwachen

Einmal müsste ich noch nerven. o_O

Ich bräuchte die BuchungsID, aber sowohl LagerplatzBuchung.BuchungsHandle, als auch LagerplatzBuchung.BuchungsHandleNew sind 0.

Gut, die Buchung ist ja auch noch nicht gespeichert, aber auch das kann ich nicht tun, weil ich die Job Id nicht habe.

Wie komme ich an die BuchungsId ran?
 
Die BuchungsID kannst Du erst auslesen, wenn die Buchung gespeichert wurde, also über die DCM "LagerplatzBuchungSave".
 
Hm...

Vielleicht mal eben zur Erklärung, was ich vor habe:
Ich möchte interne Umbuchungen auf ein bestimmtes Lager erkennen, das funktioniert in der DCM schon mal problemlos. Allerdings möchte ich jetzt den Ziellagerplatz umschreiben, was in der DCM bisher auch funktioniert.
Der Grund dafür ist, dass wir für das eigentliche Ziellager zunächst eine Kommunikation aufbauen müssen und die Antwort verarbeiten müssen. Erst dann buche ich die Sachen auf den korrekten Lagerplatz, aber das passiert hinterher, außerhalb der DCMs.

Um jetzt die Verarbeitung sauber protokollieren zu können, habe ich eine Tabelle angelegt, in der ich mir die Buchungen samt Status und das eigentliche Ziellager merke. Dann kommen die Verarbeitungsprozesse auf unserer Seite. Abschließend möchte ich dann die Umbuchung vom Zwischenlager auf das eigentliche Ziellager vornehmen.

Mein Problem ist daher, dass ich in der temporären Tabelle gerne den Bezug zur Buchung hätte, was in der DCM LagerPlatzBuchungBeforeSave nicht möglich ist.
Mache ich das über LagerplatzBuchungSave, komme ich zwar ran, kann aber den Ziellagerplatz nicht ändern, es sei denn, ich speichere das Objekt erneut. Ist aber die Buchung dann nicht bereits vollzogen, wenn ich in LagerplatzBuchungSave reinspringe?
 
Hi,

mach doch beides:
Vor Speicherung Lager ändern.
Nach Speicherung protokollieren.
Nach dem Speichern fehlen dann aber die vorigen Daten, die geändert wurden.

Vor dem Speichern Lager ändern und in einer eigenen Tabelle protokollieren.
ID aus der eigenen Tabelle mit in die Buchung schreiben (Feld "Memo" oder benutzerdefiniertes Feld).
Nach dem Speichern ID aus der Buchung auslesen und BuchungsID im Datensatz der eigenen Tabelle ergänzen.
 
Danke, klappt soweit und kann erstmal so laufen.

Da ich es in LagerplatzBuchungSave nicht hinbekommen habe, die BuchungsID rauszuziehen, gehe ich wie folgt vor:
  1. In LagerplatzBuchungBeforeSave wird in meine Protokolltabelle geschrieben und der Ziellagerplatz angepasst
  2. Die ScopeIdentity des Inserts übernehme ich in den Context der Buchung
Dadurch habe ich ja bereits eine eindeutige Zuordnung und brauche die BuchungsID nicht in meine Tabellen zu übernehmen.

Aktuell nutze ich das Feld Referenz, da das für interne Umbuchungen nicht genutzt wird und meine Anpassung sich ausschließlich auf diese Art Buchungen bezieht. Lieber wäre mir ein benutzerdefiniertes Feld, aber finde an dem LagerplatzBuchung-Objekt keine Möglichkeit auf solche Felder zuzugreifen?!

Da meine Identity natürlich ein int ist und das Feld Referenz ein varchar, gefällt mir das nicht so sehr, weshalb ich noch per Trigger den Wert in ein benutzerdefiniertes Integer-Feld schreibe.

Das kann ich dann nochmal schöner lösen, wenn ich weiß, wie ich da in der DCM rankomme.

Soweit passt es aber erstmal
Danke und Gruß
Arne
 
Die "BuchungsID" steht in der Property "BuchungsHandle" des LagerplatzBuchung-Objekts aus dem Context?!
Einen Zugriff auf benutzerdefinierte Felder gibt es wohl nicht, da im Standard in dieser Klasse keine benutzerdefinierten Felder angelegt werden können. Du kannst Dir die ID aber auch über die "DcmProperties" merken:

Code:
switch (context.ListId)
{
  case DcmDefinitionManager.DcmListId.LagerplatzBuchungBeforeSave:
  DcmContextBeforeLagerbuchung contextBeforeLagerbuchung = (Sagede.OfficeLine.Wawi.LagerEngine.DcmContextBeforeLagerbuchung)context;
  // Anpassung Ziellagerplatz, Protokollierung der Änderung...
  // ID aus Protokolltabelle merken:
  protokollID = 123;
  contextBeforeLagerbuchung.LagerplatzBuchung.DcmProperties.IntegerValues["ProtokollID"] = protokollID;
  break;

  case DcmDefinitionManager.DcmListId.LagerplatzBuchungSave:
  DcmContextLagerbuchung contextLagerbuchung = (Sagede.OfficeLine.Wawi.LagerEngine.DcmContextLagerbuchung)context;
  Mandant mandant = contextLagerbuchung.Mandant;
  // ID aus Protokolltabelle abfragen:
  protokollID = Sagede.Core.Tools.ConversionHelper.ToInt32(contextLagerbuchung.LagerplatzBuchung.DcmProperties.IntegerValues["ProtokollID"]);
  if (protokollID > 0)
  {
  int buchungsID = contextLagerbuchung.LagerplatzBuchung.BuchungsHandle;
  // Update BuchungsID in Protokolltabelle...
  }
  break;

  default:
  break;
}
return true;
 
Zuletzt bearbeitet:
Ich muss zugeben, DcmProperties hatte ich bisher noch gar nicht genutzt, macht aber Sinn. :D
Danke für den Hinweis.

Ja, ich vermute ich habe dann was anderes falsch gemacht, denn die SqlQuery hatte keine affected rows, weil mein Buchungshandle an der Stelle leer war :confused:

Aber ich passe das mal auf die DcmProperties an und schaue dann nochmal.

Danke Dir!
 
Hallo Zusammen,

ich möchte das Thema nocheinmal aufgreifen, da dieses das einzige in den Suchergebnissen zu den Begriffen 'DcmContextLagerbuchung' oder 'DcmContextBeforeLagerbuchung' war...

Ich würde gerne wissen, ob es möglich ist im .Net-Code festzustellen, welches Formular oder was gerade die Lagerbuchung durchführt (z.B. Buchungserfassung, 'Lagerbewegung bearbeiten' oder gar aus einer eigenen Maske)?
Dies interessiert mich sehr, da die Lagerbuchung aus dem Sage-Standard nur selten genutzt wird und wenn, dann um von Lager A (alle Seriennummern) nach Lager B zu buchen und dann möchte ich dies in unserer eigenen "Seriennummernhistorie" inserten...

Auch ist mir aufgefallen, dass bei einer IU das "LagerplatzBuchungSave" und "LagerplatzBuchungBeforeSave" 3mal aufgerufen wird! 2mal ist keine (context as DcmContextLagerbuchung).LagerplatzBuchung).Bewegungsart hinterlegt (per MessageBox) und beim dritten mal ist es dann doch die "Interne Umbuchung" hinterlegt... Ist das so normal?


Ich würde mich über ein paar kurze Tipps freuen und bedanke mich schonmal für eure Unterstützungen!


MfG Paul@GEKKO :)
 
Zuletzt bearbeitet:
Hallo,

hat jemand eventuell eine vollständige Beschreibung, wie die Lagerplatz-Engine arbeitet? Selbst der Dev-Support gibt Lösungshinweise die nicht funktionieren können, wie man durch viel rumprobieren erfahren muss. Zum konkreten Fall: unser Unternehmen vermietet diverse Produkte. Die Produkte können also nicht wie normale Handelsware behandelt werden, sondern werden im Rahmen der Vermietung von einem Lagerplatz zum anderen umgelagert. (Mietwaren-Lager an Kundenlager, Kundenlager an Mietwarenlager). So bleibt das Anlagegut (unsere Mietware) auch für den Prüfer immer übersichtlich in einem inventierbaren Lager.
Wir lösen dies über interne Umbuchung und das funktioniert auch soweit. Problematisch sind Fälle wie Korrektur der Mengen in einem Beleg oder das Löschen eines Beleges. Wir würden es gern vermeiden, das Rad noch einmal neu zu erfinden. Der DEV-Support Vorschlag: den zugehörigen Job des Belegobjektes zu löschen und die neuen Werte in einem neuen Job zu erfassen, wird mit der Meldung "Löschen des Jobs nur mit Löschen des Beleges möglich" quittiert. Unsere derzeitige Lösung besteht darin, alle Buchungen des originalen Beleges zu stornieren und die neuen Mengen im gleichen Job zu erfassen. Dies müssen wir auch vor dem Löschen des Belegs durchführen, weil der Lagerjob selbst dann nicht gelöscht wird (???) Das kommt mir alles ziemlich tricki vor. Gibt es da auch smartere Lösungen? Kann man über die KHKLagerbewegungsarten - Tabelle eventuell eigene Bewegungsarten kreieren. Was bewirken die Einzelnen Werte dieser Tabelle?

Ich bin für jeden Hinweis dankbar :)
 
Moin,

Ich habe das ganze noch nicht so erfasst, was ihr genau macht und/oder vorhabt, aber das kann an mir liegen, daher ein paar Fragen und Anmerkungen :)
Problematisch sind Fälle wie Korrektur der Mengen in einem Beleg oder das Löschen eines Beleges.
Welche Problematiken genau treten da auf?

den zugehörigen Job des Belegobjektes zu löschen und die neuen Werte in einem neuen Job zu erfassen, wird mit der Meldung "Löschen des Jobs nur mit Löschen des Beleges möglich" quittiert.
Wenn ein Lagerjob über einen Beleg erstellt wurde, gibt es in der KHKLagerplatzBuchungen einen Verweis im Feld Referenz. Ob das ausschlaggebendes Kriterium für den Fall ist, weiß ich nicht zu 100%, könnte es mir aber vorstellen, denn ansonsten ist mir kein Bezug bekannt.

Unsere derzeitige Lösung besteht darin, alle Buchungen des originalen Beleges zu stornieren und die neuen Mengen im gleichen Job zu erfassen. Dies müssen wir auch vor dem Löschen des Belegs durchführen, weil der Lagerjob selbst dann nicht gelöscht wird (???) Das kommt mir alles ziemlich tricki vor. Gibt es da auch smartere Lösungen?
Wie gesagt bin ich mir nicht ganz sicher, ob ich alles richtig verstanden habe, aber so wie ich es verstehe, würde ich einen Gegenbeleg erzeugen, also eine Belegart verwenden ( zur Not selbst anlegen ), die über entsprechende Kennzeichen die benötigten Rückbuchungen vornimmt.
Dann einfach einen Korrekturbeleg, wo die korrigierten Buchungen drin sind. Kann man über eine DCM dann auch in einem Schritt durchführen.

Kann man über die KHKLagerbewegungsarten - Tabelle eventuell eigene Bewegungsarten kreieren. Was bewirken die Einzelnen Werte dieser Tabelle?
Ja, das machen wir auch. Man muss halt die Kennzeichen entsprechend setzen:

- Bewegungsart : Kürzel/Kennzeichen der Bewegungsart ( bspw. IU usw. ) => frei wählbar
- Bezeichnung : Info, damit man weiß, worum es sich bei dieser Bewegungsart handelt => frei wählbar
- Standardtext : Ein frei wählbarer Text, der bei den Buchungen mit übernommen wird. Hier ist eine Art Platzhalter $&$ möglich, über den man bspw. die Belegnummer in den Standardtext übernimmt, sofern die Buchung über einen Beleg durchgeführt wird.
- IstManuell : Ob die Bewegungsart manuell in den Buchungsmasken verwendet werden kann.
- Bestandswirkung : Ob die Bewegungsart Bestand bucht.
- Schwebt : Ob es sich um eine schwebende Buchung handelt.
- IstInventur : Ob die Bewegungsart eine Inventurbuchung darstellt.
- IstIFAuftrag : Ob die Bewegungsart für interne Fertigungsaufträge verwendet wird.
- IstStorno : Ob die Bewegungsart eine Stornobuchung durchführt ( Mengen werden negativ bewertet )
- Anzeige : Steht für die Reihenfolge der Auswahl über die Sage-Masken. Ist bei uns häufig einfach 0, weil wir die eigenen Bewegungsarten nur Script basiert einsetzen.

Bei den Spalten IstManuell bis IstStorno muss man bedenken, dass es ein KHKBoolean Datentyp ist, bei dem -1 für true steht!
Kenne ich aus keiner Programmiersprache, dass ein negativer Wert als true definiert wird, aber ist wohl aus KHK Zeiten übernommen, wie man am Namen sehen kann. ;)

Ein Profi möge mich korrigieren, wenn ich etwas falsch dargestellt habe.
:cool:
 
Auch ein freundliches Moin an Dich!
Ich habe Deinen Beitrag ehrlicher Weise erst vor ein paar Wochen bemerkt und wollte nicht ein Jahr später antworten, aber da das Thema grad aktualisiert wurde... :)
Ich würde gerne wissen, ob es möglich ist im .Net-Code festzustellen, welches Formular oder was gerade die Lagerbuchung durchführt (z.B. Buchungserfassung, 'Lagerbewegung bearbeiten' oder gar aus einer eigenen Maske)?
Generell ist mir da keine standardisierte Möglichkeit bekannt, aber Du hast ja in den DCMs die Möglichkeit, eine Info bspw. in ein benutzerdefiniertes Feld zu schreiben. In der DCM weißt Du ja, in welchem Kontext du Dich befindest und kannst dann reinschreiben, was Du willst oder benötigst. Wenn Du für das benutzerdefinierte Feld einen Standardwert wie bspw. Sage100 Lagerbuchung, hast Du automatisch auch einen Hinweis, wenn das Formular verwendet wurde. Das setzt natürlich voraus, dass alle eigenen/externen Lösungen dieses Feld explizit füllen.

Auch ist mir aufgefallen, dass bei einer IU das "LagerplatzBuchungSave" und "LagerplatzBuchungBeforeSave" 3mal aufgerufen wird! 2mal ist keine (context as DcmContextLagerbuchung).LagerplatzBuchung).Bewegungsart hinterlegt (per MessageBox) und beim dritten mal ist es dann doch die "Interne Umbuchung" hinterlegt... Ist das so normal?
Ich erinnere mich nicht mehr genau an die Gründe, aber ich meine, dass das tatsächlich normal sei.
 
Hallo Arne,

danke für die ausführliche Antwort. "Problematisch" war offensichtlich die falsche Wortwahl von mir. Besser wäre wahrscheinlich "Umständlich". Meine Hoffnung war/ist, dass es einfachere Möglichkeiten gibt.

Z.B. wird derzeit in unserer Lösung ein Beleg wie folgt korrigiert:
- Stornieren der Lagerbuchungen je Positionen des Ursprungbelegs
- Lagerjob (Storno) speichern
- Erzeugen der Lagerbuchungen je Positionen des korrigierten Belegs
- Lagerjob (Korrektur) speichern

Konsequenter Weise haben wir so drei Lager-Jobs. Original, Storno, Korrektur. Sieht nicht schön aus und Sage löst dieses Problem irgendwie anders (es gibt nur ein Lagerjob pro Sage-Beleg, unabhängig davon, wie oft dieser geändert wurde). Was halt nicht funktioniert ist, den Original-Lagerjob zu löschen und damit auch alle Buchungen zu löschen und einfach einen neuen zu erzeugen. Auch nicht im Kontext des Beleges(Wir benutzen die DCM DcmContextBelegProxyBeforeSave.). Den Original-Lagerjob zu ändern erfordert wieder zu prüfen: Welche Position wurde geändert? Wurden Positionen gelöscht? usw.

Allgemein ärgert mich ja, dass man nur wenig Dokumentation zu den Classen findet, außer Beschreibungen die sich schon aus der ungarischen Notation ergeben (LagerJob.Delete() = Löscht einen Lagerjob - haben wir schon vermutet :cool: ), aber welche Bedingungen müssen für den erfolgreichen Aufruf erfüllt sein?)

Viele Grüße und Sorry für die späte Reaktion
Uwe
 
Zurück
Oben