giovedì 14 dicembre 2017

Range numerazione documenti contabili.


In SAP i documenti contabili hanno in chiave anche l'anno; questo significa che la numerazione dei documenti può riutilizzare gli stessi numeri in anni differenti.

Quando siamo partiti con SAP la società di consulenza ha operato con una, probabilmente sua, consuetudine di numerazione impostanto le prime 2 cifre di ogni range FI con l'anno e poi con l'identificativo del numero di range.


Chiave della tabella testata documenti BKPF


Esempio di numerazione


Questo ha il vantaggio di capire a colpo d'occhio di che anno si tratta guardando il numero documento e poi che non serve inserire l'anno quando, per esempio, si visualizza un numero documento dalla transazione FB03:



La controindicazione è che, quando si crea la nuova numerazione per copia dall'anno precedente, bisogna manualmente cambiare tutti i contatori mettendo come prime 2 cifre il nuovo anno.

Quindi per generare i nuovi contatori per un nuovo anno si usa la transazione OBH2, che crea la numerazione per copia dall'anno precedente.


Poi con la transazione FBN1 si deve cambiare, per ogni contatore, la cifra con il nuovo anno. Per copia ha preso la stessa numerazione dell'anno precedente:



si devono cambiare le prime 2 cifre con il nuovo anno.

Ma ci sono decine e decine di contatori, poi si deve fare per tutte le società!

I primi anni l'ho fatto a mano ma poi, aumentando anche il numero di società gestite nel sistema, ci impiegavo davvero tanto tempo e, soprattutto, potevo anche fare qualche errore di digitazione.

Alla fine mi sono deciso e ho scritto un piccolo ABAP che va ad aggiornare i contatori modificando le prime 2 cifre.

Note:
  • un contatore viene modificato solo se lo stesso contatore aveva, nell'anno precedente, le prime 2 cifre uguali all'anno. Questo perchè ci sono alcuni contatori, per esempio per le numerazioni esterne o per le fatture, che non devono rispettare la regola.
  • un contatore viene modificato solo se ha lo stato iniziale, cioè se non è già stato "staccato" nessun numero.
  • il programma funziona fino al 2099, poi il 2100 e 2101 saranno da trattare in modo particolare poichè non riconosce in modo automatico se "00" è il prefisso dell'anno o se è un contatore che non deve essere trattato in questa modalità....comunque io, per quella data, non ci sarò più.
Listato sorgente del programma

*----------------------------------------------------------------------+
* Programma  : ZFI_RANGE                                               |
* Autore     : Fabio Giacobbe - 20/12/2016                             |
* Descrizione: Correzione numerazione FI per nuovo anno.               |
*              Nella numerazione FI (oggetto RF_BELEG) si tiene il     |
*              numero anno come iniziale della numerazione.            |
*              Questo programmino lo fa per tutti i range dell'anno.   |
*----------------------------------------------------------------------+
* Modifiche  :            by                                           |
* Note       :                                                         |
*----------------------------------------------------------------------+
REPORT  zfi_range.

*----------------------------------------------------------------------*
* Tabelle del DB utilizzate all'interno del programma.
*----------------------------------------------------------------------*
TABLES: nriv.

* Internal Tables
DATA: BEGIN OF xnriv OCCURS 40.
        INCLUDE STRUCTURE inriv.
DATA:   mark(1)    TYPE c.
DATA: END OF xnriv.

* Intervallo
DATA: BEGIN OF error_iv OCCURS 5.
        INCLUDE STRUCTURE inriv.
DATA: END OF error_iv.

DATA: BEGIN OF interval OCCURS 10.
        INCLUDE STRUCTURE inriv.
DATA: END OF interval.

*----------------------------------------------------------------------*
* Parametri di selezione
*----------------------------------------------------------------------*
PARAMETERS: i_bukrs LIKE t001-bukrs,
            i_anno(4) TYPE n.

*----------------------------------------------------------------------*
* Variabili globali
*----------------------------------------------------------------------*
DATA: BEGIN OF list_info,
         object          LIKE tnro-object.
DATA: END OF list_info.

DATA: BEGIN OF error.
        INCLUDE STRUCTURE inrer.
DATA: END OF error.

DATA: error_occured          TYPE c VALUE '0',
      warning_occured        TYPE c VALUE '0'.

*----------------------------------------------------------------------*
* Inizio programma
*----------------------------------------------------------------------*
START-OF-SELECTION.

  PERFORM leggi-dati.
  PERFORM aggiorna-ranges.

*&---------------------------------------------------------------------*
*&      Form  LEGGI-DATI
*&---------------------------------------------------------------------*
FORM leggi-dati .

  DATA: w_num(2) TYPE n,
        w_pre(2) TYPE n.

  IF i_anno < 2017 OR
     i_anno > 2099.
    MESSAGE 'Anno errato!!!' TYPE 'S'.
    STOP.
  ENDIF.

  w_num = i_anno+2(2).
  w_pre = w_num - 1.

  SELECT * FROM nriv WHERE object    = 'RF_BELEG'
                       AND subobject = i_bukrs
                       AND toyear    = i_anno
                       AND nrlevel   = 0.     "solo con stato iniziale

    CLEAR xnriv.
    MOVE-CORRESPONDING nriv TO xnriv.

    IF xnriv-fromnumber+0(2) = w_pre AND
       xnriv-tonumber+0(2)   = w_pre.
      xnriv-fromnumber+0(2) = w_num.
      xnriv-tonumber+0(2)   = w_num.
      xnriv-procind = 'U'.
      APPEND xnriv.
    ENDIF.

  ENDSELECT.

ENDFORM.                    " LEGGI-DATI
*&---------------------------------------------------------------------*
*&      Form  AGGIORNA-RANGES
*&---------------------------------------------------------------------*
FORM aggiorna-ranges .

  IF xnriv[] IS INITIAL.
    MESSAGE 'Nessun aggiornamento richiesto!!!' TYPE 'S'.
    EXIT.
  ENDIF.

  REFRESH interval.
  LOOP AT xnriv.
    interval = xnriv.
    APPEND interval.
  ENDLOOP.

  list_info-object = 'RF_BELEG'.

* controllo LOCK
  CALL FUNCTION 'NUMBER_RANGE_ENQUEUE'
    EXPORTING
      object       = list_info-object
    EXCEPTIONS
      foreign_lock = 01.
  IF sy-subrc = 01.
    MESSAGE 'ranges bloccati da altri utenti!!!' TYPE 'S'.
    STOP.
  ENDIF.

  CALL FUNCTION 'NUMBER_RANGE_INTERVAL_UPDATE'
    EXPORTING
      object          = list_info-object
    IMPORTING
      error           = error
      error_occured   = error_occured
      warning_occured = warning_occured
    TABLES
      error_iv        = error_iv
      interval        = interval.

  IF error_occured <> 0.
    MESSAGE 'ERRORI !!!! NESSUN AGGIORNAMENTO FATTO.' TYPE 'S'.
    BREAK-POINT.
    STOP.
  ENDIF.

  CALL FUNCTION 'NUMBER_RANGE_UPDATE_CLOSE'
    EXPORTING
      object          = list_info-object
    EXCEPTIONS
      no_changes_made = 1.

  COMMIT WORK AND WAIT.

ENDFORM.                    " AGGIORNA-RANGES

pagina di avvio:




Nessun commento:

Posta un commento