Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

Inbound IDoc Validation

Former Member
0 Likes
1,613

Hi all,

we process an extended version of DEBMAS01 IDoc on inbound and need to verify if the incoming IDoc does not contain outdated information already. Basically, we check if the underlying record was not yet changed in SAP based on change pointer BDCPS.

To achieve this we created a new process code that executes a new function module. This function module first retrieves the SAP kunnr of the DEBMAS01 and retrieves the record from KNA1. Afterwards we check if there any entries in BDCPS that are not yet processed. If so, we reject the IDoc. If not, we validate a specific version in KNA1 in addition against a custom field in DEBMAS01. At the end the standard function module IDOC_INPUT_DEBITOR to apply the information to KNA1.

Now, our problem is we need to lock the KNA1 record before we check for change pointers, otherwise the whole logic will not work if there happens a change at the same time. We tried to use enqueue/dequeue functions, but then the IDOC_INPUT_DEBITOR function module raises the error that the record is already locked. We also tried to update the KNA1 record before we check BDCPS, but unfortunately when IDOC_INPUT_DEBITOR is called the update gets committed and we loose the database lock.

Do you have any ideas how we could lock the record or another concept in mind? We don't want to copy IDOC_INPUT_DEBITOR and utilize as much standard as possible.

Many thanks for your input...we drive crazy here...especially as with a WAIT UP TO we cannot test the database LUWs as they are committed with a WAIT....

Cheers

Our custom function module:

FUNCTION Z_IDOC_INPUT_DEBITOR.

*"----

-


""Lokale Schnittstelle:

*" IMPORTING

*" VALUE(INPUT_METHOD) LIKE BDWFAP_PAR-INPUTMETHD

*" VALUE(MASS_PROCESSING) LIKE BDWFAP_PAR-MASS_PROC

*" VALUE(PI_XD99_USED) TYPE CHAR1 DEFAULT SPACE

*" VALUE(PI_KNVK_SPECIAL) TYPE CHAR1 DEFAULT SPACE

*" EXPORTING

*" VALUE(WORKFLOW_RESULT) LIKE BDWFAP_PAR-RESULT

*" VALUE(APPLICATION_VARIABLE) LIKE BDWFAP_PAR-APPL_VAR

*" VALUE(IN_UPDATE_TASK) LIKE BDWFAP_PAR-UPDATETASK

*" VALUE(CALL_TRANSACTION_DONE) LIKE BDWFAP_PAR-CALLTRANS

*" TABLES

*" IDOC_CONTRL STRUCTURE EDIDC

*" IDOC_DATA STRUCTURE EDIDD

*" IDOC_STATUS STRUCTURE BDIDOCSTAT

*" RETURN_VARIABLES STRUCTURE BDWFRETVAR

*" SERIALIZATION_INFO STRUCTURE BDI_SER

*" EXCEPTIONS

*" WRONG_FUNCTION_CALLED

*"----

-


DATA: zzfred like ZZFRED, "SFDC Extended Segment

i_e1kna1m like e1kna1m,

i_kna1 like kna1,

ls_idoc_data type edidd, "manipulierte IDOC DATA

lv_index type sy-tabix. "Index in table IDOC_DATA

DATA: i_CPIDENT like BDCPS-CPIDENT,

number_records type NUM.

  • Flag signals if customer already locked.

DATA: locked(1) type c value 'N'.

TABLES: bdcp,

bdcps.

*-------

*Sleep Pointer setzen, um LOCK auf Datensatz zu testen

  • WAIT UP TO 300 SECONDS.

*-------

LOOP AT IDOC_DATA.

CASE IDOC_DATA-segnam.

  • E1KNA1M

WHEN 'E1KNA1M'.

i_e1kna1m = IDOC_DATA-SDATA.

read table idoc_data into ls_idoc_data

with key segnam = IDOC_DATA-segnam.

lv_index = sy-tabix.

  • ZZFRED

WHEN 'ZZFRED'.

zzfred = IDOC_DATA-SDATA.

ENDCASE.

ENDLOOP.

  • <---------------------------------------------------------------------

  • Prüfen ob KUNNR übergeben wurde, sonst auf SFDC prüfen

  • und dann mit SFDC_ID die KUNNR aus SAP holen,

  • ansonsten eine neue SAP KUNNR erzeugen als nächst höhere freie Nr

IF i_e1kna1m-KUNNR eq '/'. "Kundennummer wurde nicht mit IDOC

"übergeben = '/' oder blank '' je nach

"Einstellung in INFA

SELECT SINGLE * FROM kna1 into i_kna1

WHERE sfdc_id = zzfred-sfdc_id.

IF sy-subrc eq 0. " Kunde gefunden in Kna1

  • IDOC Feld KUNNR den Wert aus Tabelle KNA1 zuweisen

i_e1kna1m-kunnr = i_kna1-kunnr.

ELSE.

  • neuen Wert für KUNNR erstellen und dann IDOC Segment zuweisen

i_e1kna1m-kunnr = '0000059376'. "

  • Code wechseln, so dass Wert

  • aus Tabelle ankommt

ENDIF. "sy-subrc

