Skip to Content
Technical Articles

TM 3.0 – Concept of Plan extension and LAG

Plan Extension:

Context:

In a typical CPG company, there are thousands of Trade Promotions/Trade Events are created & executed throughout the year. It’s quite a tedious job for the users to create these events manually. In order to manage time and effort effectively, a mass copy functionality is needed. SAP standard does provide this functionality via some configurations, but there would be some custom build scenarios which will not be copied. For example, new custom status profiles with special statuses were set up for our client which are not being copied using standard Mass copy job. To achieve the functionality of mass copy of the promotions which in statuses – Planned, Approved, Performed, Stopped & closed while extending the CBP Plans there needs to be custom enhancement along with the required system configuration.

In TMA3.0 & above – the CBP Plan can be extended either in the Calendar or the P&L view.

From Calendar

 

From P&L

From the RA (Responsibility Area)

So once you try to extend ~ it would give a pop-up for the promotions of statuses which you would like to copy => here we would configure for Planned, Approved, Stopped, Closed etc. (based on the status profile of the Promotions)

Dependency:

Promotions are dependent on the responsibility area assigned to the user (& CBP Plan as well for the RAs assigned to a CBP Plan. And all the copied promotions would copy the copying promotion exactly (along with spends, Driver values, products, etc.) ~ only the date of the copied promo.

Also, make sure that the fund plan & funds are created for the year for which the CBP plan needs to be extended.

Impact:

Many of the attributes like – Planning Customer, Sales Org, Trade Spends, Dates, etc. are copied from the source promotion to the copied promotion via standard SAP delivered functionality.

Apart from that, we need to make sure that the Trade Spend Values in the Planning Layout (from BW IP) are also copied across to the new promotion. After that user would make the necessary changes before finalizing the promotion & approving for execution. With the mass copy of the promotions (based on the selection as per the configuration setting), The planned/approved/stopped/performed/closed promotions would be copied into the extended year retaining the dame dates of the previous year and the status would be put in Draft. So that if any changes required can be put in.

Design:

  • Plan extension can be done from calendar view or P&L view or from RA.
  • Pop up with promotions statuses and types of promotions will be displayed.
  • Based on the options selected by the user, the promotions get copied to the extended view.
  • All the promotions copied to the new year will be in draft status.
  • If no promotions are found, the only plan gets extended.

The TPM Custom Status Profile snapshot

 Given below is a BADI/Enhancement Spots which may be used to achieve the functionality

Enhancement Spot /JBPC/EH_PLAN
BADI /JBPC/EH_EXTEND_PLAN

There is a standard SAP implementation given which can be used or referenced to achieve our need here.

Pseudocode:

  1. Get the attributes of the plan.
* HSY BADI Implementation for CBP Plan Extension

  METHOD /jbpc/if_eh_extend_plan~extend_plan.

    DATA ls_planattr        TYPE crms_mktpl_ol_attributes.
    DATA lr_mktproject_plan TYPE REF TO cl_crm_mktpl_ol_mktproject.
    DATA lv_wait_time       TYPE /jbpc/wait_sec.
    DATA lv_status          TYPE abap_bool .
    DATA lv_plan_guid       TYPE cgpl_guid16.
    DATA lt_guid            TYPE crmt_mktgs_guid.
    DATA lt_sel_options     TYPE crmt_mktib_value.
    DATA lv_scn_guid        TYPE cgpl_guid16 .
    DATA lv_scnplangroup    TYPE cgpl_sem_plgrp.
    DATA lv_plan_year       TYPE /jbpc/bp_year.
    DATA lv_scen_id         TYPE crm_imp_object_id .
    DATA lr_applmanager     TYPE REF TO cl_crm_mktgs_application_mgr.
    DATA lv_scen_guid       TYPE sysuuid_x.
    DATA lr_scenarios       TYPE REF TO /jbpc/cl_crm_mktpl_ol_scns.
    DATA lr_scenario        TYPE REF TO /jbpc/cl_crm_mktpl_ol_scn.
    DATA lr_message_handler TYPE REF TO cl_crm_mktgs_msg_handler.
    DATA lv_msgtext         TYPE string.


    lt_sel_options  = ir_parameters->get_parameter_by_name( 'SEL_OPTION' )->get_values( ).
    lv_scn_guid     = ir_parameters->get_parameter_by_name('SCN_GUID')->get_value( ).
    lv_scnplangroup = ir_parameters->get_parameter_by_name('PLANGROUP')->get_value( ).
    lv_plan_year    = ir_parameters->get_parameter_by_name( 'SYNCH_YEAR' )->get_value( ).


    TRY.
        lr_mktproject_plan ?= get_marketing_project( ir_plan =  ir_item ).
      CATCH cx_crm_mktib_application_impl.
    ENDTRY.

    lr_mktproject_plan->get_attributes( IMPORTING es_attributes = ls_planattr ).

*     release lock for scenario
    lv_scen_guid = /jbpc/cl_crm_jbp_common_api=>get_scenario_for_plan( iv_plan_guid = ls_planattr-guid ).
    CALL FUNCTION 'CONVERSION_EXIT_CGPLP_OUTPUT'
      EXPORTING
        input  = lv_scen_guid
      IMPORTING
        output = lv_scen_id.

    lr_applmanager     = lr_mktproject_plan->get_application_manager( ).
    lr_message_handler = lr_applmanager->get_message_handler( ).
    lr_scenarios ?= lr_applmanager->get_collection_for_type( iv_object_type =  /jbpc/cl_crm_mktjbp_constants=>mkt_objtype_scenario ).

    APPEND lv_scen_guid TO lt_guid.
    lr_scenarios->load( lt_guid ).
    lr_scenario ?= lr_scenarios->get_item_by_guid( iv_guid =  lv_scen_guid ).
    /jbpc/cl_extend_plan_api=>read_wait_time(
      EXPORTING
        iv_sales_org   = ls_planattr-sales_org  " Sales Organization ID
        iv_dis_channel = ls_planattr-dis_channel  " Distribution Channel
        iv_division    = ls_planattr-division  " Division
      RECEIVING
        rv_wait_time   = lv_wait_time ). " Extend Plan Wait Time


      CALL FUNCTION 'ZFM_JBPC_CBP_EXTEND_PLAN' STARTING NEW TASK 'Extend_Plan' CALLING processing_check ON END OF TASK
        EXPORTING
          it_sel_options   = lt_sel_options
          iv_plan_guid     = ls_planattr-guid
          iv_scenario_guid = lv_scn_guid
          iv_plangroup     = lv_scnplangroup
          iv_plan_year     = lv_plan_year.

*      CALL FUNCTION '/JBPC/CBP_EXTEND_PLAN' STARTING NEW TASK 'Extend_Plan' CALLING processing_check ON END OF TASK
*        EXPORTING
*          it_sel_options   = lt_sel_options
*          iv_plan_guid     = ls_planattr-guid
*          iv_scenario_guid = lv_scn_guid
*          iv_plangroup     = lv_scnplangroup
*          iv_plan_year     = lv_plan_year.

    WAIT UNTIL sv_process_status = abap_true UP TO lv_wait_time SECONDS.
*     provide a message that plan is being extended.
    IF sv_process_status = abap_false .
      MESSAGE i451(/jbpc/vvf_impl_msg) INTO lv_msgtext.
      lr_message_handler->add_message_symsg( iv_log_type = cl_crm_mktgs_msg_handler=>co_log_function ).
    ENDIF.


  ENDMETHOD.

2. Call FM by passing ZFM

  •  Get the plan instance.
  •  Get the scenario of the plan
  •  Call the global class method zcl_jbpc_cbp_extend_plan->extend_plan.
FUNCTION zfm_jbpc_cbp_extend_plan.

  DATA lt_plan_promo      TYPE crmt_mktgs_guid.
  DATA lt_promotions_link TYPE /jbpc/tmktpl_tpm_link.
  DATA ls_sel_options     TYPE crmt_gen_value .
  DATA lr_parameter       TYPE REF TO cl_crm_mktib_action_parameter.
  DATA lt_sel_options     TYPE crmt_mktib_value.
  DATA lr_plan            TYPE REF TO cl_crm_mktpl_ol_mktproject.
  DATA lv_guid            TYPE cgpl_guid16.
  DATA lv_scen_guid       TYPE sysuuid_x.
  DATA lr_scenarios       TYPE REF TO /jbpc/cl_crm_mktpl_ol_scns.
  DATA lr_scenario        TYPE REF TO /jbpc/cl_crm_mktpl_ol_scn.
  DATA lv_scen_id         TYPE crm_imp_object_id .
  DATA lr_application_mgr TYPE REF TO cl_crm_mktpl_application_mgr.
  DATA lr_plan_coll       TYPE REF TO cl_crm_mktpl_ol_collection.
  DATA lt_guid            TYPE crmt_mktgs_guid.
  DATA ls_attributes      TYPE /jbpc/s_mktpl_ib_pln_attr.
  DATA lr_psm_asg_coll    TYPE REF TO cl_crm_mktgs_asg_collection.
  DATA lr_psm_item        TYPE REF TO /jbpc/cl_crm_mktpl_scn_psm_itm.

* load plan instance.
  lr_application_mgr ?= cl_crm_mktpl_application_mgr=>get_instance( ).
  lr_plan_coll ?= lr_application_mgr->get_collection_for_type( iv_object_type = /jbpc/cl_crm_mktjbp_constants=>mkt_objtype_plan ).


  APPEND iv_plan_guid TO lt_guid.
  lr_plan_coll->load( lt_guid ).
  lr_plan ?= lr_plan_coll->get_item_by_guid( iv_guid =  iv_plan_guid ).
  lr_plan->set_edit_mode( ).
  lr_plan->get_attributes(  IMPORTING       es_attributes =  ls_attributes  ).
* *Get the scenario guid for the plan
  lv_scen_guid = /jbpc/cl_crm_jbp_common_api=>get_scenario_for_plan( iv_plan_guid = ls_attributes-guid ).

*     set sync date since the buffer is initial in a new session .
  /jbpc/cl_extend_plan_api=>set_sync_date(
    EXPORTING
      iv_sync_year = iv_plan_year   " Planning Year
      iv_sales_org = ls_attributes-sales_org   " Sales Organization ID
      iv_node_guid = ls_attributes-node_guid    " GUID of Hierarchy Node
      iv_ra_guid   = ls_attributes-ra_guid ).   " Responsibility Area GUID

* load scenario reference
* lr_applmanager = lr_mktproject->get_application_manager( ).
  lr_scenarios ?= lr_application_mgr->get_collection_for_type( iv_object_type =  /jbpc/cl_crm_mktjbp_constants=>mkt_objtype_scenario ).
  APPEND lv_scen_guid TO lt_guid.
  lr_scenarios->load( lt_guid ).
  lv_guid = lv_scen_guid.
  lr_scenario ?= lr_scenarios->get_item_by_guid( iv_guid =  lv_guid   ).

  lr_scenario->set_edit_mode( ).

* * syn scenario
  lr_psm_asg_coll = lr_scenario->get_assignment_collection( iv_assignment_type = cl_crm_mktpl_constants=>asg_type_planning_sync_mgr ).
  IF lr_psm_asg_coll IS NOT BOUND.
    RETURN.
  ENDIF.
* Get the planning synchronization item
  lr_psm_item ?= lr_psm_asg_coll->get_item_by_index( iv_index = 1 ).
*
* Call the Object Planning Synchronization Manager.
  IF lr_psm_item IS BOUND .
*   Synchronize BW data
    TRY.
        lr_psm_item->synchronize( i_force_change  = abap_true
          iv_asynchronous = abap_false ).
      CATCH cx_crm_mktpl_imp_synchronize.
        RETURN.
    ENDTRY.
  ENDIF.

  lt_sel_options = it_sel_options .
  SORT lt_sel_options DESCENDING. " BW require the execution of planning event in a specific sequence.

  DATA: lr_obj TYPE REF TO zcl_jbpc_cbp_extend_plan.
  CREATE OBJECT lr_obj.

*-- Copy promotions based on status.
  IF lt_sel_options IS NOT INITIAL.

    lr_obj->extend_plan( ir_plan         = lr_plan
                         it_sel_options  = it_sel_options
                         iv_plan_year    = iv_plan_year
                         iv_plan_guid    = iv_plan_guid ).

  ENDIF.

  lr_application_mgr->save_and_commit( ).

  rv_result =  abap_true .

ENDFUNCTION.
  METHOD extend_plan.

    DATA: lt_promotion_tab TYPE crmt_mktgs_guid.

    IF ir_plan IS BOUND.
*-- Get Promotions from plan to extend
      get_promotions( EXPORTING ir_plan          = ir_plan
                                it_sel_options   = it_sel_options
                                iv_plan_year     = iv_plan_year
                      RECEIVING rt_promotion_tab = lt_promotion_tab ).

*-- delete promotions by status.
      delete_promo_by_status( EXPORTING it_sel_options   = it_sel_options
                              CHANGING  ct_promotion_tab = lt_promotion_tab ).


*-- Copy Promotions
      copy_promotions( EXPORTING it_promotion_tab = lt_promotion_tab
                                 iv_plan_guid     = iv_plan_guid
                                 ir_plan          = ir_plan ).


    ENDIF.
  ENDMETHOD.

D. Get_Promotions method is called.

  • Get the relevant campaign types
  • Delete entries from the table based on promo types values selected
  • If the value is CPY2, ALL – All promotions to be copied except canceled
  • If the value is CPY2, EDL – Only EDLP & EDLC promos are selected
  • If the value is CPY2, HIL – Only EDLP, EDLC, HILO promos are selected
  • If the value is CPY2, OTH – Only Miscellaneous and Corporate promotions are selected
  • Get all the promotions based on the campaign type selected for the plan year to the plan selected.

E. Delete_promo_by_status method is called by passing the promotions.

  • Get the status of the promotions.
  • Read the value selected from pop up
  • If the value is CPY1, ALL – All status promos are selected except the rejected status
  • If the value is CPY1, APR – Approved, Performed, Stopped and Closed status are selected
  • If the value is CPY1,DRF – Copy only Draft and Planned status

F. COPY_PROMOTIONS method is called by passing the promotions & Plan id.

  • Copy promotions by calling method zhsy_extend_plan_api=>copy_promotions
  • Unlock the plan using FM DEQUEUE_ENQ_CGPL_PROJECT
  • Link the promotions to calendar by using /jbpc/cl_extend_plan_api=>link_promotions.

G. Save and commit.

 

Concept of Lag:

Context:

 In SAP TM, two sets of date ranges are provided: In-store dates and shipment dates. These are used across promotion planning and Customer Business Planning (CBP) for various processes such as
defaulting the dates on the promotion, moving consumption volume to shipment volume in promotion, moving the base consumption to shipment in CBP, etc.

SAP does provide Account defaults to be maintained in the system but these are defined per customer and do not allow for any product characteristic (e.g. season) to be part of the date default. These are defined by promotion type and duration which does not meet the business needs as the default of the date agnostic of promotions. Furthermore, these will not allow shifting of volume from consumption to shipment as these are promotion specific defaults.

The purpose of the LAG requirement is to provide an ability to the NA Controller Accounting Team to maintain the date defaults by season for a customer with an ability to upload the Lag rules. This specification will also consider the requirement to default the Shipment dates from the Instore dates on the promotion planning screen.

Design:

Custom Table Creation: Create a new Custom Table Z_CBP_LAG (with maintenance view) with the following fields. This would be primary table for the creation of Responsibility Areas in the CRM system.

CLNT Customer Season Lag Days Year Type Wholesaler Created By Created On Changed By Changed On
<System Client> <CRM Customer Hierarchy Node ID>

 

 

<Season attribute>

 

 

<Multiple of 7>

 

 

<Year>

 

 

<Regular/ Wholesaler/Promo>

<CRM Customer Hierarchy Node ID>

 

 

<User ID>

 

 

<Date>

 

 

<User ID>

 

 

<Date>

<Mandatory> <Mandatory> <Mandatory> <Mandatory> <Mandatory> <Mandatory> <Optional> <Mandatory> <Mandatory> <Mandatory> <Mandatory>

 

The business rule to fill this table is as follows:

  • For a customer which is primarily a direct ship customer e.g. Publix, Costco, the table will contain the entries for the customer = Publix along with season, lag days, year, type = Regular and Wholesaler will be Blank
  • For a customer which is an Indirect e.g. Walmart where the movement happens between Walmart and McLane the table will contain two entries.

Entry1: Customer= Walmart along with season, lag days, year, type = Regular, Wholesaler =<No Value>. This signifies within the Walmart Plan the expected date when Walmart will receive the goods from McLane

Entry2: Walmart along with season, lag days, year, and type = Wholesaler, Wholesaler= McLane. This signifies when Hershey is going to ship the product to McLane.

  • For Customers where there is no consumption to shipment lag to be maintained and only default on promotion is required then the entry will be done with Type = Promo. This case may happen for McLane if in future there is a promotion required to be created.
  • No Customer can have the type= Regular and Promo at the same time.

 Default dates on promotion:

A User can create a promotion from two places. One when the user is in the CBP Plan. Two when the user is in the Promotion search screen and in a particular Responsibility Area. In either of these two cases when a user lands on the new promotion page the following should default
a) Customer
b) Responsibility Area
c) Season code from the responsibility Area.

