Skip to content

Latest commit

 

History

History
793 lines (618 loc) · 25.4 KB

README.md

File metadata and controls

793 lines (618 loc) · 25.4 KB

Exercise 3: Create Value Help, Enhance the Behavior Definition and Behavior Implementation of the Shopping Cart Business Object

Create your first order in the shopping cart.

Introduction

Now that you've created your Shopping Cart RAP business object and a UI service on top in exercise 2, you will enhance the RAP BO data model, behavior definition, and behavior implementation in the present exercise.

You will learn

  • How to enhance a behavior definition to add validations, determinations and side effects
  • How to create a value help
  • How to enhance a behavior implementation
  • How to run the SAP Fiori Elements Preview

Reminder:
Don't forget to replace all occurences of the placeholder ### with your assigned group number in the exercise steps below.
You can use the ADT function Replace All (Ctrl+F) for the purpose.
If you don't have a group number, choose a 3-digit suffix and use it for all exercises.


Step 1: Enhance behavior definition to add validations, determinations and side effects

In this step we will add validations, determinations and side effects.

🔵 Click to expand
  1. Open your behavior definition ZR_SHOPCART_### to enhance it. Add the following statements to your behavior definition:

    update (features: instance);    
    

    and

    draft action(features: instance) Edit;   
    
projection
  1. Replace the statement

    draft determine action Prepare;

    in your behavior definition with the following code:

    draft determine action Prepare { validation checkOrderedQuantity;  validation checkDeliveryDate;}
    determination setInitialOrderValues on modify { create; }
    determination calculateTotalPrice on modify { create; field Price, OrderQuantity; } 
    validation checkOrderedQuantity on save { create; field OrderQuantity; }
    validation checkDeliveryDate on save { create; field DeliveryDate; }
    
projection
  1. Add side effects to update the field TotalPrice.

    Add this code-snippet before the mapping statement.

     //  side effects
     side effects
     {
       field Price affects field TotalPrice;
       field OrderQuantity affects field TotalPrice;
     }   
    
  2. Check your behavior definition:

    🟡📄 Click to expand and view or copy the source code!
    
    managed implementation in class ZBP_R_SHOPCART_### unique;  
    strict ( 2 );  
    with draft;  
    
    define behavior for ZR_SHOPCART_### alias ShoppingCart    
    persistent table zshopcart_###
    draft table zshopcart_###_d
    etag master LocalLastChangedAt
    lock master total etag LastChangedAt
    authorization master ( global )
    
    {
      field ( readonly )
      OrderUUID,
      CreatedAt,
      CreatedBy,
      LastChangedAt,
      LastChangedBy,
      LocalLastChangedAt
      ,
      PurchaseRequisition,
      PrCreationDate,
      OverallStatus;
    
    
    
      field ( numbering : managed )
      OrderUUID;
    
    
      create;
      update ( features : instance );
      delete;
    
      draft action ( features : instance ) Edit;
      draft action Activate optimized;
      draft action Discard;
      draft action Resume;
      draft determine action Prepare { validation checkOrderedQuantity; validation checkDeliveryDate; }
      determination setInitialOrderValues on modify { create; }
      determination calculateTotalPrice on modify { create; field Price, OrderQuantity; }
      validation checkOrderedQuantity on save { create; field OrderQuantity; }
      validation checkDeliveryDate on save { create; field DeliveryDate; }
    
      //  side effects
      side effects
      {
        field Price affects field TotalPrice;
        field OrderQuantity affects field TotalPrice;
      }
    
      mapping for zshopcart_###
        {
          OrderUUID           = order_uuid;
          OrderID             = order_id;
          OrderedItem         = ordered_item;
          Price               = price;
          TotalPrice          = total_price;
          Currency            = currency;
          OrderQuantity       = order_quantity;
         DeliveryDate        = delivery_date;
          OverallStatus       = overall_status;
          Notes               = notes;
          CreatedBy           = created_by;
          CreatedAt           = created_at;
          LastChangedBy       = last_changed_by;
          LastChangedAt       = last_changed_at;
          LocalLastChangedAt  = local_last_changed_at;
          PurchaseRequisition = purchase_requisition;
          PrCreationDate      = pr_creation_date;
        }
    }   
    
    
    

    Hint: Please replace ### with your group number .

  1. Save and activate.

Step 2: Activate use of side effects in the behavior projection

In this step will activate the use of side effects so that the field TotalPrice will be updated immediately once the price or the number of ordered items has been changed.

