Sunday, March 30, 2014

SAP ECC6.0 : BAPI_INCOMINGINVOICE_CREATE gives 'Enter G/L Account' error.

Last three weeks (at the same time my SPS-22 Upgrade is in motion), I have been assigned to check out an error that keeps telling user to "Enter G/L Account" when they tried to run a program to automatically create invoice based on a file. 

1. I thought the file pass by another 3rd party system provided some wrong data in it. So I had the parameters checked against old files and previous technical specification. I found no discrepancies. 

2. So it had to be some changes in the BAPI "BAPI_INCOMINGINVOICE_CREATE1", and I thought some user exits OR enhancement points done by some programmers had some effect to it. Or there were some change in the business process as a result of those exits/enhancement. None I found and even if the business process had change, the affect shouldn't be so adverse until existing customized business program's logic ran away. Even if it does, the previous programmers or functionals should've given thought of other customized programs will be affected by their changes. 

3. Irregardless, I gave trace (ST05) on the customized program. So I found the following trace analysis : 
- SAPLMRM_BAPI - DIM_GENERAL_SAPLMRM_BAPI==== - BAPI_INCOMINGINVOICE_REATEMRM_
- SAPLMRM_BAPI - LMRM_BAPIF0C - MRM_INVOICE_CREATE_CALL
- SAPLMRM_BAPI - LMRM_BAPIF0C - MRM_INVOICE_CREATE_CAL_N - MRM_INVOICE_CREATE (Line 39)
- SAPLMRMH - LMRMHU09 - MRM_INVOICE_CHECK - MRM_DRSEG_FILL
- SAPLMRMH - LMRMHF0A - MRM_DRSEG_FILL - ME_READ_ITEM_INVOICE
- SAPLEINR - LEINRF2M - XEK08R_AUFBAUEN
- SAPLEINR - LEINRF5I - XEK08R_AUFBAUEN_BLANKO
- SAPLMRMH - LMRMHF07 - DRSEG_ITEM_CHECK - MRM_DRSEG_CHECK
- SAPLMRMH - LMRMHF07 - DRSEG_ITEM_CHECK - MEX_LESEN_SACHKONTO

When we trace the standard routines as called from the standard includes above, the error message ME - 083 ('Enter G/L Account') came to be validated in routine MEX_LESEN_SACHKONTO. 

MEX_LESEN_SACHKONTO is only validated by a call from BAPI's BAPI_INCOMINGINVOICE_CREATE1. Manual creation from ME21N, ME22N or MIR* tcode does not go through MEX_LESEN_SACHKONTO. Validation of G/L Account from MEX_LESEN_SACHKONTO is only done from a BAPI call. 

Findings : 
1. If you trace until SALEINR - LEINF5I - XEK08R_AUFBAUEN_BLANKO, and at the same time, you are creating an invoice for a blanket PO, you might bound to see BETS table containing type 99. This is normal as per invoice creation because the invoice creation is also based on all the best possible type to create it's line item. 

2. If you find your manual creation in MIRO works just well, then it is absolutely not related to any change of code in either user exits, enhancement implementation or both. 

3. MEX_LESEN_SACHKONTO is only validated from BAPI calling "BAPI_INCOMINGINVOICE_CREATE1". 

As a result, if you find yourself doing the same thing like I'm doing, you are checking at the wrong places but no harm done because you have, at least, find out where the error ME - 083 is coming from. The error message is definitely BAPI related but not due to standard coding. It is due to the table ACCOUNTINGDATA neither filled up or filled properly.

So, the solution: 
Check your BAPI's BAPI_INCOMINGINVOICE_CREATE1 table parameter's ACCOUNTINGDATA. Is it being filled or filled properly? This was my issue, the ACCOUNTINGDATA table parameter was not filled at all. As a result, the error message ME - 083 pops and halts the creation process. 

williamwilstroth... BAPI_INCOMINGINVOICE_CREATE1, ME083

Tuesday, March 4, 2014

SAP ECC6.0 : Tips on SE38 Editor

By chance and fooling around the SE38, I found one magic. Not really magic but I'm sure it's there. Just that, we don't really go explore much on the tips and tricks of SE38. Anyhow, here's the magic keys combination : Press CTRL and SPACE together at types declaration and comparators, you will get a push up list of available types or comparators. 

