[ABAP] Nummernkreis: Nächste freie Nummer vergeben (Beispiel: BANF)

* http://www.kodyaz.com/articles/create-number-range-in-abap-using-sap-snro-transaction-code.aspx
* https://www.tapatalk.com/groups/abapteamforum/function-module-to-get-next-number-in-number-range-t4162861.html
* http://www.erpworkbench.com/sap-tcodes/snro.htm
* https://www.berater-wiki.de/Access_Tabellenbeziehung_Nummernkreise

* Transaktion: SNRO
* Tabellen: TNRO, TNROT, NRIV, T161

* Nummernkreisobjekte aus Tabelle TNRO, z.B. BANF, ADRNR
PARAMETERS: p_object TYPE tnro-object DEFAULT 'BANF'.
* Einkaufsbelegart für Ermittlung des zugewiesenen Nummernkreisintervalls
PARAMETERS: p_bsart TYPE t161-bsart DEFAULT 'BA'.

* Definition der Nummernkreisobjekte prüfen, siehe Transaktion SNRO
SELECT SINGLE tnro~object,
              tnro~domlen,
              tnro~buffer,
              tnro~noivbuffer,
              tnrot~txtshort
  INTO @DATA(lv_tnro)
  FROM tnro
  INNER JOIN tnrot ON tnro~object = tnrot~object
  WHERE tnro~object = @p_object
    AND tnrot~langu = @sy-langu.

IF sy-subrc = 0.

  WRITE: / 'Objekt:', lv_tnro-object.
  WRITE: / 'Kurztext:', lv_tnro-txtshort.
  WRITE: / 'Domäne:', lv_tnro-domlen.
  WRITE: / 'Buffer:', lv_tnro-buffer.
  WRITE: / 'Buffer-Size:', lv_tnro-noivbuffer.

* internes Nummernkreisintervall für BANF-Belegart holen
* siehe auch Tabelle NRIV
  SELECT SINGLE *
    FROM t161
    INTO @DATA(lv_t161)
    WHERE bstyp = 'B'
    AND bsart = @p_bsart.

  IF sy-subrc = 0.

    WRITE: / 'BSTYP:', lv_t161-bstyp.
    WRITE: / 'BSART:', lv_t161-bsart.
    WRITE: / 'Nummernkreis:', lv_t161-numki.

* Nummernkreis-Objekt sperren
    CALL FUNCTION 'NUMBER_RANGE_ENQUEUE'
      EXPORTING
        object           = p_object
      EXCEPTIONS
        foreign_lock     = 1
        object_not_found = 2
        system_failure   = 3
        OTHERS           = 4.

    IF sy-subrc = 0.

      WRITE: / |Objekt gesperrt: { p_object }|.

* Rückgabewert
      DATA: lv_number TYPE string.
* Fehlercode
      DATA: lv_rc TYPE inri-returncode.

* Nummernkreis: Nächste freie Nummer vergeben
      CALL FUNCTION 'NUMBER_GET_NEXT'
        EXPORTING
          nr_range_nr             = lv_t161-numki   " Intervall
          object                  = p_object        " Objekt (SNRO)
        IMPORTING
          number                  = lv_number       " generierte Nummer
          returncode              = lv_rc
        EXCEPTIONS
          interval_not_found      = 1
          number_range_not_intern = 2
          object_not_found        = 3
          quantity_is_0           = 4
          quantity_is_not_1       = 5
          interval_overflow       = 6
          buffer_overflow         = 7
          OTHERS                  = 8.

* Returncode, siehe INCLUDE LSNR3F01
      CASE lv_rc.
        WHEN ' '.
          WRITE: / 'Alles o.k.'.
        WHEN '1'.
          WRITE: / 'Die vergebene Nummer liegt im kritischen Bereich.'.
        WHEN '2'.
          WRITE: / 'Dies war die letzte Nummer, beim nächsten Mal wird die erste Nummer vergeben'.
        WHEN '3'.
          WRITE: / 'Es werden mehr Nummern verlangt als zur Verfügung stehen, in QUAN steht die Anzahl der vergebenen Nummern.'.
      ENDCASE.

      IF sy-subrc = 0.
        WRITE: / 'Objekt:', p_object.
        WRITE: / 'generierte Nummer:', lv_number.
      ENDIF.

* Nummernkreis-Objekt entsperren
      CALL FUNCTION 'NUMBER_RANGE_DEQUEUE'
        EXPORTING
          object           = p_object
        EXCEPTIONS
          object_not_found = 1
          OTHERS           = 2.

      IF sy-subrc = 0.
        WRITE: / |Objekt entsperrt: { p_object }|.
      ELSE.
        WRITE: / |Objekt konnte nicht entsperrt werden: { p_object }|.
      ENDIF.
    ELSE.
      WRITE: / |Objekt konnte nicht gesperrt werden: { p_object }|.
    ENDIF.
  ELSE.
    WRITE: / 'Kein internes Nummernkreisintervall für BANF-Belegart:', p_bsart.
  ENDIF.
ELSE.
  WRITE: / |Objekt in Tabelle TNRO nicht vorhanden: { p_object }|.
ENDIF.