0

Fortlaufende RechnungsNr. bzw. ID Nummer

Hallo,

ich hätte gerne, dass meine Rechnungen, Auftragsbestätigung und Angebote fortlaufende Nummern haben.

Dafür nutze ich folgenden Code

let myYear := year(today());
let myRN := max((select Rechnungen where year('Datum der Rechnungsstellung') = myYear).substr('ID-Nr', 8));
'ID-Nr' := "RE-" + myYear + "-" + format(number(myRN) + 1, "0000");
'Datum der Rechnungsstellung' := today().

 

Leider bleibt hier meine ID Nr. immer gleich. Lediglich das ABS, RE oder AN ändert sich wie gewünscht.

Wo liegt hier mein Denkfehler?

40 Antworten

null
    • Torsten_Stang.1
    • vor 2 Jahren
    • Gemeldet - anzeigen
    DIGITOOL said:
    max((select Rechnungen where year('Datum der Rechnungsstellung')..... funktioniert nicht, wenn es mehrere Datensätze mit dem Ergebnis gibt!

     Wieso denn das? Wäre mir neu. ich übergeben mit (select Tabelle where Bedingung = xy) doch ein Array von Datensätzen an max(), welches genau das auch erwartet...?

      • Torsten_Stang.1
      • vor 2 Jahren
      • Gemeldet - anzeigen

      DIGITOOL meine Verwunderung fusst darauf, dass ich das Verfahren genau so vielfach mit korrektem Ergebnis einsetze, z.B. generiere ich BANF-Nr. so:

      let myNr := max((select BANF).number(item(split('BANF-Nr', "-"), 2))) + 1;
      'BANF-Nr' := "BANF-" + format(now(), "YY") + "-" + format(myNr, "0000")
      

      Gut, hier fehlt die Einschränkung mit "where" - aber die ändert am der Funktion max() übergebenen Datentyp ja nichts...

       

      In Deinem Beispiel fehlt dem max() die Angabe des Feldes, wohingegen last() den Datensatz übergeben bekommt.

      • + Maßanzug statt Massenware +
      • RonaldP
      • vor 2 Jahren
      • Gemeldet - anzeigen

      Torsten Stang 
      Jo, da hab ich mich verrannt.🤦‍♂️
      Dank dir für die Aufklärung!

    • Ninox-Professional
    • planoxpro
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Hi, die unterschiedlichen Längen des Präfix machen die Sache ein bisschen komplizierter. Aber ich würde es mal so versuchen (nicht getestet; kann Spuren von Flüchtigkeit enthalten):

    let myTyp := switch number(Typ) do
       case 1: "AN"
       case 2: "RE"
       case 3: "ABS"
    end;
    let myPre := myTyp + text(year(today())) + "-";
    let myPos := lenght(myPre);
    let lastNum := max((select Rechnungen[substr('ID-Nr', 0, myPos) = myPre]).substr('ID-Nr', myPos);
    'ID-Nr' := myPre + format(number(lastNum) + 1, "0000")

    Nach dem Schema könnte man auch noch weitere Präfixe berücksichtigen (wie das "ANSS", das irgendwo in einem Screenshot auftaucht).

      • Torsten_Stang.1
      • vor 2 Jahren
      • Gemeldet - anzeigen

      planox. pro 

      mit dem Splitten fange ich ja genau die unterschiedlichen Längen ab. Klar läuft das Skript dann aus dem Ruder, wenn die Präfixe manuell angepasst werden, aber das sollte IMHO sowieso keine Option sein.

      Im Übrigen sollte dann ein contains('ID-Nr',myTyp) auch zur Einschränkung genügen...

    • Ninox-Professional
    • planoxpro
    • vor 2 Jahren
    • Gemeldet - anzeigen
    Torsten Stang said:
    Im Übrigen sollte dann ein contains('ID-Nr',myTyp) auch zur Einschränkung genügen...

    Prinzipiell schon, klar, aber es fehlt dann ja noch das Jahr. Warum zwei Filterkriterien, wenn es auch mit einem geht? ;)

    Ich wollte deine Herangehensweise auch keineswegs in Zweifel ziehen. Natürlich kann man sowas auch mit split() machen. Ich hatte zugegebenermaßen auch nicht alle hier geposteten Codes genau analysiert, aber den Eindruck, dass das Problem noch nicht gelöst war. Deshalb mein Alternativvorschlag.

    • Torsten_Stang.1
    • vor 2 Jahren
    • Gemeldet - anzeigen
    planox. pro said:
    Ich wollte deine Herangehensweise auch keineswegs in Zweifel ziehen.

    Alles gut, habe ich keineswegs so aufgefasst.

    im Zweifel bin ich ja für Alternativen auch dankbar. 😉

    • Erik_Moller
    • vor 2 Jahren
    • Gemeldet - anzeigen
    planox. pro said:
    end;

     Hallo planox. pro

    leider klappt das nicht, hier wird in der vorletzten Zeile das letzte ; bemängelt und in der letzten Zeile das (lastNum) :(

      • Ninox-Professional
      • planoxpro
      • vor 2 Jahren
      • Gemeldet - anzeigen

      Erik Möller Ja, sorry, da fehlte eine schließende Klammer und zuvor auch ein Bindestrich. So sollte es gehen:

      let myTyp := switch number(Typ) do
          case 1: "AN"
          case 2: "RE"
          case 3: "ABS"
      end;
      let myPre := myTyp + "-" + text(year(today())) + "-";
      let myPos := length(myPre);
      let lastNum := max((select Rechnungen)[substr('ID-Nr', 0, myPos) = myPre].substr('ID-Nr', myPos + 1));
      'ID-Nr' := myPre + format(number(lastNum) + 1, "0000")
      
      • Erik_Moller
      • vor 2 Jahren
      • Gemeldet - anzeigen

      planox. pro Solange ich kein Rechnungsdatum eingebe passt, aber wenn ich das eintrage springt er.

      • Ninox-Professional
      • planoxpro
      • vor 2 Jahren
      • Gemeldet - anzeigen

      Erik Möller Verstehe ich nicht. Das Rechnungsdatum spielt dabei doch gar keine Rolle. Und was heißt "springt er"? Wer springt da wohin?

      Mein Code-Vorschlag war als "Trigger nach Änderung" im Auswahlfeld 'Typ' gedacht. Und natürlich kann man dort auch gleich das Rechnungsdatum setzen. Die Zeile hatte ich weggelassen, weil sie bei der Problemlösung keine Rolle spielte. Hier noch mal komplett:

      let myTyp := switch number(Typ) do
          case 1: "AN"
          case 2: "RE"
          case 3: "ABS"
      end;
      let myPre := myTyp + "-" + text(year(today())) + "-";
      let myPos := length(myPre);
      let lastNum := max((select Rechnungen)[substr('ID-Nr', 0, myPos) = myPre].substr('ID-Nr', myPos + 1));
      'ID-Nr' := myPre + format(number(lastNum) + 1, "0000");
      'Datum der Rechnungsstellung' := today()
      
      

      Wenn das nicht funktioniert, dann muss es wohl irgendwo noch andere Trigger geben, die da reinspielen. Ein Trigger "Bei neuem Datensatz" kann in diesem Fall nicht funktionieren, weil die ID-Nr ja vom Typ abhängig ist, welcher bei Neuerstellung des Datensatzes aber noch gar nicht bekannt ist.

    • Erik_Moller
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Jetzt funktioniert es!! Prima, super.

    Vielen Dank.

    Habe dein Code aber jetzt bei Trigger bei neuem Datensatz und Trigger nach Änderung einfügen müssen.

    Vielen Dank Euch allen für die Unterstützung!!

    • Erik_Moller
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Doch noch eine kleine Frage dazu, der Code legt das Rechnungsdatum fest (today), kann man es nicht auch so programmieren, dass ich das Datum manuell verändern kann? (Mache meine Rechnungen meistens alle zusammen eine Woche vor dem eigentlichen Rechnungstermin fertig)

    Wenn ich es ja weg lasse und das Datum manuell dann eintrage wird eine Rechnungsnummer übersprungen:

    also von RE-2022-0001 direkt auf RE-2022 - 0003, statt auf RE-2022-0002.

      • Ninox-Professional
      • planoxpro
      • vor 2 Jahren
      • Gemeldet - anzeigen

      Erik Möller 

      Du hast da offenbar noch einen anderen Trigger laufen, der das Rechnungsdatum einbezieht. Zum Überspringen einer Nummer kann es m. E. eigentlich nur kommen, wenn eine bereits vergebene Nummer neu gesetzt wird. Das heißt, wenn der Datensatz die ID-Nr XX-2022-0013 hat, dann ist 13 die aktuell höchste laufende Nummer. Die nächste, die per Script ermittelt wird, ist also 14, und die ID-Nr dieses Datensatzes lautet nun XX-2022-0014. Die 0013 ist weg, weil sie ja mit der 0014 überschrieben wurde.

      Augenscheinlich benutzt du die Vorlage "Rechnungen" von Ninox. Dort werden die Dokumente typ-übergreifend durchnummeriert, und zwar über einen Trigger "Bei neuem Datensatz" mit der Voreinstellung "RE" für "Rechnung". Der nächste neue Datensatz bekommt also bspw. automatisch die Nummer RE-2022-0013. Ändert man nun den Typ, werden einfach nur die ersten beiden Buchstaben der ID-Nr geändert. Aus RE-2022-0013 wird dann AN-2022-0013 oder LS-2022-0013. Aber die 13 als höchste laufende Nummer bleibt erhalten. Und der nächste Datensatz bekommt die 14, unabhängig davon, ob dann vielleicht noch der Typ geändert wird.

      Du wolltest aber, wenn ich es richtig verstanden habe, nicht typ-übergreifend EINE laufende Nummer für ALLE Datensätze, sondern für jeden Typ eine eigene lfd. Nummer. Und das funktioniert aus genannten Gründen nicht mit den Triggern aus der Vorlage. Denn es lässt sich keine auf den Typ bezogene ID-Nr generieren, wenn der Typ noch nicht feststeht.

      Da du zudem auch noch Rechnungen vorproduzieren willst, würde ich folgenden Vorgehensweise empfehlen: Lösche die Trigger "Bei neuem Datensatz" sowie "Nach Änderung" im Auswahlfeld 'Typ' und erstelle statt dessen einen Button "ID-Nr vergeben" oder so mit folgendem Code:
       

      if Typ and not 'ID-Nr' then
         let myTyp := switch number(Typ) do
            case 1: "AN"
            case 2: "RE"
            case 3: "ABS"
         end;
         let myPre := myTyp + "-" + text(year(today())) + "-";
         let myPos := length(myPre);
         let lastNum := max((select Rechnungen)[substr('ID-Nr', 0, myPos) = myPre].substr('ID-Nr', myPos + 1));
         'ID-Nr' := myPre + format(number(lastNum) + 1, "0000");
         'Datum der Rechnungsstellung' := today()
      end
      

      Dann wird die ID-Nr zwar nicht mehr automatisch erstellt, sondern erst nach Klick auf den Button, aber du hast immer passende Nummern für jeden Typ und bist auch im Hinblick auf die GoBD auf der sicheren Seite, weil du stets korrekte Rechnungsnummern und Datumswerte hast.

    • Erik_Moller
    • vor 2 Jahren
    • Gemeldet - anzeigen
    planox. pro said:
    d

     Guten Morgen.

    Genau, ich habe die Vorlage von Ninox verwendet, da ich hier total Neuling bin und überprüfe, ob Ninox eine Lösung für uns wäre.

    Ich habe die alte Formel jetzt gelöscht und dafür in "Typ" deine Formel integriert.

    Funktioniert sehr gut bei AN und bei ABS, nur bei RE wir keine ID generiert wenn ich ins Feld klicke. 

    • Erik_Moller
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Es klappt.... Hab den "Standardwert" gelöscht und den Code auch nochmal bei der Tabelle eingefügt ohne Zusatz 

     'Datum der Rechnungsstellung' := today()

    und jetzt kann ich das Datum verändern und die Rechnungsnummern, bzw Angebotsnummern  sind fortlaufend. 

    Vielen Dank Euch allen bei der Unterstützung!!!