🔵 Click to expand
  1. Open your behavior definition ZC_SHOPCART_### to enhance it. Add the following statements to your behavior projection:

    use side effects;      
    
  2. Check your behavior projection:

    🟡📄 Click to expand and view or copy the source code!
    projection;
    strict ( 2 );
    use draft;
    use side effects;
    
    define behavior for ZC_SHOPCART_### alias ShoppingCart
    use etag
    
    
    
    {
      use create;
      use update;
      use delete;
    
      use action Edit;
      use action Activate;
      use action Discard;
      use action Resume;
      use action Prepare;
    
    }
    
    

Step 3: Create a value help for products

This data definition is needed to create a value help for products.

🔵 Click to expand
  1. Right-click Data Definitions and select New Data Definition.

    projection
  2. Create a new data definition:

    • Name: ZI_Products_###

    • Description: data definition for products

      Click Next >.

      projection
  3. Click Finish.

    projection
  4. In your data definition ZI_Products_### replace your code with following:

🟡📄 Click to expand and view or copy the source code!
 @AbapCatalog.viewEnhancementCategory: [#NONE]
 @AccessControl.authorizationCheck: #NOT_REQUIRED
 @EndUserText.label: 'Value Help for I_PRODUCT'
 @Metadata.ignorePropagatedAnnotations: true
 @ObjectModel.usageType:{
   serviceQuality: #X,
   sizeCategory: #S,
   dataClass: #MIXED
 }
 define view entity ZI_PRODUCTS_###
   as select from I_Product
 {
   key Product                                                 as Product,
       _Text[1: Language=$session.system_language].ProductName as ProductText,
       @Semantics.amount.currencyCode: 'Currency'
       case
         when Product = 'D001' then cast ( 1000.00 as abap.dec(16,2) ) 
         when Product = 'D002' then cast ( 499.00 as abap.dec(16,2) ) 
         when Product = 'D003' then cast ( 799.00 as abap.dec(16,2) ) 
         when Product = 'D004' then cast ( 249.00 as abap.dec(16,2) )
         when Product = 'D005' then cast ( 1500.00 as abap.dec(16,2) ) 
         when Product = 'D006' then cast ( 30.00 as abap.dec(16,2) ) 
         else cast ( 100000.00 as abap.dec(16,2) ) 
       end                                                     as Price,
       
       @UI.hidden: true
       cast ( 'EUR' as abap.cuky( 5 ) )                        as Currency,

       @UI.hidden: true
       ProductGroup                                            as ProductGroup,

       @UI.hidden: true
       BaseUnit                                                as BaseUnit

 }
 where
     Product = 'D001'
   or Product = 'D002'
   or Product = 'D003'
   or Product = 'D004'
   or Product = 'D005'
   or Product = 'D006'
  1. Save and activate.

  2. You can test your CDS view entity by pressing F8 to start the Data Preview.

Step 4: Add value helps in the CDS projection view

You will now adjust the CDS projection view ZC_SHOPCART_### of your Fiori elements app by adding the value help you have just created.

🔵 Click to expand
  1. In the Project Explorer navigate to the CDS projection view ZC_SHOPCART_###.

    product value help
  2. Here add the following code above the fields OrderedItem and Currenccy :

    product value help
      @Consumption.valueHelpDefinition: [{ entity: 
                 {name: 'ZI_PRODUCTS_###' , element: 'Product' },
                 additionalBinding: [{ localElement: 'Price', element: 'Price', usage: #RESULT },
                                     { localElement: 'Currency', element: 'Currency', usage: #RESULT }
                                                                       ]
                 }]  
      OrderedItem,

    and

      @Consumption.valueHelpDefinition: [ { entity: { name: 'I_Currency', element: 'Currency' } } ]  
      Currency,

Step 5: Enhance behavior implementation

Enhance the BO behavior implementation according to the enhancements done in the BO behavior definition.

🔵 Click to expand
  1. Open the behavior implementation ZBP_SHOPCART_###, add the constant c_overall_status to your behavior implementation. In your Local Types, replace your code with following:

    Do not forget to replace all occurences of the placeholder ### with your suffix.

🟡📄 Click to expand and view or copy the source code!
CLASS lhc_shopcart DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
  CONSTANTS:
    BEGIN OF c_overall_status,
      new       TYPE string VALUE 'New / Composing',
      submitted TYPE string VALUE 'Submitted / Approved',
      cancelled TYPE string VALUE 'Cancelled',
    END OF c_overall_status.
  METHODS:
    get_global_authorizations FOR GLOBAL AUTHORIZATION
      IMPORTING
      REQUEST requested_authorizations FOR ShoppingCart
      RESULT result,
    get_instance_features FOR INSTANCE FEATURES
      IMPORTING keys REQUEST requested_features FOR ShoppingCart RESULT result.

  METHODS calculateTotalPrice FOR DETERMINE ON MODIFY
    IMPORTING keys FOR ShoppingCart~calculateTotalPrice.

  METHODS setInitialOrderValues FOR DETERMINE ON MODIFY
    IMPORTING keys FOR ShoppingCart~setInitialOrderValues.

  METHODS checkDeliveryDate FOR VALIDATE ON SAVE
    IMPORTING keys FOR ShoppingCart~checkDeliveryDate.

  METHODS checkOrderedQuantity FOR VALIDATE ON SAVE
    IMPORTING keys FOR ShoppingCart~checkOrderedQuantity.
ENDCLASS.

CLASS lhc_shopcart IMPLEMENTATION.
METHOD get_global_authorizations.
ENDMETHOD.
METHOD get_instance_features.

  " read relevant olineShop instance data
  READ ENTITIES OF zr_shopcart_### IN LOCAL MODE
    ENTITY ShoppingCart
      FIELDS ( OverallStatus )
      WITH CORRESPONDING #( keys )
    RESULT DATA(OnlineOrders)
    FAILED failed.

  " evaluate condition, set operation state, and set result parameter
  " update and checkout shall not be allowed as soon as purchase requisition has been created
  result = VALUE #( FOR OnlineOrder IN OnlineOrders
                    ( %tky                   = OnlineOrder-%tky
                      %features-%update
                        = COND #( WHEN OnlineOrder-OverallStatus = c_overall_status-submitted  THEN if_abap_behv=>fc-o-disabled
                                  WHEN OnlineOrder-OverallStatus = c_overall_status-cancelled THEN if_abap_behv=>fc-o-disabled
                                  ELSE if_abap_behv=>fc-o-enabled   )
                      %action-Edit
                        = COND #( WHEN OnlineOrder-OverallStatus = c_overall_status-submitted THEN if_abap_behv=>fc-o-disabled
                                  WHEN OnlineOrder-OverallStatus = c_overall_status-cancelled THEN if_abap_behv=>fc-o-disabled
                                  ELSE if_abap_behv=>fc-o-enabled   )

                      ) ).
