This program checks all INVOIC MM IDocs in status 64 and 66 to determine if they have been received. Those IDocs older than 10 days that have still not been goods receipted are given error status 51.
REPORT ZIDOCERROR message-id ZS7 . *______________________________________________________________________ */ Program Name: Process invoice IDocs with Goods Receipt */ Description : This program checks all INVOIC MM IDocs in status 64 * and 66 to determine if they have been received. Those * IDocs older than 10 days that have still not been * goods receipted are given error status 51. */ Transaction : N/A - run via scheduled job *______________________________________________________________________ tables: edidc, mkpf, ekpo, rbkp, e1edk01, e1edka1, e1edk02, e1edp02. data: iedidc like edidc occurs 1 with header line, data_rec like edidd occurs 1 with header line. data: c_docnum(16) type c, c_mblnr(10) type c, c_invoic(10) type c, rc(1) type c, lead_time like lfm1-plifz, gr_qty like mseg-erfmg, test_date like sy-datum, gr_required like ekpo-webre, po_number(10) type n, po_lineno like ekpo-ebelp, n_vend(10) type n, vendor_id like lfa1-lifnr. data: begin of itab_gr occurs 0, mblnr like mkpf-mblnr, bwart like mseg-bwart, erfmg like mseg-erfmg, end of itab_gr. constants: * name of container element (workitem object id) C_ELEMENT_WI_OBJ_ID LIKE SWCONT-ELEMENT VALUE '_WI_OBJECT_ID', * name of container element (NumberPlusEventcode) C_ELEMENT_NO_PLUS_INFO LIKE SWCONT-ELEMENT VALUE 'NumberPlusEventcode'. ranges: r_status for edidc-status. TYPE-POOLS: * general idoc type pool TIDOC. ************************************************************************ * INCLUDES * ************************************************************************ * include for workflow programming INCLUDE <CNTN01>. ************************************************************************ * INNITIALIZATION * ************************************************************************ initialization. * create IDoc status selection table. clear r_status. refresh r_status. MOVE: 'EQ' TO r_status-OPTION, "equals 'I' TO r_status-SIGN, "include '64' TO r_status-LOW. APPEND r_status. MOVE: '66' TO r_status-LOW. APPEND r_status. ************************************************************************ * START-OF-SELECTION ************************************************************************ start-of-selection. select * from edidc into table iedidc where status in r_status and direct = '2' and "inbound mestyp = 'INVOIC' and mescod = 'MM'. loop at iedidc. clear rc. CALL FUNCTION 'EDI_DOCUMENT_OPEN_FOR_READ' EXPORTING DOCUMENT_NUMBER = iedidc-docnum IMPORTING IDOC_CONTROL = IEDIDC EXCEPTIONS DOCUMENT_FOREIGN_LOCK = 01 DOCUMENT_NOT_EXIST = 02 DOCUMENT_NUMBER_INVALID = 03 ERROR_MESSAGE = 04 OTHERS = 05. IF NOT SY-SUBRC IS INITIAL. c_docnum = iedidc-docnum. shift c_docnum left deleting leading '0'. * 'Cannot open INVOIC IDoc & for Goods Receipt processing' message w025 with c_docnum. continue. ENDIF. call function 'EDI_SEGMENTS_GET_ALL' exporting document_number = iedidc-docnum tables idoc_containers = data_rec exceptions document_number_invalid = 1 end_of_document = 2 others = 3. if not sy-subrc is initial. CALL FUNCTION 'EDI_DOCUMENT_CLOSE_READ' EXPORTING DOCUMENT_NUMBER = iedidc-docnum IMPORTING IDOC_CONTROL = iedidc c_docnum = iedidc-docnum. shift c_docnum left deleting leading '0'. * 'Cannot retrieve data for INVOIC IDoc & (Goods Receipt processing)' message w030 with c_docnum. continue. else. CALL FUNCTION 'EDI_DOCUMENT_CLOSE_READ' EXPORTING DOCUMENT_NUMBER = iedidc-docnum IMPORTING IDOC_CONTROL = iedidc. * If this is a change or modify IDoc, change status to 51 (error). * One & only one K01 segment should exist - read table data_rec with key segnam = 'E1EDK01'. if sy-subrc is initial. move data_rec-sdata to e1edk01. case e1edk01-action. when '000'. "original data * OK - do nothing when '002'. "modified data * 'Invoice & - IDoc for Review Only' perform idoc_status_update using '51' '028' 'Modification' ' '. when '002'. "modified data * 'Invoice & - IDoc for Review Only' perform idoc_status_update using '51' '028' 'Cancellation' ' '. endcase. endif. check rc is initial. * get the vendor no. clear vendor_id. loop at data_rec where segnam = 'E1EDKA1'. move data_rec-sdata to e1edka1. check: e1edka1-parvw = 'LF', e1edka1-partn co ' 0123456789', e1edka1-partn <> ' '. n_vend = e1edka1-partn. vendor_id = n_vend. endloop. * if this is a new IDoc, check to make sure it even needs the GR test clear gr_required. loop at data_rec where segnam = 'E1EDP02'. move data_rec-sdata to e1edp02. check: e1edp02-qualf = '001', e1edp02-belnr <> ' ', e1edp02-zeile <> ' '. * Note that a missing PO number / line number is NOT an error here - * the IDoc will error in the standard SAP processing in RBDAPP01 shift e1edp02-belnr left deleting leading '0'. clear: po_number, po_lineno. if e1edp02-belnr co ' 0123456789'. po_number = e1edp02-belnr. endif. if e1edp02-zeile co ' 0123456789'. po_lineno = e1edp02-zeile. endif. select single webre from ekpo into gr_required where ebeln = po_number and ebelp = po_lineno. if ( sy-subrc is initial and gr_required = 'X' ). exit. endif. endloop. "E1EDP02 segments * if any line item on this invoice requires a goods receipt, continue * receipt evaluation. Otherwise, status the IDoc to go to standard SAP * processing. (Assumption is made that if an IDoc has status 66, the GR * flag was turned "on" at some point and has since been removed.) if gr_required is initial. "no goods receipt required if iedidc-status = '66'. * 'Goods Receipt no longer required' perform idoc_status_update using '64' '026' ' ' ' '. endif. continue. "next IDoc endif. * Should be only one K02, but loop just in case... loop at data_rec where segnam = 'E1EDK02'. move data_rec-sdata to e1edk02. if e1edk02-qualf = '009'. * if an invoice already exists for this ref. no., give the IDoc * an error status select single belnr from rbkp into rbkp-belnr where xblnr = e1edk02-belnr(16) and blart = 'KR' "invoice and stblg = ' '. "no reversal if sy-subrc is initial. *'Invoice & already exists for ref.no. &' c_invoic = rbkp-belnr. shift c_invoic left deleting leading '0'. perform idoc_status_update using '51' '027' c_invoic e1edk02-belnr(16). exit. "exit loop on data recs for this IDoc endif. clear: itab_gr, gr_qty. refresh: itab_gr. select a~mblnr b~bwart b~erfmg into corresponding fields of table itab_gr from mkpf as a inner join mseg as b on a~mblnr = b~mblnr where a~vgart = 'WE' "goods receipt for PO and a~blart = 'WE' "goods receipt and a~xblnr = e1edk02-belnr(16). loop at itab_gr. case itab_gr-bwart. when '101'. "receipt gr_qty = gr_qty + itab_gr-erfmg. when '102'. "reversal gr_qty = gr_qty - itab_gr-erfmg. endcase. endloop. * if no goods receipt if gr_qty <= 0. case iedidc-status. * if new IDoc, status to '66' when '64'. * 'Waiting for Goods Receipt' perform idoc_status_update using '66' '022' ' ' ' '. * if reprocessed IDoc, check length of delay and status to 51 * (late receipt) if > 10 days. when '66'. clear lead_time. select single plifz from lfm1 into lead_time where lifnr = vendor_id and ekorg = '7100'. if lead_time is initial. lead_time = 10. endif. test_date = iedidc-credat + lead_time. **TEST ** if test_date > sy-datum. **TEST if test_date <= sy-datum. * 'Goods Receipt Overdue' perform idoc_status_update using '51' '024' ' ' ' '. else. * do nothing - IDoc stays in status 66 and gets tested for GR in next * job run endif. endcase. else. "goods receipt exists * if this is a reprocess of an IDoc for which a goods receipt now * exists, give the IDoc status 64, so it is processed by RBDAPP01 * in the next job step. if iedidc-status = '66'. c_mblnr = mkpf-mblnr. shift c_mblnr left deleting leading '0'. * 'Goods Receipt found for ref.no. &' perform idoc_status_update using '64' '023' e1edk02-belnr(16) ' '. endif. endif. else. "wrong K02 qualifier * do nothing - IDoc will try to post and be handled manually endif. "QUALF='009' endloop. "data_rec endif. "successful retrieval of IDoc data segments > data_rec endloop. "iedidc end-of-selection. *----------------------------------------------------------------------- * FORM IDOC_STATUS_UPDATE * Creates status records for the selected IDocs. *----------------------------------------------------------------------- FORM IDOC_STATUS_UPDATE using value(i_stat) value(i_msgno) value(i_msgv1) value(i_msgv2). tables: edi_ds, tede2. DATA: MESS like EDIMESSAGE. data: l_commit_counter LIKE ediglodata-comcount value '00000001', inbsync LIKE ediglodata-inbsync, t_couple_to_process LIKE ediinbound OCCURS 0 WITH HEADER LINE. CALL FUNCTION 'EDI_DOCUMENT_OPEN_FOR_PROCESS' EXPORTING DOCUMENT_NUMBER = iedidc-docnum IMPORTING IDOC_CONTROL = IEDIDC EXCEPTIONS DOCUMENT_FOREIGN_LOCK = 01 DOCUMENT_NOT_EXIST = 02 DOCUMENT_NUMBER_INVALID = 03 ERROR_MESSAGE = 04 OTHERS = 05. IF NOT SY-SUBRC IS INITIAL. c_docnum = iedidc-docnum. shift c_docnum left deleting leading '0'. * 'Cannot open INVOIC IDoc & for Goods Receipt processing' message w025 with c_docnum. rc = 'X'. exit. ENDIF. CLEAR EDI_DS. EDI_DS-DOCNUM = iedidc-DOCNUM. EDI_DS-STATUS = i_stat. EDI_DS-REPID = 'ZS7BM000007'. EDI_DS-TABNAM = 'EDI_DS'. EDI_DS-MANDT = SY-MANDT. EDI_DS-STAMQU = 'SAP'. EDI_DS-STAMID = 'ZS7'. EDI_DS-STAMNO = i_msgno. EDI_DS-STAPA1 = i_msgv1. EDI_DS-STAPA2 = i_msgv2. GET TIME. EDI_DS-LOGDAT = SY-DATUM. EDI_DS-LOGTIM = SY-UZEIT. CALL FUNCTION 'EDI_DOCUMENT_STATUS_SET' EXPORTING DOCUMENT_NUMBER = iedidc-DOCNUM IDOC_STATUS = edi_ds IMPORTING IDOC_CONTROL = iedidc EXCEPTIONS DOCUMENT_NUMBER_INVALID = 1 OTHER_FIELDS_INVALID = 2 STATUS_INVALID = 3 OTHERS = 4 . IF NOT SY-SUBRC IS INITIAL. c_docnum = iedidc-docnum. shift c_docnum left deleting leading '0'. * IDoc no. & failed status update to & message w021 with c_docnum i_stat. ENDIF. CALL FUNCTION 'EDI_DOCUMENT_CLOSE_PROCESS' EXPORTING DOCUMENT_NUMBER = iedidc-DOCNUM. if i_stat = '51'. clear: t_couple_to_process. refresh: t_couple_to_process. select single * from tede2 into tede2 where evcode = 'INVL'. if sy-subrc is initial. t_couple_to_process(16) = iedidc-docnum. t_couple_to_process+16(138) = tede2. append t_couple_to_process. PERFORM analyzing_event_create TABLES t_couple_to_process USING l_commit_counter inbsync. if sy-subrc is initial. MESS-MSGID = 'ZS7'. MESS-MSGTY = 'E'. MESS-MSGNO = i_msgno. MESS-MSGV1 = i_msgv1. MESS-MSGV2 = i_msgv2. CALL FUNCTION 'IDOC_ERROR_WORKFLOW_START' EXPORTING DOCNUM = 0 EVENTCODE = 'EDIM' MESS = mess STATUSMESS = mess EXCEPTIONS NO_ENTRY_IN_TEDE5 = 1 ERROR_IN_START_WORKFLOW = 2 OTHERS = 3. COMMIT WORK. endif. "link created endif. "tede2 found endif. * Set return code to stop further processing of this IDoc rc = 'X'. ENDFORM. *----------------------------------------------------------------------- * FORM ANALYZING_EVENT_CREATE * Creates link between IDoc and workflow container. * SAP code stolen from LEDINF01 *----------------------------------------------------------------------- FORM analyzing_event_create TABLES t_couple_to_process_in STRUCTURE ediinbound USING commit_counter_in LIKE ediglodata-comcount start_recfb_synchron_in LIKE ediglodata-inbsync. * local variables DATA: * instance that is created l_object TYPE swc_object, * object key, e.g IDoc number l_object_key LIKE swotobjid-objkey, * id of wf event l_event_id LIKE swedumevid-evtid, * status record for case of error l_status_record TYPE tidoc_status_record_ext, * flag indicating whether subscribed task is started synchronously l_start_recfb_synchron LIKE sweflags-syncflag VALUE ' ', * idoc number (needed because of type checking) l_idoc_number LIKE edidc-docnum. * local constants CONSTANTS: * object type 'IDOC' c_object_type LIKE swetypecou-objtype VALUE 'IDOCINVOIC', * name of event to be created c_idc_evt LIKE swetypecou-event VALUE 'INPUTERROROCCURREDMM' . if t_couple_to_process_in[] is initial. COMMIT WORK. CALL FUNCTION 'DEQUEUE_ALL'. CLEAR commit_counter_in. exit. endif. * cast l_start_recfb_synchron = start_recfb_synchron_in. * declaration of container swc_container l_t_ev_container. * initialize container swc_clear_container l_t_ev_container. * dequeue all idocs at the same time LOOP AT t_couple_to_process_in. * cast l_idoc_number = t_couple_to_process_in(16). CALL FUNCTION 'EDI_DOCUMENT_DEQUEUE_LATER' EXPORTING docnum = l_idoc_number EXCEPTIONS OTHERS = 0. ENDLOOP. * get first idoc number in table in order to create an object READ TABLE t_couple_to_process_in INDEX 1. * set object key in variable of correct type (casting) l_object_key = t_couple_to_process_in(16). * create an object, i.e. an IDoc swc_create_object l_object c_object_type l_object_key. * fill container: work item object id (idoc) swc_set_element l_t_ev_container "EC * c_element_wi_obj_id "EC * l_object. "EC * * fill container: NumberPlusEventcode (table of couples) swc_set_table l_t_ev_container c_element_no_plus_info t_couple_to_process_in. * fire event that will trigger the idoc inbound processing CALL FUNCTION 'SWE_EVENT_CREATE' EXPORTING objtype = c_object_type objkey = l_object_key event = c_idc_evt * CREATOR = ' ' * START_WITH_DELAY = ' ' start_recfb_synchron = l_start_recfb_synchron IMPORTING event_id = l_event_id TABLES event_container = l_t_ev_container EXCEPTIONS objtype_not_found = 1 OTHERS = 2. IF ( sy-subrc <> 0 ) * event was not created => error handling for this idoc (EDIM) OR ( l_event_id = 0 ). * stop processing, no commit MESSAGE ID 'E0' TYPE 'A' NUMBER '374' WITH l_status_record-docnum c_idc_evt RAISING event_create_failed. ELSE. * do commit and reset counter * the commit will get the idocs to the database and at the same time * activate the event that was created COMMIT WORK. * dequeue all unprocessed IDocs to avoid log-overflow CALL FUNCTION 'DEQUEUE_ALL'. CLEAR commit_counter_in. * reset table of idocs that need to be processed CLEAR t_couple_to_process_in. REFRESH t_couple_to_process_in. ENDIF. ENDFORM. " ANALYZING_EVENT_CREATE
Related Items:
|