Creating an operative project structure in SAP project system based on a standard project structure or on another operative structure using BAPIs might be a very difficult task. The reason for that is that before the relevant BAPI for saving the new operative project structure could be called it would be necessary to select from the template project structure every single possible project object and sometimes there might be many. Among possible project objects we could list project definitions, WBS elements, network headers, network activities, network activity elements, milestones, material components, PS texts, relationships, etc.
Luckily for us SAP comes with two function modules that when called in the correct order and together with some other function modules do the complex work with possibly much less lines of code. The functions are “CJWB_PROJECT_COPY” and “CJDT_CREATE_ACT_FOR_NEW_PRJ”.
The first of the function modules is in charge of creating project definitions, WBS elements and other objects related to WBS elements (e.g. PS texts and WBS element milestones). The second function module is in charge of attaching standard network headers and their dependents objects (e.g. network activities, network activity elements, milestones, material components, etc.) to the objects previously generated by function module “CJWB_PROJECT_COPY”.
Among the function modules other than the ones already mentioned that also have to be called in order to successfully accomplish the standard project copy the most important are “CJDW_GET_NEW_NUMBERS” and “CJDT_GET_NEW_NUMBERS”. These function modules are in charge of replacing temporary internal numbers by correct internal numbers that will be updated to the database (e.g. OBJNR numbers).
Below are two sample codes for copying standard project structure. The first is a simple code for cases in which network headers are not necessary while the latter is a slightly more complex code for cases in which network headers are necessary. The second code sample also contains some lines for manipulating WBS element data (project responsible and applicant number) for demonstration purposes.
The sample are based on the calls performed in standard transactions CJ20N and CJ2B (includes LCNPB_MF4T, LCNPB_MF55 and LCJTRF3B).
Sample 1: Simple project structure without network headers
sy-ucomm = 'GEN1'. CALL FUNCTION 'CJWB_PROJECT_COPY' EXPORTING call_from = 'P' standard_wbs_to_be_copied = <-- standard project definition to be copied no_dialog = abap_true replace_string = <-- project definition to be created EXCEPTIONS existing_project = 1 existing_project_in_paging = 2 wrong_call = 3 wbs_for_copy_not_found = 4 error_pspid_generate = 5 no_copy = 6 error = 7 OTHERS = 8. CALL FUNCTION 'CJDW_GET_NEW_NUMBERS'. CALL FUNCTION 'CJDT_GET_NEW_NUMBERS'. SET SCREEN 0. COMMIT WORK.
Sample 2: Project structure with network headers and some data manipulation
REPORT zstdprojcopy. DATA: lt_cjdi TYPE TABLE OF rcj_markl. DATA: ls_cjdi LIKE LINE OF lt_cjdi. DATA: ls_proj LIKE proj. DATA: ls_prps LIKE prps. DATA: l_vsnmr LIKE vskopf-vsnmr. DATA: ls_tc10 LIKE tc10. DATA: ls_tcn41 LIKE tcn41. DATA: l_old_ucomm LIKE sy-ucomm. DATA: l_old_tcode LIKE sy-tcode. DATA: l_start_termin TYPE ps_plfaz. DATA: l_end_termin TYPE ps_plsez. DATA: l_ntw_found TYPE c LENGTH 1. CONSTANTS: c_vorgabe TYPE caufvd-plart VALUE '1'. CONSTANTS: c_aplid TYPE c LENGTH 1 VALUE 'G'. CONSTANTS: c_change TYPE c LENGTH 1 VALUE 'V'. CONSTANTS: c_asterisk TYPE c LENGTH 1 VALUE '*'. CONSTANTS: c_meth_tmex TYPE fcode VALUE 'TMEX'. CONSTANTS: c_vernr TYPE ps_vernr VALUE 99. CONSTANTS: c_astnr TYPE ps_astnr VALUE 99. * Source and Target Project Definitions SELECTION-SCREEN BEGIN OF BLOCK a WITH FRAME. PARAMETERS: p_sproj TYPE projs-pspid OBLIGATORY. PARAMETERS: p_tproj TYPE proj-pspid OBLIGATORY. SELECTION-SCREEN END OF BLOCK a. * Target project start and end dates SELECTION-SCREEN BEGIN OF BLOCK b WITH FRAME. PARAMETERS: p_plfaz TYPE ps_plfaz. PARAMETERS: p_plsez TYPE ps_plsez. SELECTION-SCREEN END OF BLOCK b. START-OF-SELECTION. IF p_plfaz IS INITIAL. l_start_termin = sy-datum. ELSE. l_start_termin = p_plfaz. ENDIF. IF p_plsez IS INITIAL. l_end_termin = sy-datum. ELSE. l_end_termin = p_plsez. ENDIF. * The two lines of code below might look strange at first, but they are necessary because in include FCJWBI00_OK_CODE_PAI somewhere * inside function 'CJWB_PROJECT_COPY' the system checks the sy-ucomm. If it is empty the process is aborted and only the project * definition is created. 'GEN1' is the same ucomm used in the copying process of the project builder (CJ20N) l_old_ucomm = sy-ucomm. sy-ucomm = 'GEN1'. CALL FUNCTION 'CJWB_PROJECT_COPY' EXPORTING call_from = 'P' standard_wbs_to_be_copied = p_sproj start_termin = l_start_termin end_termin = l_end_termin no_dialog = abap_true replace_string = p_tproj IMPORTING project_workarea = ls_proj vsnmr_copy = l_vsnmr EXCEPTIONS existing_project = 1 existing_project_in_paging = 2 wrong_call = 3 wbs_for_copy_not_found = 4 error_pspid_generate = 5 no_copy = 6 error = 7 OTHERS = 8. * Just for demonstration purposes in lines from 79 to 98 the person responsible and the applicant number are changed in the project definition. * Of course this could also be accomplished by substitution rules or BAdIs... ls_proj-vernr = c_vernr. ls_proj-astnr = c_astnr. CALL FUNCTION 'CJDW_PROJ_MODIFY' EXPORTING i_proj = ls_proj EXCEPTIONS beakz = 1 pspnr = 2 error_message = 98 OTHERS = 99. CALL FUNCTION 'CJDW_GET_TREE' EXPORTING levels = 99 x_outline = space TABLES elements = lt_cjdi EXCEPTIONS not_found = 1 OTHERS = 2. * Also for demonstration purposes in lines from 102 to 126 the person responsible and the applicant number are changed in each WBS element of the structure. * This could also be accomplished by substitution rules or BAdIs... LOOP AT lt_cjdi INTO ls_cjdi. CLEAR ls_prps. CALL FUNCTION 'CJDW_PRPS_GET' EXPORTING index = ls_cjdi-index IMPORTING e_prps = ls_prps EXCEPTIONS cancel = 1 not_found = 2 OTHERS = 3. IF sy-subrc = 0. ls_prps-vernr = c_vernr. ls_prps-astnr = c_astnr. CALL FUNCTION 'CJDW_PRPS_MODIFY' EXPORTING beakz = c_change index = ls_cjdi-index i_prps = ls_prps EXCEPTIONS not_found = 1 posnr = 2 OTHERS = 3. ENDIF. ENDLOOP. * Prepare call of 'CJDT_CREATE_ACT_FOR_NEW_PRJ' CALL FUNCTION 'CO_TA_TCN41_READ' EXPORTING plnaw = 'N' profidnetz = ls_proj-vprof IMPORTING tcn41_exp = ls_tcn41 EXCEPTIONS not_found = 01. * The two lines of code below might also look strange at first, but they are also necessary because in includes LCJTRFJ8 and LCJTRFI2 * somewhere inside function 'CJTR_CALL_FROM_EXTERN' the system selects some default values based on transaction code. l_old_tcode = sy-tcode. sy-tcode = 'CJ20N'. CALL FUNCTION 'CJTR_CALL_FROM_EXTERN' EXPORTING aplid = c_aplid fcode_imp = space proj_imp = ls_proj trtyp_imp = c_change top_imp = 1 TABLES cjdi_imp = lt_cjdi EXCEPTIONS no_existing_psp = 1 no_pprofil = 2 OTHERS = 3. SELECT SINGLE * INTO ls_tc10 FROM tc10 WHERE tcode = 'CJ2D'. * Again a strange but necessary line of code. In include LCOKOF1S somewhere inside function 'CJDT_CREATE_ACT_FOR_NEW_PRJ' the system * selects the default value for the order category from table t490 based on the transaction code. It would also be a possibility to * create a new entry in the aforementioned table with the transaction code in context (i.e. tcode of the current program) sy-tcode = 'CJ20N'. * Function for adding network objects to the previously created project structure CALL FUNCTION 'CJDT_CREATE_ACT_FOR_NEW_PRJ' EXPORTING tc10wa = ls_tc10 tcn41_imp = ls_tcn41 proj_imp = ls_proj vsnmr_copy = l_vsnmr sched_param = space flg_new_prj = abap_true EXCEPTIONS no_entries = 1 OTHERS = 2. IF sy-subrc = 0. l_ntw_found = abap_true. ENDIF. CALL FUNCTION 'CNEV_05_COPY_EVOP' EXPORTING i_kokrs = ls_proj-vkokr. CALL FUNCTION 'CO_BT_PROJKN_DET' EXPORTING projn_pa = space projn_tv = space. CALL FUNCTION 'NW_EX_SET_NETSTUFE_MAX_PROJECT' EXPORTING i_profidproj = ls_proj-profl EXCEPTIONS project_profile_does_not_exist = 1 network_profile_does_not_exist = 2 OTHERS = 3. * Check if any required field is still empty. This function module is optional and could result in disruptive pop-ups CALL FUNCTION 'CJWB_CHECK_BEFORE_COMMIT' EXCEPTIONS cancel = 1. * Call network scheduling if network exists IF l_ntw_found = abap_true. CALL FUNCTION 'CJWB_PROJECT_INIT_EXTERN_CALL' EXPORTING i_method = c_meth_tmex i_object = c_asterisk i_view_object = c_asterisk i_sub_view = space i_aktyp = c_change i_pronr = ls_proj-pspnr EXCEPTIONS not_found = 1 OTHERS = 2. ENDIF. * Prepare commit of WBS element dates table (PRTE) CALL FUNCTION 'CJTR_POST_DATES' EXCEPTIONS sched_wrong = 1 check_top_down = 2 OTHERS = 3. * Prepare commit of network data if network exists IF l_ntw_found = abap_true. CALL FUNCTION 'CO_BT_PROJKN_DET' EXPORTING projn_pa = c_vorgabe projn_tv = space. CALL FUNCTION 'CO_ZV_ORDER_POST' EXPORTING commit_flag = abap_false ext_flg = abap_true trans_typ = c_change no_dialog = abap_true EXCEPTIONS update_reject = 1 budget_reject = 2 OTHERS = 3. ENDIF. * Substitute internal numbers CALL FUNCTION 'CJDW_GET_NEW_NUMBERS'. CALL FUNCTION 'CJDT_GET_NEW_NUMBERS'. COMMIT WORK. sy-tcode = l_old_tcode. sy-ucomm = l_old_ucomm. * Set screen 0. The function 'CJWB_PROJECT_COPY' sets screen 0200 and if this is not overwritten here a dump may occurr (screen not found) SET SCREEN 0. CALL FUNCTION 'LOCATION_CORRECT' EXPORTING bild = space bildgruppe = space kopfgruppe = space positionsgruppe = space programm = space stackstufe = 0 trtyp = space. END-OF-SELECTION.