For example, here's the push up types of data declaration, 


Here's another example, the push up types of comparators,



There you go, good luck and happy exploration.

williamwilstroth... CTRL+SPACE, push up tips

Thursday, June 27, 2013

SAP ECC6.0 : LINE-SIZE and LINE-COUNT in any location.

I have to admit, these LINE-SIZE and LINE-COUNT has never come into my mind that one could put it anywhere in the coding but not at the REPORT syntax at the the first line. Nevertheless, the placement and its' way of usage had caught me by surprise. 

One of my assignments was to remove "Deleted" parts (line items) from a report. These parts, deleted, meaning no longer active or exist in the factory. All I had to do was to put in a line of code to remove this parts. That is simple. Unfortunately, this report did not properly optimized its' column width. The program was already coded in such a way it only use ALV fieldcat's output length to size its' own column. This is okay for me as long as the report work perfectly and beautifully but some of the columns were too tight. As a result of it, some values were chopped off by the ALV report. 

One way to lengthen this to display all the columns nicely is to increase the output length. Another way is to use back the DDIC structure's declared type's length (using "REUSE_ALV_FIELDCATALOG_MERGE" function module[1]). Both of these are fine way to adjust an ALV report column. However, both were not feasible at the moment. Why? There's only one reason to this and it is due to the LINE-SIZE that was initially declared in the REPORT heading. 

Generally, at one glance, one would assume, that this report does not use LINE-SIZE and LINE-COUNT too. This very report proved me wrong. W-R-O-N-G. The LINE-SIZE was strategically placed at a few locations because this is due to report types. Different report type sometimes prefer different type of LINE-SIZE. Here it goes. Now I know. I see. Mystery is solved. The LINE-SIZE was at another location.

Sources : 
[1]. For all SAP ALV Samples, go to SE80, select Package, and put "SLIS", and press Enter.

williamwilstroth... LINE-SIZE

SAP ECC6.0 : CSLEO_ENQUEUE and ME_PURCHASE_DOCUMENT_READ affecting output type.

When a program such as ME22N has already lock EKKO/EKPO tables thru ENQUEUE_EMEKKOE function, other programs won't be able to manipulate those standard tables until it is de-queue or released. Of course, it has to finish its one LUW (or known as Logical Unit of Work). But sometimes, programs we modified or wrote may somehow try to grab or should I say fight to use the same table. As a result we are embroiled in whether to let the initial LUW to finish or not. So we have UPDATE TASK at hand to let next program in waiting to finish after the initial LUW finish. Then, today, I learn something new, which is CSL. CSL is Cross System Lock and it works in a specified way to ensure that critical program that is running and updating a tables does not get used by other programs. CSL holds a major topic of its own. You can find it here

I met CSL in an issue which I had to troubleshoot why an output type, with external send '5', kept producing "Update Was Terminated" message. So, I began my journey to go through 3 programs : RSM13000, RSNAST00, and ZSAPFM06P_IDT2. RSM13000 relates to RV_UPDATE_MESSAGE function module. RSNAST00 is where you normally use it to test your output type. And the ZSAPFM06P_IDT2 is our main character which is also a driver or print program. Now, the issue at hand is we need to know why error "Update Was Terminated" message is pop up and the output type was not sent out. 

Naturally, the very first thing we will do, is to double check the output type profile and settings just to ensure that everything is okay. Then in my case, I personally love ST05 (Trace Analysis, yes you are right) to record everything what went wrong in the field. So I would activate my ST05 and then repeat the whole process until it gets the error. Then I would returned to ST05 and get a quick glance where the error is coming from then do a back tracing. Ever heard of back tracing? It's an idea which I developed over my 10 years of work with trouble shooting ABAP program. Sometimes, my back tracing works. Unfortunately, this time, it doesn't work at all. The reason is because the error was triggered from print program that was running in the background. So much information I can get from ST05. But ST05 is the primary forensic tool that I will use to trace my program. 

So here's my result when I used ST05 and pin-pointing suspects of crime or partner accessory to the crime scene:

1. ZSAPFM06P_IDT2->ZFM06PF02_IDT2->AUSGABE_POS
- ZFM06PF01_IDT2->POS_AUSGABEN
- ZFM06PF02_IDT2->ME_PURCHASE_DOCUMENT_DATA_READ

