We now add another piece of information to the display of the customer's address from Tutorial 1: we display the customer's balance from accounting, i.e. the sum of the current open items minus any down payments.

As a result, the display of customer data will look like this:

To implement this, we first include two attributes in our ABAP class "customer", namely the amount and the currency of the balance:

   data:
      open_balance_amount   type dmbtr,
      open_balance_currency type waers.

Next, we implement an ABAP method that calculates the balance. For this we use the standard function module "BAPI_AR_ACC_GETOPENITEMS":

 method build_open_balance.

    clear:
    open_balance_amount,
    open_balance_currency.

    data:
      items type table of bapi3007_2.

    call function 'BAPI_AR_ACC_GETOPENITEMS'
      exporting
        customer    = kunnr
        companycode = '1010'
        keydate     = sy-datum
      tables
        lineitems   = items.

    loop at items assigning field-symbol(<item>)

*     add debit/credit 
      if <item>-db_cr_ind = 'S'.
        open_balance_amount = open_balance_amount + <item>-lc_amount.
      else.
        open_balance_amount = open_balance_amount - <item>-lc_amount.
      endif.

* set company currency
      open_balance_currency = <item>-loc_currcy.

    endloop.

  endmethod.

In the HTML file we output the balance:

 <!-- Balance -->
<div class="infoblock">
    <label class='label'>Balance</label>
    <br />
    <span class='output' name='open_balance_amount'></span>
    <span class='output' name='open_balance_currency'></span>
</div>

Except for the call of the method we are now ready. At which point in the ABP coding should we call the method? At first glance, the most obvious thing to do is to call the method as soon as the user presses the "Display" button:, i.e. in our method "display":

* display customer data
  method display.
    if not s10databaseread( ).
      s10errormessage( 'Please enter a valid customer number' ).
    endif.
    
* Calculate accounting balance
    build_open_balance( ).

    s10nextscreen( 'display').

  endmethod.

This is how it can be done and it works. In the development of more complex applications, however, one runs into difficulties if one wants to provide such information derived from the key values at the earliest possible time:

Usually, you start with a small amount of data, but later you have an application in which, for example, 50 pieces of information, including tables and diagrams, are displayed on different screens, where the order is chosen by the user by targeting information via a menu or via individual buttons. There may be additional parameters on some of the screens, such as specifying a time period in our example, so that only items that have been due for some time are included.

Thus, the approach of getting all the information at once at the beginning no longer works. As a workaround, we can change the reading strategy and get the data only when a specific screen such as "Accounting data" is displayed. However, this makes the coding heavily dependent on the structure of the user interface, and changes to the user interface require logic changes in the ABAP class. For example, we may initially display all accounting data on a separate screen, and now there is a requirement to display the balance already on the overview screen. This easily leads to either reading data multiple times, or introducing switches with the meaning "data x already read" to avoid getting the data multiple times. These switches must be managed correctly, for example reset when the customer number or a selection parameter changes.

As a solution, the S10 framework provides a mechanism where data is automatically read only when it is needed in an HTML page, and re-read only when the content of the relevant key fields has changed. A detailed description of this can be found in the "Build methods" tutorial; we show the mechanism here using our balance example. The S10 framework requires the specification of key fields on which the information to be determined depends and the method which must be called for this purpose. Therefore, in the declaration of the method at "importing" those attributes on which the data depends are named, and at "exporting" those that are calculated in the method. In our example it looks like this:
   methods:
      build_open_balance
        importing
          kunnr                 type kna1-kunnr
        exporting
          open_balance_amount   type dmbtr
          open_balance_currency type waers.


We can now simply omit the "build_open_balance()" call: the S10 framework executes the method when one of the exporting attributes is to be displayed in an HTML page. You can now easily move the output of individual attributes from one screen to another and be sure that the associated build method is called in time and only once, as long as the key values do not change. To check the correct recalculation after changing the customer number, we add a "back" button on the "display" screen:

This works exactly like the "Display" button from Tutorial 1:

<button type="button" class="toolbarbutton" onclick="S10Apply('start');">
    Back
</button>

In our ABAP class then still the method "start", which navigates to the screen "start":

* start again with customer number input
  method start.
    s10nextscreen( 'start').
  endmethod.



Now we can change the customer within the application. The build method "build_open_balance" is automatically called again by the S10 framework to display the balance if the customer number has changed:





One could now write a separate build method for each attribute. However, this does not make sense because very often attributes can be obtained together without much additional effort, for example by calling a BAPI or with a database access. Therefore you better combine these attributes in a "build" method and specify all attributes that are calculated together in "exporting".

Tables can also be named in a "build" method under "exporting". As an example, we output a table of all open items of the customer in a separate screen. As a result we want to achieve the following:



 

For the general technique of table output, you can find all the details in the Tables documentation. For our example it looks like this:

In the "display" screen we add another button "Open items":

 <button type="button" class="toolbarbutton" onclick="S10Apply('to_openitems');">
     Open items
</button>

The button executes the ABAP method "to_openitems", with which we branch to the new screen "openitems":
* display open items
  method to_openitems.
    s10nextscreen( 'openitems').
  endmethod.


In our ABAP program we define a class "openitem" which contains the fields of the open accounting items to be displayed, i.e. a section of the BAPI structure:

class openitem definition inheriting from /s10/any.

  public section.

    data:
      doc_no     type bapi3007_2-doc_no, " Document Number
      item_num   type bapi3007_2-item_num, " Line item
      pstng_date type bapi3007_2-pstng_date, " Posting Date
      doc_type   type bapi3007_2-doc_type, " Document type
      lc_amount  type dmbtr, " Amount in LC with 2 decimals
      pmnttrms   type bapi3007_2-pmnttrms, " Payment Terms
      loc_currcy type bapi3007_2-loc_currcy. "Currency

endclass.

You can have this class generated in transaction /s10/util by ticking the required fields from BAPI structure "bapi3007_2".

In class "customer" we create a table "openitems" of objects of class "openitem":
 data:
    openitems  type table of ref to openitem.

We fill the table in the method "build_open_balance", which is now declared as follows:
methods:
      build_open_balance
        importing
          kunnr                 type kna1-kunnr
        exporting
          open_balance_amount   type dmbtr
          open_balance_currency type waers
          openitems             type table.

That is, another exporting parameter has now been added, the table "openitems". Here please note that it is only declared with "type table".

In the implementation of "build_open_balance" we fill the table. Since the BAPI returns the amounts without sign, we have to interpret the debit/credit indicator as sign:

 method build_open_balance.

    clear:
    open_balance_amount,
    open_balance_currency,
    openitems.

    data:
      items type table of bapi3007_2.

    call function 'BAPI_AR_ACC_GETOPENITEMS'
      exporting
        customer    = kunnr
        companycode = '1010'
        keydate     = sy-datum
      tables
        lineitems   = items.

* sort items
    sort items by  doc_no item_num.

    loop at items assigning field-symbol(<item>).

* correct sign
      if <item>-db_cr_ind = 'H'.
        <item>-lc_amount = - <item>-lc_amount.
      endif.

*     add to total amount
      open_balance_amount = open_balance_amount + <item>-lc_amount.

* append to open items table
      data(oi) = new openitem( ).
      oi->s10copy( <item> ).
      append oi to openitems.

* set company currency
      open_balance_currency = <item>-loc_currcy.

    endloop.

  endmethod.


With this the ABAP program is ready and we only need the HTML file for the screen "openitems". If you want to save yourself some typing, you can use transaction /s10/util again, generate a list display for the BAPI structure "bapi3007_2" and then transfer this display to the HTML file "openitems".

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=400">
    <link rel='stylesheet' type='text/css' href='../../../style/s10.style.css'>
    <link rel='stylesheet' type='text/css' href='../../../style/custom.style.css'>
    <script src='../../synactiveS10/synactiveS10.java.js'></script>

    <title>Customer information</title>
</head>
<body style="width: 100%; margin: 0px; padding: 0px;" onload='init();' class="colorscheme9">

    <div class="headerarea" style="width: 100%; padding: 10px;">
        <b>Open items <span class='output' type="text" name='name1'></span></b>
        <br />
        <br />


        <button type="button" class="toolbarbutton" onclick="S10Apply('to_display');">
            Overview
        </button>


        <button type="button" class="toolbarbutton" onclick="S10Logoff();">
            Logoff
        </button>


    </div>


    <!-- column headers -->
    <div class="colheaders">


        <!-- Document number -->
        <div class='colhead colheadup output ' style="width: 90px;" name="doc_no"></div>

        <!-- Item number -->
        <div class='colhead output ' style="width: 36px;" name="item_num"></div>

        <!-- Posting date -->
        <div class='colhead output ' style="width: 80px;" name="pstng_date"></div>

        <!-- Payment terms -->
        <div class='colhead output ' style="width: 48px;" name="pmnttrms"></div>

        <!-- Amount -->
        <div class='colhead output totals' style="width: 200px; --portrait-width: 90px; text-align: right;" name="lc_amount"></div>


        <div class="colhead" style="width: 20px; float: right; margin-right: 4px;" onclick="S10FilterTable(this);">
            <img src="../../../icons/filter.png" style="width: 18px; height: 18px;">
        </div>

    </div>

    <!-- list rows -->
    <form class='table' name='openitems'>

        <div class="tablerow">

            <!-- Document number -->
            <div class='outputcelldiv ' style="width: 90px;" name="doc_no"></div>
            <!-- Item number -->
            <div class='outputcelldiv ' style="width: 36px;" name="item_num"></div>
            <!-- Posting date -->
            <div class='outputcelldiv ' style="width: 80px;" name="pstng_date"></div>
            <!-- Payment terms -->
            <div class='outputcelldiv ' style="width: 48px;" name="pmnttrms"></div>
            <!-- Amount -->
            <div class='outputcelldiv ' style="width: 200px; --portrait-width: 90px; text-align: right;" name="lc_amount"></div>

        </div>

    </form>

    <!-- nothing selected -->
    <div class="tablenocontent" style="display: block;">No items selected</div>



</body>
</html>

To navigate back to the overview, we have defined the "Overview" button here, which calls a small ABAP method, as with the previous navigation buttons:

* display general attributes
  method to_display.
    s10nextscreen( 'display').
  endmethod.


With this, the list display of open items is ready and integrated into our application.

We recommend you work with the mechanism of "build" methods from the very beginning, as this makes complex dialog applications much clearer, and subsequent changes to the user interface much easier and safer.