The Instore dates can be manually populated or come from the selection in CBP screen

The following logic needs to be used for defaulting the Lag days:

  • Based on the Customer Node, Season and Year (derived from Instore Start date) the Lag table Z_CBP_LAG must be read to find the Lag Days. By Default, the system needs to read the Lag type = Regular. If no rule is found then the Lag type = Promo must be read.

The Shipment Start and End Dates must be defaulted by the Lag days.

Shipment Start date = Instore Start Date – Lag days

Shipment End Date = Instore End Date – Lag days

  • If no Lag type rule was defined then the Lag days must be treated as 0. This will cause the Shipment Start Date = Instore Start Date

Shipment end Date = Instore End Date

  • If a user goes in and changes the Instore date (start or end date) the shipment dates should be recalculated.
  • If a user makes a change to the Shipment dates (start or end) manually then in those cases a flag needs to be set on the promotion to indicate that the lag days are different from standard. Once this has been set even a reset of consumption dates by the user should not trigger the shipment date recalculation.

Given below is a BADI/Enhancement Spots which may be used to achieve the functionality

Enhancement Spot: CRM_MKTPL

  1. Badi Definition: CRM_MKTPL_OL_ASG

Methods: IF_EX_CRM_MKTPL_OL_ASG~CHECK_ATTRIBUTES,