This is the first suspect, that I had to stop and examined him. Because when I used RSNAST00 to run him, it went to an error saying SE38 was not found in the process. SE38? Why would I use SE38? Simple. When one use RSNAST00 via SE38 to run, the SY-TCODE will be SE38. It was using SE38 as the main catalyst to determine which program was using to display or hold a PO document. So I thought I found my suspect but it was not because SY-TCODE would be holding another value if it's running in the background. 

2. ZFM06PF02_IDT2->AUSGABE_KOPF
This is the second suspect, which I thought is the culprit because the XDIALOG was not set to blank. General speaking, at least, I know that to run a print program in the background, it should not have any printer setting popping up or it may stall the whole background process leading to "Update Was Terminated". Of course, I used my surgical tool to make an incision and make sure XDIALOG is set to blank for the moment. Temporarily. Then I re-ran my test, the error message was still displaying despite I had it set to blank.

Although these 2 suspects were ready to be left alone but I had no intention to letting them go away. I was thinking I am missing something. So I had myself sit down and trace from the beginning especially when I clicked on the "Save" button. So it came across this 'ENQUEUE_EMEKKOE' in the trace analysis (ST05). Hence, I put a break-point at that very spot ie, 

SAPLMEXF->LMEXFU10->MQ_ENQUEUE_DOCUMENT

Then I ran from the beginning that is executing ME22N. The break-point was hit. Okay, it had to enqueue EKKO/EKPO, so the PO document can be used. Next, I went to repeat the output type again. Strange, it hit the "Update Was Terminated" again. So, what on earth, is happening. I went to see SM13 and look at this termination error. It said,
User XXXX already processing Purchase Order NNNNN
Okay, this meant something somewhere wants to use the EKKO/EKPO table but they cannot do so because ME22N has already enqueue these tables in the first place. So, the big question comes, 
Which program wants to access EKKO/EKPO?
Now, I had two questions, why does it need to access it again? And of course, the next question would which program wants to access them. So, the next two hours I had to start again at somewhere to try to find out which program. Was it the RSM13000? Or was it the RSNAST00? Or is it the print program itself, ZSAPFM06P_IDT2? I had to look into all these again. 

Firstly, RSM13000 is an RV_UPDATE_MESSAGE which I don't think it will do much since it is a bridge to call RSNASTED or RSNAST00 depending on which type of output type you are using. So that's leave print program alone ZSAPFM06P_IDT2. Just to prove it's innocence, I used its original clone SAPFM06P to run it. Voila, there was not a single error message at all. This is getting me somewhere! I opened two screens; each side by side so when I trace I would know what was the difference between these two print program. Well, behold, the logic was totally different from the other. One was querying KOMP using RV_PRICE_PRINT_READ and the other was using ME_PURCHASE_DOCUMENT_READ. The purpose of these two standard function calls is to derive the PO document's price/condition. RV_PRICE_PRINT_READ does not try to lock the EKKO/EKPO but ME_PURCHASE_DOCUMENT_READ tried to do a ENQUEUE_EMEKKOE again despite the ME22N had already done so. When ME_PURCHASE_DOCUMENT_READ tried to enqueue EKKO/EKPO, it went to check if there's another program is also using the table via CSLEO_ENQUEUE. Here's how I come to the conclusion that our culprit of this whole error was CSLEO_ENQUEUE or CSL (Cross System Lock). 

Cross System Lock had the system lock up so other program does not try to overtake the current program and used the table. Cross System Lock uses token concept to determine which program in a cross system is using a lock down table. Therefore, this has made my troubleshooting easier now.

Finally, I understood that this ZSAPFM06P_IDT2 which was written previously, uses ME_PURCHASE_DOCUMENT_READ to get KOMP (Pricing/Condition). And doing so, the call function tries to enqueue EKKO/EKPO and CSL had to walk in to tell us that we cannot do so because ME22N is already using it. That's why I get the error "Update Was Terminated" -> User "me" already processing Purchase Order "nnnnnnnnnn"

Though I have found out why the unduly "Update Was Terminated" error message occurs but there is still one more problem i.e. the customized program was original copy out and modified just for output type 1 - printing only. The NACHA (Output Type) 5 was not in the coding. No email will be send out. Hence, you need to find that spot that prepare all the email parameters and especially in OPEN_FORM function which it will export recipient and sender. In my case, it will be as below :