ENDMETHOD.

METHOD calculateTotalPrice.
  DATA total_price TYPE zr_shopcart_###-TotalPrice.

  " read transfered instances
  READ ENTITIES OF zr_shopcart_### IN LOCAL MODE
    ENTITY ShoppingCart
      FIELDS ( OrderID TotalPrice )
      WITH CORRESPONDING #( keys )
    RESULT DATA(OnlineOrders).

  LOOP AT OnlineOrders ASSIGNING FIELD-SYMBOL(<OnlineOrder>).
    " calculate total value
    <OnlineOrder>-TotalPrice = <OnlineOrder>-Price * <OnlineOrder>-OrderQuantity.
  ENDLOOP.

  "update instances
  MODIFY ENTITIES OF zr_shopcart_### IN LOCAL MODE
    ENTITY ShoppingCart
      UPDATE FIELDS ( TotalPrice )
      WITH VALUE #( FOR OnlineOrder IN OnlineOrders (
                        %tky       = OnlineOrder-%tky
                        TotalPrice = <OnlineOrder>-TotalPrice
                      ) ).
ENDMETHOD.

METHOD setInitialOrderValues.

  DATA delivery_date TYPE I_PurchaseReqnItemTP-DeliveryDate.
  DATA(creation_date) = cl_abap_context_info=>get_system_date(  ).
  "set delivery date proposal
  delivery_date = cl_abap_context_info=>get_system_date(  ) + 14.
  "read transfered instances
  READ ENTITIES OF ZR_shopcart_### IN LOCAL MODE
    ENTITY ShoppingCart
      FIELDS ( OrderID OverallStatus  DeliveryDate )
      WITH CORRESPONDING #( keys )
    RESULT DATA(OnlineOrders).

  "delete entries with assigned order ID
  DELETE OnlineOrders WHERE OrderID IS NOT INITIAL.
  CHECK OnlineOrders IS NOT INITIAL.

  " **Dummy logic to determine order IDs**
  " get max order ID from the relevant active and draft table entries
  SELECT MAX( order_id ) FROM zshopcart_### INTO @DATA(max_order_id). "active table
  SELECT SINGLE FROM zshopcart_###_d FIELDS MAX( orderid ) INTO @DATA(max_orderid_draft). "draft table
  IF max_orderid_draft > max_order_id.
    max_order_id = max_orderid_draft.
  ENDIF.

  "set initial values of new instances
  MODIFY ENTITIES OF zr_shopcart_### IN LOCAL MODE
    ENTITY ShoppingCart
      UPDATE FIELDS ( OrderID OverallStatus  DeliveryDate Price  )
      WITH VALUE #( FOR order IN OnlineOrders INDEX INTO i (
                        %tky          = order-%tky
                        OrderID       = max_order_id + i
                        OverallStatus = c_overall_status-new  "'New / Composing'
                        DeliveryDate  = delivery_date
                        CreatedAt     = creation_date
                      ) ).
  .
