"Stückliste entfalten" automatisieren

30. Mai 2007 15:21

Hallo!
Ich möchte gerne beim Erfassen eines Auftrags die Funktion "Stückliste entfalten" automatisieren.
Das was ich jetzt also manuell machen würde, wenn ich die Zeile erfasst habe, nämlich auf "Funktion -> Stückliste entfalten" klicken, soll am liebsten automatisch passieren.
Das Problem ist nur, es gibt keinen Trigger, wo ich das starten könnte. Denn er muss den Rec komplett weggeschrieben haben (OnInsert muss komplett durch sein), bevor ich die Funktion aufrufen kann.
Eigentlich bräuhcte ich sozusagen einen "OnAfterInsert" Trigger, den es ja aber leider natürlich nicht gibt ;-)
Hat jemand eine Idee, wie ich das realisieren könnte?

Danke!

Es grüßt,
Astrill

30. Mai 2007 17:10

Hallo Astrill,

ich denke, für die Entfaltung einer Stückliste sind in der Zeile lediglich die Informationen Art=Artikel, die Artikelnr. und die Menge notwendig. Von diesen Feldern ist Menge das Feld, das als letztes eingetragen werden muss (und auch nicht vor den anderen Feldern eingetragen werden kann).

Daher würde ich dies nach der Validierung des Feldes Menge in der Form machen. Hier hast Du die Möglichkeit im Trigger OnAfterValidate einzugreifen. Prüfe erst ab, ob es sich um einen Artikel handelt und dieser eine Stückliste besitzt. Wenn das so ist, speicherst Du den Record mit CurrForm.SAVERECORD und danach entfaltest Du über die Funktion ExplodeBOM der Form. Ich würde aber noch eine Abfrage nach dem Schema "Es handelt sich bei Artikel Nr. xxx um einen Stücklistenartikel. Wollen Sie die Stückliste entfalten?" dazwischen setzen. Nicht jeder User findet es lustig, wenn die Software macht was sie will.

Wenn die Stückliste auf jeden Fall entfaltet werden soll, kannst Du auch statt der Abfrage eine Meldung bringen, oder wärend der Freigabe prüfen, ob alle notwendigen Entfaltungen vorgenommen wurden.

Gruß
Frank

31. Mai 2007 10:36

Hallo und danke für die Antwort!

Nur leider geht das so nicht, weil (wenn ich das richtig sehe) er den Record ja noch nicht geschrieben hat. Ich müsste also vorher ein COMMIT machen, aber das will ich natürlich auch nicht.
So kann ich nicht aus dem noch nicht geschriebenen Record eine Codeunit aufrufen, die selbigen verwendet :-(

Oder?

Es grüßt,
Astrill

31. Mai 2007 10:50

Hi Astrill,

ich habe das gerade mal versucht und bei mir funktioniert es. (Ich habe hier gerade die Version 3.7 vor mir.)

Hier mein Codestück:
Code:

Quantity - OnAfterValidate()
----------------------------------------------------------
IF Reserve = Reserve::Always THEN BEGIN
  CurrForm.SAVERECORD;
  AutoReserve;
  CurrForm.UPDATE(FALSE);
END;

//Test-Stückliste automatisch
IF (Type = Type::Item) THEN BEGIN
  IF ItemLocal.GET("No.") THEN BEGIN
    ItemLocal.CALCFIELDS("Bill of Materials");
    IF ItemLocal."Bill of Materials" THEN BEGIN
      CurrForm.SAVERECORD;
      ExplodeBOM();
      CurrForm.UPDATE(FALSE);
    END;
  END;
END;
//Test


Versuchs mal. :-)

Gruß
Frank

31. Mai 2007 11:28

Hallo Frank,
vielen Dank für die schnelle Antwort!

