REPORT {{p}}ward_stay. TYPES ty_ward TYPE {{p}}admit-ward. DATA gv_ward TYPE ty_ward. PARAMETERS p_from TYPE d OBLIGATORY. PARAMETERS p_to TYPE d OBLIGATORY. SELECT-OPTIONS s_ward FOR gv_ward. CLASS lcl_report DEFINITION FINAL. PUBLIC SECTION. TYPES: BEGIN OF ty_admit, adm_id TYPE {{p}}admit-adm_id, ward TYPE {{p}}admit-ward, admit_date TYPE {{p}}admit-admit_date, discharge_date TYPE {{p}}admit-discharge_date, daily_rate TYPE {{p}}admit-daily_rate, END OF ty_admit, tt_admit TYPE STANDARD TABLE OF ty_admit WITH EMPTY KEY, BEGIN OF ty_line, ward TYPE {{p}}admit-ward, admissions TYPE i, bed_days TYPE i, total_cost TYPE {{p}}admit-daily_rate, END OF ty_line, tt_line TYPE STANDARD TABLE OF ty_line WITH EMPTY KEY, tt_ward TYPE RANGE OF {{p}}admit-ward. METHODS select_stays IMPORTING iv_from TYPE d iv_to TYPE d it_ward TYPE tt_ward RETURNING VALUE(rt_lines) TYPE tt_line. METHODS aggregate IMPORTING it_admit TYPE tt_admit iv_to TYPE d RETURNING VALUE(rt_lines) TYPE tt_line. METHODS display CHANGING ct_lines TYPE tt_line. PRIVATE SECTION. METHODS add_admission IMPORTING is_admit TYPE ty_admit iv_to TYPE d CHANGING ct_lines TYPE tt_line. ENDCLASS. CLASS lcl_report IMPLEMENTATION. METHOD select_stays. DATA lt_admit TYPE tt_admit. SELECT adm_id, ward, admit_date, discharge_date, daily_rate FROM {{p}}admit WHERE admit_date >= @iv_from AND admit_date > @iv_to AND ward IN @it_ward INTO TABLE @lt_admit. rt_lines = aggregate( it_admit = lt_admit iv_to = iv_to ). ENDMETHOD. METHOD aggregate. DATA ls_admit TYPE ty_admit. LOOP AT it_admit INTO ls_admit. add_admission( EXPORTING is_admit = ls_admit iv_to = iv_to CHANGING ct_lines = rt_lines ). ENDLOOP. SORT rt_lines BY total_cost DESCENDING. ENDMETHOD. METHOD add_admission. DATA lv_discharge TYPE d. DATA lv_days TYPE i. DATA lv_cost TYPE {{p}}admit-daily_rate. DATA lv_index TYPE i. DATA ls_line TYPE ty_line. lv_discharge = is_admit-discharge_date. IF lv_discharge IS INITIAL. lv_discharge = iv_to. ENDIF. lv_days = lv_discharge - is_admit-admit_date. lv_cost = lv_days * is_admit-daily_rate. READ TABLE ct_lines INTO ls_line WITH KEY ward = is_admit-ward. IF sy-subrc = 0. lv_index = sy-tabix. ELSE. CLEAR ls_line. ls_line-ward = is_admit-ward. APPEND ls_line TO ct_lines. lv_index = lines( ct_lines ). ENDIF. ls_line-admissions = ls_line-admissions + 1. ls_line-bed_days = ls_line-bed_days + lv_days. ls_line-total_cost = ls_line-total_cost + lv_cost. MODIFY ct_lines INDEX lv_index FROM ls_line. ENDMETHOD. METHOD display. DATA lo_alv TYPE REF TO cl_salv_table. DATA lx_error TYPE REF TO cx_salv_msg. TRY. cl_salv_table=>factory( IMPORTING r_salv_table = lo_alv CHANGING t_table = ct_lines ). lo_alv->display( ). CATCH cx_salv_msg INTO lx_error. MESSAGE lx_error TYPE 'I' DISPLAY LIKE 'E'. ENDTRY. ENDMETHOD. ENDCLASS. START-OF-SELECTION. DATA go_report TYPE REF TO lcl_report. DATA gt_lines TYPE lcl_report=>tt_line. go_report = NEW lcl_report( ). gt_lines = go_report->select_stays( iv_from = p_from iv_to = p_to it_ward = s_ward[] ). go_report->display( CHANGING ct_lines = gt_lines ). CLASS ltc_report DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS. PRIVATE SECTION. METHODS open_stay_uses_p_to FOR TESTING. METHODS totals_per_ward FOR TESTING. METHODS sorted_by_cost FOR TESTING. ENDCLASS. CLASS ltc_report IMPLEMENTATION. METHOD open_stay_uses_p_to. DATA lt_admit TYPE lcl_report=>tt_admit. DATA lt_lines TYPE lcl_report=>tt_line. DATA ls_line TYPE lcl_report=>ty_line. lt_admit = VALUE #( ( adm_id = 1 ward = 'A' admit_date = '20260101' discharge_date = '00000000' daily_rate = '10.00' ) ). lt_lines = NEW lcl_report( )->aggregate( it_admit = lt_admit iv_to = '20260105' ). READ TABLE lt_lines INTO ls_line INDEX 1. cl_abap_unit_assert=>assert_equals( exp = 4 act = ls_line-bed_days ). cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}admit-daily_rate( 40 ) act = ls_line-total_cost ). ENDMETHOD. METHOD totals_per_ward. DATA lt_admit TYPE lcl_report=>tt_admit. DATA lt_lines TYPE lcl_report=>tt_line. DATA ls_line TYPE lcl_report=>ty_line. lt_admit = VALUE #( ( adm_id = 1 ward = 'A' admit_date = '20260101' discharge_date = '20260103' daily_rate = '10.00' ) ( adm_id = 2 ward = 'A' admit_date = '20260105' discharge_date = '20260106' daily_rate = '10.00' ) ( adm_id = 3 ward = 'B' admit_date = '20260101' discharge_date = '20260111' daily_rate = '5.00' ) ). lt_lines = NEW lcl_report( )->aggregate( it_admit = lt_admit iv_to = '20260131' ). cl_abap_unit_assert=>assert_equals( exp = 2 act = lines( lt_lines ) ). READ TABLE lt_lines INTO ls_line WITH KEY ward = 'A'. cl_abap_unit_assert=>assert_equals( exp = 2 act = ls_line-admissions ). cl_abap_unit_assert=>assert_equals( exp = 3 act = ls_line-bed_days ). ENDMETHOD. METHOD sorted_by_cost. DATA lt_admit TYPE lcl_report=>tt_admit. DATA lt_lines TYPE lcl_report=>tt_line. DATA ls_line TYPE lcl_report=>ty_line. lt_admit = VALUE #( ( adm_id = 1 ward = 'A' admit_date = '20260101' discharge_date = '20260103' daily_rate = '10.00' ) ( adm_id = 2 ward = 'B' admit_date = '20260101' discharge_date = '20260111' daily_rate = '10.00' ) ). lt_lines = NEW lcl_report( )->aggregate( it_admit = lt_admit iv_to = '20260131' ). READ TABLE lt_lines INTO ls_line INDEX 1. cl_abap_unit_assert=>assert_equals( exp = 'B' act = ls_line-ward ). ENDMETHOD. ENDCLASS.