1. Routine AUSGABE_KOPF:
- When the coding starts to do task differently according to NACHA (Output type), you will need the following coding, 
      DATA lvs_comm_type   TYPE ad_comm,
             lvs_comm_values TYPE szadr_comm_values.

      CALL FUNCTION 'ADDR_GET_NEXT_COMM_TYPE'
        EXPORTING
          strategy           nast-tcode
          address_number     lfa1-adrnr
        IMPORTING
          comm_type          lvs_comm_type
          comm_values        lvs_comm_values
        EXCEPTIONS
          address_not_exist  1
          person_not_exist   2
          no_comm_type_found 3
          internal_error     4
          parameter_error    5
          OTHERS             6.

      IF sy-subrc <> 0.
        "Nothing to display.
      ENDIF.

      MOVE-CORRESPONDING nast TO intnast.
      MOVE sy-repid           TO xprogramm.

      CALL FUNCTION 'CONVERT_COMM_TYPE_DATA'
        EXPORTING
          pi_comm_type              lvs_comm_type
          pi_comm_values            lvs_comm_values
          pi_country                lfa1-land1
          pi_repid                  xprogramm
          pi_snast                  intnast
        IMPORTING
          pe_itcpo                  itcpo
          pe_device                 xdevice
          pe_mail_recipient         lvs_recipient
          pe_mail_sender            lvs_sender
        EXCEPTIONS
          comm_type_not_supported   1
          recipient_creation_failed 2
          sender_creation_failed    3
          OTHERS                    4.
      IF sy-subrc <> 0.
        "Avoid cancellation with message TD421
        retco '1'.

        PERFORM protocol_update USING '740' space space space space.

        "Dummy message to make the message appear in the where-used list
        IF 2.
          MESSAGE s740(me).
        ENDIF.

        EXIT.
      ENDIF.

      IF xdevice 'MAIL'.
        CALL FUNCTION 'SX_ADDRESS_TO_DEVTYPE'
          EXPORTING
            recipient_id lvs_recipient
            sender_id    lvs_sender
          EXCEPTIONS
            err_invalid  1
            err_system   2
            OTHERS       3.
        IF sy-subrc <> 0.
          retco '1'.

          PERFORM protocol_update USING '740' space space space space.

          IF 2.
            MESSAGE s740(me).
          ENDIF.

          EXIT.
        ENDIF.
      ENDIF.
Now, my issue is complete and user can issue email without trouble using the new output type. 

Here's some additional source to help you understand more when you click the "SAVE" button at output type page. (FCODE = 'V70S', this function code is standard code). Sometime we would like to know what are the function modules that were execute in UPDATE TASK mode.

1. CL_PO_HEADER_HANDLE_MM========CP -> CL_PO_HEADER_HANDLE_MM========CM00H -> PO_POST -> CALL FUNCTION 'MEPO_DOC_POST'
2. SAPLMEPO -> ISAUTO_SCH_EMM_MM06EF0B_BUCHENE -> BUCHEN -> CALL FUNCTION 'ME_UPDATE_DOCUMENT' IN UPDATE TASK -> LINE 51 (ENHANCEMENT 8)
3. SAPLMEPO -> FM06ECDC -> CD_CALL_EINKBELEG -> CALL FUNCTION 'EINKBELEG_WRITE_DOCUMENT' IN UPDATE TASK -> LINE 13
4. SAPLMEPO -> MM06EF0B_BUCHEN -> BUCHEN -> CALL FUNCTION 'ME_UPDATE_QUOTA_DIALOG' IN UPDATE TASK
5. SAPLEINU -> LEINUU05 -> ME_UPDATE_DOCUMENT -> CALL FUNCTION 'OUTBOUND_CALL_01000730_E'
6. SAPLVMSG -> LVMSGU02 -> RV_MESSAGE_UPDATE -> CALL FUNCTION 'WFMC_MESSAGE_SINGLE'


Edited on 06/28/2013 Friday 11:00 am. 

Reference  :

williamwilstroth... CSL, CSLEO_ENQUEUE, ERROR "Update Was Terminated" 

Tuesday, June 11, 2013

SAP ECC6.0 : Maximum Char. Length Per Cell in an ALV report