Ich hab dein Code ausprobiert, aber in 4.03 funktionierts leider nicht :-(
Vielleicht ist die Sales-Explode BOM in der Version anders oder so.
Aber wenn ich deinen Code einbaue, dann bekomme ich den Fehler, dass die Schreibtransaktion nicht erlaubt ist (und merkwürdigerweise auch 1x, dass er die Zeile nicht findet, aber nicht reproduzierbar).

Und wieder würde mir nur ein nicht gewünschter COMMIT einfallen, der dieses Problem löst :-(

Es grüßt,
Astrill

Nachtrag:
Irgendwas mache ich wohl falsch, denn ich hab das grad an einer 3.70b ausprobiert und da gehts auch nicht... :-?

31. Mai 2007 12:53

Hallo Astrill,

wie das in der 4.xx klappt kann ich gerade nicht sagen - kann mir das aber morgen mal vornehmen.

Wie sieht aber dein Code in der 3.70b aus und wo hast du Ihn eingefügt? Er muss in den Trigger OnAfterValidate des Feldes Menge der Form 46 Verkaufsauftrag Subform.

Gruß
Frank

31. Mai 2007 13:29

Hallo!

Ich habe das in eine ganz frische 3.70er DB eingebaut, genau so wie du:

Code:
Quantity - OnAfterValidate()
IF Reserve = Reserve::Always THEN BEGIN
  CurrForm.SAVERECORD;
  AutoReserve;
  CurrForm.UPDATE(FALSE);
END;

//Test-Stückliste automatisch
IF (Type = Type::Item) THEN BEGIN
  IF ItemLocal.GET("No.") THEN BEGIN
    ItemLocal.CALCFIELDS("Bill of Materials");
    IF ItemLocal."Bill of Materials" THEN BEGIN
      CurrForm.SAVERECORD;
      ExplodeBOM();
      CurrForm.UPDATE(FALSE);
    END;
  END;
END;
//Test


Wenn ich erst eine Zeile erstelle, dann den Quellcode hinzufüge und dann nochmal in die vorhandene Auftragszeile gehe und auf Menge einen validate laufen lasse, dann funktionierts auch. Aber eben nur, wenn er die Zeile schon vorher hat... hattest Du das vielleicht so getestet?

Es grüßt,
Astrill

31. Mai 2007 13:37

:?: Hmmmm, also ich habe das gerade nochmal getestet und dabei genau darauf geachtet, dass vor der Eingabe der Menge die Zeile noch nicht gespeichert ist (also die Zeile noch mit einem Sternchen versehen ist). Bei mir klappt das ohne Probleme.

Wie lautet denn die Fehlermeldung genau?

Gruß
Frank

31. Mai 2007 16:53

Hallo!
Das gibts ja nicht, ich habs grad nochmal überprüft (auf 3.70B) und ausprobiert, bekomme aber immer:

Die Verwendung der unten aufgeführten C/AL-Funktionen ist innerhalb von Schreibtransaktionen, die eine oder mehrere Tabellen gesperrt haben, eingeschränkt (da eine oder mehrere Tabellen gesperrt sein werden).
[...]


Ich mache ja auch während einer Schreibtransaktion ein Codeunit.RUN... (in der Funktion ExplodeBOM).

Versteh ich nicht, dass es bei dir funktioniert... :-?

Es grüßt,
Astrill

1. Juni 2007 00:51

innerhalb von Schreibtransaktionen darfst Du den Rückgabewert von Codeunit.run NICHT abfangen, also nicht
if codeunit.run then irgendwas;
sondern nur
codeunit.run;

1. Juni 2007 10:07

Hallo Astrill,

vermutlich funktioniert das bei dir nicht weil du die Verfügbarkeitsprüfung eingeschaltet hast - und ich halt nicht. Hier soll eine Form modal angezeigt werden - und das ist halt das Problem.

Meiner Meinung nach kannst Du aber ganz gefahrlos ein Commit einbauen:

Code:
Quantity - OnAfterValidate()
----------------------------------------------------------
IF Reserve = Reserve::Always THEN BEGIN
  CurrForm.SAVERECORD;
  AutoReserve;
  CurrForm.UPDATE(FALSE);
END;

//Test-Stückliste automatisch
IF (Type = Type::Item) THEN BEGIN
  IF ItemLocal.GET("No.") THEN BEGIN
    ItemLocal.CALCFIELDS("Bill of Materials");
    IF ItemLocal."Bill of Materials" THEN BEGIN
      CurrForm.SAVERECORD;
      COMMIT;
      ExplodeBOM();
      CurrForm.UPDATE(FALSE);
    END;
  END;
END;
//Test



Wenn der Code nicht ausgeführt wird, wird von der Runtime sowieso direkt danach ein Commit ausgeführt. Somit wäre das einzige, das im Fehlerfall nicht ausgeführt wurde das Entfalten der Stückliste. Dies kann aber auch manuell noch nachgeholt werden - dadurch ist das Risiko eines zwischengeschalteten Commits hier zu vernachlässigen.

Gruß
Frank

4. Juni 2007 11:13

Hallo und nochmals vielen Dank!

Mit dem Commit klappt es in der Tat problemlos. Wo genau wird denn diese Verfügbarkeitsprüfung gemacht? Leider habe ich nichts gefunden. Aber man könnte es ja vielleicht so machen, dass bei einem Stücklistenartikel eben keine Verfügbarkeitsprüfung gemacht wird, auch wenn diese generell eingeschaltet ist. So kann man das ja vielleicht umgehen.
Nur wie gesagt, ich weiß leider nicht, wo ich das finden kann. Kann mir dajemand vielleicht nochmal einen Tipp geben? :wink:

Vielen Dank!
Es grüßt,
Astrill

NACHTRAG: Danke, habs doch gefunden. Für andere die's auch suchen: Debitoren&Verkauf Einrichtung -> Bestandswarnung
Klappt jetzt! :-)