ENDMETHOD.

METHOD checkDeliveryDate.

*   " read transfered instances
  READ ENTITIES OF zr_shopcart_### IN LOCAL MODE
    ENTITY ShoppingCart
      FIELDS ( DeliveryDate )
      WITH CORRESPONDING #( keys )
    RESULT DATA(OnlineOrders).

  DATA(creation_date) = cl_abap_context_info=>get_system_date(  ).

  "raise msg if delivery date is not ok
  LOOP AT OnlineOrders INTO DATA(online_order).
    APPEND VALUE #(  %tky           = Online_Order-%tky
                     %state_area    = 'VALIDATE_DELIVERYDATE'
                  ) TO reported-ShoppingCart.

    IF online_order-DeliveryDate IS INITIAL OR online_order-DeliveryDate = ' '.
      APPEND VALUE #( %tky = online_order-%tky ) TO failed-ShoppingCart.
      APPEND VALUE #( %tky         = online_order-%tky
                      %state_area   = 'VALIDATE_DELIVERYDATE'
                      %msg          = new_message_with_text(
                              severity = if_abap_behv_message=>severity-error
                              text     = 'Delivery Date cannot be initial' )
                      %element-deliverydate  = if_abap_behv=>mk-on
                    ) TO reported-ShoppingCart.

    ELSEIF  ( ( online_order-DeliveryDate ) - creation_date ) < 14.
      APPEND VALUE #(  %tky = online_order-%tky ) TO failed-ShoppingCart.
      APPEND VALUE #(  %tky          = online_order-%tky
                      %state_area   = 'VALIDATE_DELIVERYDATE'
                      %msg          = new_message_with_text(
                              severity = if_abap_behv_message=>severity-error
                              text     = 'Delivery Date should be atleast 14 days after the creation date'  )
                      %element-deliverydate  = if_abap_behv=>mk-on
                    ) TO reported-ShoppingCart.
    ENDIF.
  ENDLOOP.

ENDMETHOD.

METHOD checkOrderedQuantity.

  "read relevant order instance data
  READ ENTITIES OF zr_shopcart_### IN LOCAL MODE
  ENTITY ShoppingCart
  FIELDS ( OrderID OrderedItem OrderQuantity )
  WITH CORRESPONDING #( keys )
  RESULT DATA(OnlineOrders).

  "raise msg if 0 > qty <= 10
  LOOP AT OnlineOrders INTO DATA(OnlineOrder).
    APPEND VALUE #(  %tky           = OnlineOrder-%tky
                    %state_area    = 'VALIDATE_QUANTITY'
                  ) TO reported-ShoppingCart.

    IF OnlineOrder-OrderQuantity IS INITIAL OR OnlineOrder-OrderQuantity = ' '.
      APPEND VALUE #( %tky = OnlineOrder-%tky ) TO failed-ShoppingCart.
      APPEND VALUE #( %tky          = OnlineOrder-%tky
                      %state_area   = 'VALIDATE_QUANTITY'
                      %msg          = new_message_with_text(
                              severity = if_abap_behv_message=>severity-error
                              text     = 'Quantity cannot be empty' )
                      %element-orderquantity = if_abap_behv=>mk-on
                    ) TO reported-ShoppingCart.

    ELSEIF OnlineOrder-OrderQuantity > 10.
      APPEND VALUE #(  %tky = OnlineOrder-%tky ) TO failed-ShoppingCart.
      APPEND VALUE #(  %tky          = OnlineOrder-%tky
                      %state_area   = 'VALIDATE_QUANTITY'
                      %msg          = new_message_with_text(
                              severity = if_abap_behv_message=>severity-error
                              text     = 'Quantity should be below 10' )

                      %element-orderquantity  = if_abap_behv=>mk-on
                    ) TO reported-ShoppingCart.
    ENDIF.
  ENDLOOP.
ENDMETHOD.
ENDCLASS.

  1. Save and activate.

  2. Go back to your behavior definition ZR_SHOPCARTTP_### and activate it again, if needed.

Step 6: Run SAP Fiori elements app preview and create first order

Test the enhance Shopping Cart app.

🔵 Click to expand
  1. Select ShoppingCart in your service binding and click Preview to open SAP Fiori elements preview.

    preview
  2. Make use of the value help for ordered item and select one. Add also the ordered quantity and click Create.

    preview
  3. Your order is now created and the total price is calculated automatically.

    preview

Summary & Next Exercise

^Top of page

Now that you've...

  • enhanced the data model with a value help,
  • enhanced the behavior definition,
  • enhanced the behavior implementation, and
  • ran the SAP Fiori elements app preview,

you can continue with the next exercise - Exercise 4 - Integrate the Wrapper into the Shopping Cart Business Object.