I had to combine several lines (records) of a column into a string. This string will then become a value in a column. This field is known as Ref Designator or technically known as EBORT. EBORT is a field part of the explosion of BOM material. EBORT field and value can be derive from Function Module "CSAP_MAT_BOM_READ" and output is a table known as "IT_STPU". So, imagine a material being exploded into multiple sub parts; this EBORT represented the exploded BOM material.

As the main material may consist more than a hundreds of sub-materials, the string will need to be longer in order to hold as many as the sub-parts it could in a manufacturing facility. In this report, it was finely displaying because it was displaying in rows of records. Now, when the change to combine all of the referential designation of BOM parts into one single string to be displayed in an ALV; most of the remaining parts were chopped off. 

This chopping off was due to ALV's per cell only allowed 128 maximum characters to be displayed out. Hence, I had a chopped off parts of combined EBORT. So, i had the following attempt to try to expand the length in the ALV : 
- Put in "255" characters in ALV Fieldcat's INTLEN = '255'.
- Put in "255" characters in ALV Fieldcat's OUTPUTLEN = '255'.
- Declared "255" characters in the holding variable; GV_EBORT(255) TYPE C.

None of the above were able to force ALV to display a string longer than 128 in its' cell. 

Then, I found this note, 857823, that specifically states that this is "standard system behavior and cannot be changed". Now, I really need to find an alternative.

To tackle this problem, and user still insist on displaying EBORT's value in a single stream, I had to let them know the maximum characters that cell can display; I suggested that they break it into two streams or more if EBORT gets bigger.

So, my alternative solution - retain a single stream of combined EBORT but it will break into second line if it reaches 128 character. But the ceiling length I need to start breaking nicely will be reaching 120 characters or less depending on the EBORT whole next word. We don't want to break something half of a whole word.

williamwilstroth... EBORT, CSAP_MAT_BOM_READ, 128 Characters Only.

Tuesday, January 22, 2013

SAP ECC6.0 : Consignment Issue Custom Schedule Dates Auto Update

Six months ago, I had the task to do a custom implementation on the consignment issue document that it could automatically update the line item's schedule dates. Schedule dates like Goods Issue Date, Loading Date, Material Available Date and Transportation Plan Date. All these dates by requirement is to be updated according to Line Item's Delivery Date. The Delivery Date will determine all the Schedule Dates according to the Route's Transit Days. So to speak, we need to ensure that this change is only for consignment issue and no other document will be affected. 

Let's identified all those Schedule Dates that we need to modify or automatically update : 
  • VBEP-WADAT (Goods Issue Date)
  • VBEP-LDDAT  (Loading Date)
  • VBEP-MBDAT (Material Availability Date)
  • VBEP-TDDAT  (Transportation Date) 
Now, here's the challenge, how do I make sure the change takes place and it shows on Shipping Screen. There are two places of Shipping Screen that need to display the updated values. So, I identified two screens :
  • SAPMV45A - SCREEN 4552 (Line Item - Schedule Lines - Shipping Tab)
  • SAPMV45A - SCREEN 4921 (First Screen - Shipping Tab)
Modification for above screens requires 2 enhancement points and 1 user exit. 

1. SAPMV45A - SCREEN 4552 (Schedule Line - Shipping)
There will be one enhancement point here just to ensure the automatic calculation of those schedule dates are display at the screen. The enhancement point will be right after MODULE VBEP-EDATU_AUSGEBEN. That will be where the screen start to fill the schedule dates.

Inside the enhancement point, you should take into consideration of WORK DAYS and NON-WORK DAYS. The day, after Delivery Date minus Transit Days, falls on NON-WORK DAYS, then it should push back one day until it is a WORK DAY. 

In order to get the Transit Days, you need to query TVRO (SAP Table). The field that shows number of days is TRAZTD. This value is in hours and you will need to convert it to days. The function to do the conversion is 'CONVERSION_EXIT_TSTRG_OUTPUT'. 

After you have determine the number of Transit Days and WORK DAY/NON-WORK DAY, you will use the new date as your schedule dates. These schedule dates will be updated to XVBEP. 

2. SAPMV45A - SCREEN 4921 (Overview - TC - Shipping Default)
There is no modification here. The result is a result of calculation in MV45AFZZ. 

3. MV45AFZZ (User Exit)
The logic in SAPMV45A - SCREEN 4552 is applied here too. Same logic.