IF_EX_CRM_MKTPL_OL_ASG~SET_ATTRIBUTES_BEFORE

  1. Badi Definition: CRM_MKTPL_OL_OBJ

Methods: IF_EX_CRM_MKTPL_OL_OBJ~CHECK_BEFORE_SAVE

Pseudocode:

Default dates on promotion

When a new promotion is created, default the buying dates based on plan dates

1.Enhancement spot: CRM_MKTPL

Badi: CRM_MKTPL_OL_ASG

2.Filter values

DATERANGE = ASSIGNMENT_TYPE and

TPM               = OBJECT_TYPE.

3. Method IF_EX_CRM_MKTPL_OL_ASG~CHECK_ATTRIBUTES,        IF_EX_CRM_MKTPL_OL_ASG~SET_ATTRIBUTES_BEFORE are implemented to default the dates on promotion.

4. Get date values by using class cl_crm_mktpl_appl_base and method date_assign_read by passing the GUID.

5. Get header data using method get_header_assignment_item( ) from importing parameter ir_mktproject.

6. Pass the header ra_guid_ext to table /jbpc/mcrm_raatt to get the season.

7. Pass the customer, season, year and lag type to table zhsy_t_cbp_lag to get the lag days.

8. If the entry exists, then buying dates = plan dates – lag days.

9. If there is no entry in the table. Then set lag days as zero and set buying dates = plan dates.

10. Finally set the buying dates.

 

Set the flag before save

  1. Enhancement spot: CRM_MKTPL

BAdI; CRM_MKTPL_OL_OBJ

  1. Filter values:

TPM = OBJECT_TYPE

  1. Method IF_EX_CRM_MKTPL_OL_OBJ~CHECK_BEFORE_SAVE is implemented to set the flag.
  2. Check the plan dates and buying dates are not equal to lag days then set the flag and save promotion.
  3. If buying start date is less than the current date, then through an error message “buying start date cannot be less than the current date” and don’t save the promotion.

Conclusion:

As highlighted in the below screenshot, the dates are displayed using the log concept. default customer, season and Responsibility area are also displayed in the Trade Promotion.

Be the first to leave a comment
You must be Logged on to comment or reply to a post.