ENDIF. "Kunnr nicht gefüllt

  • KUNNR nun im manipulierten IDOC DATA Record vorhanden, aber noch nicht

  • an IDOC_DATA übertragen. Dies geschieht durch modify Anweisung folgend

  • i_e1kna1m-KUNNR = '0000059377'.

  • i_e1kna1m-STRAS = 'Hinterm Hornbach'.

  • manipulierte IDOC Daten übertragen

ls_idoc_data-sdata = i_e1kna1m. "man. Segment übertragen

modify idoc_data from ls_idoc_data index lv_index.

  • --------------------------------------------------------------------->

*------- Konto sperren KNA1 -

-


  • CALL FUNCTION 'ENQUEUE_EXKNA1'

  • EXPORTING

  • KUNNR = i_e1kna1m-kunnr

  • EXCEPTIONS

  • FOREIGN_LOCK = 1

  • SYSTEM_FAILURE = 2.

  • CASE SY-SUBRC.

  • WHEN 1.

  • LOCKED = 'Y'.

  • ROLLBACK WORK.

  • "MESSAGE E042 WITH kna1m-kunnr.

  • "von anderem Benutzer gesperrt

  • WHEN 2.

  • "MESSAGE E038. "Systemfehler

  • ROLLBACK WORK.

  • ENDCASE.

  • <---------------------------------------------------------------------

  • Nun prüfen, ob IDOC verarbeitet werden soll, hier auf Kriterien prüfen

  • SAP_VERSION prüfen

  • Change Pointer prüfen

  • Status für IDOC ändern (Bsp.: S.648 Buch)

*

if locked eq 'N'.

SELECT SINGLE * FROM kna1 into i_kna1

WHERE kunnr = i_e1kna1m-kunnr.

IF sy-subrc eq 0. " Kunde gefunden in Kna1

i_kna1-system_of_change = 'SFDC'.

update kna1 from i_kna1.

SELECT COUNT(*) INTO number_records

FROM BDCPS AS a INNER JOIN BDCP AS b

ON aCPIDENT = bCPIDENT

WHERE aPROCESS <> 'X' AND aMESTYPE = 'DEBMAS'

AND b~CDOBJID = i_e1kna1m-kunnr.

IF number_records > 0.

i_kna1-sap_version = i_kna1-sap_version + number_records.

EXIT.

ENDIF.

  • ENDSELECT.

IF zzfred-sap_version < i_kna1-sap_version

OR zzfred-sfdc_version < i_kna1-sfdc_version.

IDOC_STATUS-DOCNUM = IDOC_CONTRL-DOCNUM.

IDOC_STATUS-STATUS = '51'.

IDOC_STATUS-MSGTY = 'E'.

IDOC_STATUS-MSGID = 'ZE'.

IDOC_STATUS-MSGNO = '005'.

IDOC_STATUS-MSGV1 = i_e1kna1m-kunnr.

APPEND IDOC_STATUS.

WORKFLOW_RESULT = '99999'. "C_WF_RESULT_ERROR.

RETURN_VARIABLES-WF_PARAM = 'Error_IDOCs'.

RETURN_VARIABLES-DOC_NUMBER = IDOC_CONTRL-DOCNUM.

APPEND RETURN_VARIABLES.

EXIT.

ENDIF. "zzfred-sap_version

ENDIF. "sy-subrc

  • Und wenn abgelehnt, dann EXIT setzen, oder IF Bedingung, aber die

  • nachstehende Function 'IDOC_INPUT_DEBITOR' nicht ausführen

*

  • --------------------------------------------------------------------->

  • Wenn alles in Ordnung ist und IDOC nicht abgelehnt wird, dann Function

  • aufrufen, um IDOC verarbeiten zu lassen, allerdings mit den

  • manipulierten Daten.

CALL FUNCTION 'IDOC_INPUT_DEBITOR'

DESTINATION SPACE

EXPORTING

INPUT_METHOD = INPUT_METHOD

MASS_PROCESSING = MASS_PROCESSING

IMPORTING

WORKFLOW_RESULT = WORKFLOW_RESULT

APPLICATION_VARIABLE = APPLICATION_VARIABLE

IN_UPDATE_TASK = IN_UPDATE_TASK

CALL_TRANSACTION_DONE = CALL_TRANSACTION_DONE

TABLES

IDOC_CONTRL = IDOC_CONTRL

IDOC_DATA = IDOC_DATA

IDOC_STATUS = IDOC_STATUS

RETURN_VARIABLES = RETURN_VARIABLES

SERIALIZATION_INFO = SERIALIZATION_INFO

EXCEPTIONS

WRONG_FUNCTION_CALLED = 1

OTHERS = 2

.

rollback work.

  • ------ Konto entsperren ---------------------------------------------*

  • CALL FUNCTION 'DEQUEUE_EXKNA1'

  • EXPORTING

  • KUNNR = i_e1kna1m-kunnr

  • EXCEPTIONS

  • SYSTEM_FAILURE = 1.

endif.

ENDFUNCTION.

2 REPLIES 2
Read only

Former Member
0 Likes
774

Hi Maic,

Why not locking the KNA1, execute your checks, and then delocking the KNA1 just before you call the IDOC_INPUT_DEBITOR?

Regards,

John.

Read only

0 Likes
774

Yes, we did this already, but still somebody could change the record between we release the lock and the IDoc is processed in the standard module. Is there a way to get the lock and "pass" it into the module or better to say that the standard module can relock the record as it's the same transaction and user.