williamwilstroth... consignment issue, mv45afzz, tvro, traztd, route.

Tuesday, January 8, 2013

SAP ECC6.0 : VEPVG and Delivery Not Created - Part 3

From previous entry, we know when AND where the VEPVG table got inserted and then deleted. But the big question is "Why the record got deleted?". Well, I am going to tell you here that I finally found the cause of it, underlying cause to be put in here correctly.

In order to understand how does VA02 (Change Order) screen goes to that point of DELETE a record from VEPVG, I will let you see the traces of coding which I pinpoint below. You should take into consideration of analyzing how the SAP core code flowing through VA02 (PAI) after you click the "SAVE" button. 

1. When you click "SAVE", it goes thru the following :
Line 1. SAPLV45U -> LV45UFOR -> RV_SALES_DOCUMENT_UPD ->  RV_SALES_DOCUMENT_INDEX_UPDAT.
Line 2. SAPLV05I  -> LV05IFIX     -> INDICES_SCHREIBEN               -> INDICES_AUFBAUEN
Line 3. SAPLV05I  -> LV05IFEP    -> EP_01                                      -> LV05IF0V                   -> INDEX_VEPVG_AUFBAUEN
Line 4. SAPLV05I  -> LV05IFIX     -> INDICES_SCHREIBEN               -> INDEX_VEPVG_SCHREIBEN

2. What does each of line of traces means to you :
The first three lines indicates your primary entry to getting your code prepare to update Indices. Yes, there are many other indices tables like VAKMA, VAPMA, VEPVG and others. VEPVG is one of the important ones related to this issue (my entry).

Pay particular attention to line 2 and 3, 
- SAPLV05I  -> LV05IFIX -> INDICES_SCHREIBEN -> INDICES_AUFBAUEN
This line interprets how the system will fill YVEPVG and XVEPVG to be use in the following includes.  

- SAPLV05I  -> LV05IFEP -> EP_01 -> LV05IF0V -> INDEX_VEPVG_AUFBAUEN
This section of ABAP coding tells you how the Schedule dates will be determine for VEPVG. 

Then, let's focus on line 4.
Line 4. SAPLV05I  -> LV05IFIX -> INDICES_SCHREIBEN -> INDEX_VEPVG_SCHREIBEN 
This line tells you and me, how the table VEPVG gets maintained. 

So now, you know the moment when we press "SAVE" button to trigger SICH command, SAP actually flows through these following processes AND I AM TELLING YOU, there are no problem and no errors here in this coding. 

So, for god sake, where and why it is saving the VEPVG correctly?!?!?!

The answer is - you, I meant myself, did not maintain my enhancement points or user exits correctly for Y and X tables. Simple huh? Yes it is that simple. But, the complexity lies in trying to find out WHICH user exit or enhancement points that is CAUSING this problem!    
 
In my case, I had to spent 3 days long, okay, i had a week Christmas break. But that thought during the whole holiday is challenging enough for you to go back to office and do a deep dig on all the user exits; just to find out the cause why VEPVG is not saving a particular record. 

The cause of my case was an enhancement point which I'd created it for the EDI team back in August 2012.   


Back in August, I had an IDOC Order Response Enhancement project for the EDI team, and this enhancement was a fix to mend back some missing multiple schedule lines. As a result of this fix, VEPVG was affected. Therefore, the dig i can tell you, is deep dig. I had to go to MV45AFZZ before going to SE19 (you should know what this TCODE do) and display a whole list of Z-enhanced fix. 

In this case, I dive straight in to the enhancement point to correct the YVBEP table. Yes, the moment you make some change to YVBEP table, it wil indirectly change it's behavior. So do be very careful when you are changing any of X and Y internal tables. You may not know what future scenarios you are changing. 

So, it's an all well end's well. I hope in this 3 part you've gain some insight on why your X and Y internal tables is so important. Yes, i know X and Y tables exist in all user exits but you and I know we can't help it because we are all happily using it to solve our daily ABAP assignments, mini projects and big projects. Good luck!

References : 
415716 - User Exits in Delivery Processing
128947 - Correction of SD Document Indexes With RVV05IVB
178328 - Problems due to Incorrect User Exits in SD
 
williamwilstroth... SAPLV05I, LV05IFIX, INDEX_VEPVG_SHCREIBEN