REPORT {{p}}vineyard_rpt. DATA gv_variety TYPE {{p}}grape-variety. PARAMETERS p_from TYPE d OBLIGATORY. SELECT-OPTIONS s_var FOR gv_variety. CLASS lcl_vineyard DEFINITION FINAL. PUBLIC SECTION. TYPES tt_variety TYPE RANGE OF {{p}}grape-variety. TYPES: BEGIN OF ty_harvest, variety TYPE {{p}}harvest-variety, harvest_date TYPE {{p}}harvest-harvest_date, weight_kg TYPE {{p}}harvest-weight_kg, END OF ty_harvest. TYPES tt_harvest TYPE STANDARD TABLE OF ty_harvest. TYPES: BEGIN OF ty_name, variety TYPE {{p}}grape-variety, name TYPE {{p}}grape-name, END OF ty_name. TYPES tt_name TYPE STANDARD TABLE OF ty_name. TYPES: BEGIN OF ty_line, variety TYPE {{p}}grape-variety, name TYPE {{p}}grape-name, total_kg TYPE {{p}}harvest-weight_kg, harvests TYPE i, END OF ty_line. TYPES tt_line TYPE STANDARD TABLE OF ty_line. METHODS read_harvests IMPORTING iv_from TYPE d it_variety TYPE tt_variety EXPORTING et_harvest TYPE tt_harvest. METHODS read_names IMPORTING it_harvest TYPE tt_harvest EXPORTING et_names TYPE tt_name. METHODS aggregate IMPORTING it_harvest TYPE tt_harvest it_names TYPE tt_name EXPORTING et_lines TYPE tt_line. METHODS display CHANGING ct_lines TYPE tt_line. ENDCLASS. CLASS lcl_vineyard IMPLEMENTATION. METHOD read_harvests. IF it_variety IS INITIAL. SELECT variety harvest_date weight_kg INTO TABLE et_harvest FROM {{p}}harvest WHERE harvest_date >= iv_from. ELSE. SELECT variety harvest_date weight_kg INTO TABLE et_harvest FROM {{p}}harvest WHERE harvest_date >= iv_from AND variety IN it_variety. ENDIF. ENDMETHOD. METHOD read_names. IF it_harvest IS NOT INITIAL. SELECT variety name INTO TABLE et_names FROM {{p}}grape FOR ALL ENTRIES IN it_harvest WHERE variety = it_harvest-variety. ENDIF. ENDMETHOD. METHOD aggregate. DATA ls_harvest TYPE ty_harvest. DATA ls_name TYPE ty_name. DATA ls_line TYPE ty_line. DATA lt_names TYPE tt_name. DATA lt_lines TYPE tt_line. lt_names = it_names. SORT lt_names BY variety. LOOP AT it_harvest INTO ls_harvest. READ TABLE lt_names INTO ls_name WITH KEY variety = ls_harvest-variety BINARY SEARCH. IF sy-subrc = 0. CLEAR ls_line. ls_line-variety = ls_harvest-variety. ls_line-name = ls_name-name. ls_line-total_kg = ls_harvest-weight_kg. ls_line-harvests = 1. COLLECT ls_line INTO lt_lines. ENDIF. ENDLOOP. SORT lt_lines BY total_kg DESCENDING. et_lines = lt_lines. ENDMETHOD. METHOD display. DATA lo_alv TYPE REF TO cl_salv_table. TRY. cl_salv_table=>factory( IMPORTING r_salv_table = lo_alv CHANGING t_table = ct_lines ). lo_alv->display( ). CATCH cx_salv_msg. MESSAGE 'Cannot display the list' TYPE 'I'. ENDTRY. ENDMETHOD. ENDCLASS. START-OF-SELECTION. DATA go_vineyard TYPE REF TO lcl_vineyard. DATA lt_harvest TYPE lcl_vineyard=>tt_harvest. DATA lt_names TYPE lcl_vineyard=>tt_name. DATA lt_lines TYPE lcl_vineyard=>tt_line. CREATE OBJECT go_vineyard. go_vineyard->read_harvests( EXPORTING iv_from = p_from it_variety = s_var[] IMPORTING et_harvest = lt_harvest ). go_vineyard->read_names( EXPORTING it_harvest = lt_harvest IMPORTING et_names = lt_names ). go_vineyard->aggregate( EXPORTING it_harvest = lt_harvest it_names = lt_names IMPORTING et_lines = lt_lines ). go_vineyard->display( CHANGING ct_lines = lt_lines ). CLASS ltc_vineyard DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS. PRIVATE SECTION. METHODS totals_per_variety FOR TESTING. METHODS skips_unknown_variety FOR TESTING. ENDCLASS. CLASS ltc_vineyard IMPLEMENTATION. METHOD totals_per_variety. DATA ls_harvest TYPE lcl_vineyard=>ty_harvest. DATA lt_harvest TYPE lcl_vineyard=>tt_harvest. DATA ls_name TYPE lcl_vineyard=>ty_name. DATA lt_names TYPE lcl_vineyard=>tt_name. DATA lt_lines TYPE lcl_vineyard=>tt_line. DATA ls_line TYPE lcl_vineyard=>ty_line. DATA lv_total TYPE {{p}}harvest-weight_kg. DATA go_vineyard TYPE REF TO lcl_vineyard. ls_harvest-variety = 'A'. ls_harvest-harvest_date = '20260101'. ls_harvest-weight_kg = '10.000'. APPEND ls_harvest TO lt_harvest. CLEAR ls_harvest. ls_harvest-variety = 'A'. ls_harvest-harvest_date = '20260102'. ls_harvest-weight_kg = '5.000'. APPEND ls_harvest TO lt_harvest. CLEAR ls_harvest. ls_harvest-variety = 'B'. ls_harvest-harvest_date = '20260101'. ls_harvest-weight_kg = '2.000'. APPEND ls_harvest TO lt_harvest. ls_name-variety = 'A'. ls_name-name = 'Alpha'. APPEND ls_name TO lt_names. CLEAR ls_name. ls_name-variety = 'B'. ls_name-name = 'Beta'. APPEND ls_name TO lt_names. CREATE OBJECT go_vineyard. go_vineyard->aggregate( EXPORTING it_harvest = lt_harvest it_names = lt_names IMPORTING et_lines = lt_lines ). cl_abap_unit_assert=>assert_equals( exp = 2 act = lines( lt_lines ) ). READ TABLE lt_lines INTO ls_line INDEX 1. cl_abap_unit_assert=>assert_equals( exp = 'B' act = ls_line-variety ). READ TABLE lt_lines INTO ls_line INDEX 2. cl_abap_unit_assert=>assert_equals( exp = 'Alpha' act = ls_line-name ). lv_total = '15.000'. cl_abap_unit_assert=>assert_equals( exp = lv_total act = ls_line-total_kg ). cl_abap_unit_assert=>assert_equals( exp = 2 act = ls_line-harvests ). ENDMETHOD. METHOD skips_unknown_variety. DATA ls_harvest TYPE lcl_vineyard=>ty_harvest. DATA lt_harvest TYPE lcl_vineyard=>tt_harvest. DATA lt_names TYPE lcl_vineyard=>tt_name. DATA lt_lines TYPE lcl_vineyard=>tt_line. DATA go_vineyard TYPE REF TO lcl_vineyard. ls_harvest-variety = 'X'. ls_harvest-harvest_date = '20260101'. ls_harvest-weight_kg = '1.000'. APPEND ls_harvest TO lt_harvest. CREATE OBJECT go_vineyard. go_vineyard->aggregate( EXPORTING it_harvest = lt_harvest it_names = lt_names IMPORTING et_lines = lt_lines ). cl_abap_unit_assert=>assert_equals( exp = 0 act = lines( lt_lines ) ). ENDMETHOD. ENDCLASS.