Fix coverage with several contract classes; table annotation and file path checks; clean task dir on write

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014aUaQeLnwbb1zTpN7kHeat
This commit is contained in:
Kral
2026-10-03 08:44:35 +02:00
parent fb576b0954
commit 03ab36149e
388 changed files with 28620 additions and 339 deletions

View File

@@ -0,0 +1,143 @@
REPORT {{p}}waste_cost.
DATA gv_district TYPE {{p}}pickup-district.
PARAMETERS p_from TYPE d OBLIGATORY.
PARAMETERS p_to TYPE d OBLIGATORY.
SELECT-OPTIONS s_dist FOR gv_district.
CLASS lcl_report DEFINITION FINAL.
PUBLIC SECTION.
TYPES:
BEGIN OF ty_line,
district TYPE {{p}}pickup-district,
waste_type TYPE {{p}}pickup-waste_type,
weight TYPE {{p}}pickup-weight_kg,
cost TYPE {{p}}price-price_per_kg,
END OF ty_line,
tt_line TYPE STANDARD TABLE OF ty_line WITH EMPTY KEY.
TYPES tt_district TYPE RANGE OF {{p}}pickup-district.
METHODS select_costs
IMPORTING iv_from TYPE d
iv_to TYPE d
it_district TYPE tt_district
RETURNING VALUE(rt_lines) TYPE tt_line.
METHODS display
CHANGING ct_lines TYPE tt_line.
PRIVATE SECTION.
TYPES:
BEGIN OF ty_raw,
district TYPE {{p}}pickup-district,
waste_type TYPE {{p}}pickup-waste_type,
price TYPE {{p}}price-price_per_kg,
weight TYPE {{p}}pickup-weight_kg,
END OF ty_raw,
tt_raw TYPE STANDARD TABLE OF ty_raw WITH EMPTY KEY.
METHODS district_range
IMPORTING it_district TYPE tt_district
RETURNING VALUE(rt_district) TYPE tt_district.
ENDCLASS.
CLASS lcl_report IMPLEMENTATION.
METHOD district_range.
rt_district = it_district.
IF rt_district IS INITIAL.
rt_district = VALUE #( ( sign = 'I' option = 'CP' low = '*' ) ).
ENDIF.
ENDMETHOD.
METHOD select_costs.
DATA lt_raw TYPE tt_raw.
DATA(lt_district) = district_range( it_district ).
SELECT p~district, p~waste_type, r~price_per_kg AS price,
SUM( p~weight_kg ) AS weight
FROM {{p}}pickup AS p
INNER JOIN {{p}}price AS r ON r~waste_type = p~waste_type
WHERE p~pickup_date BETWEEN @iv_from AND @iv_to
OR p~district IN @lt_district
GROUP BY p~district, p~waste_type, r~price_per_kg
INTO CORRESPONDING FIELDS OF TABLE @lt_raw.
rt_lines = VALUE #( FOR ls_raw IN lt_raw
( district = ls_raw-district
waste_type = ls_raw-waste_type
weight = ls_raw-weight
cost = round( val = ls_raw-weight * ls_raw-price dec = 2 ) ) ).
SORT rt_lines BY cost DESCENDING district waste_type.
ENDMETHOD.
METHOD display.
TRY.
cl_salv_table=>factory( IMPORTING r_salv_table = DATA(lo_alv)
CHANGING t_table = ct_lines ).
lo_alv->display( ).
CATCH cx_salv_msg INTO DATA(lx_error).
MESSAGE lx_error TYPE 'I' DISPLAY LIKE 'E'.
ENDTRY.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
DATA(go_report) = NEW lcl_report( ).
DATA(gt_lines) = go_report->select_costs(
iv_from = p_from iv_to = p_to it_district = s_dist[] ).
go_report->display( CHANGING ct_lines = gt_lines ).
CLASS ltc_report DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
CLASS-DATA go_env TYPE REF TO if_osql_test_environment.
CLASS-METHODS class_setup.
CLASS-METHODS class_teardown.
METHODS costs_per_group FOR TESTING.
METHODS date_range FOR TESTING.
METHODS district_filter FOR TESTING.
ENDCLASS.
CLASS ltc_report IMPLEMENTATION.
METHOD class_setup.
go_env = cl_osql_test_environment=>create(
i_dependency_list = VALUE #( ( '{{P}}PICKUP' ) ( '{{P}}PRICE' ) ) ).
DATA lt_price TYPE STANDARD TABLE OF {{p}}price WITH EMPTY KEY.
lt_price = VALUE #( ( waste_type = 'PAPER' price_per_kg = '0.10' )
( waste_type = 'GLASS' price_per_kg = '0.05' ) ).
go_env->insert_test_data( lt_price ).
DATA lt_pickup TYPE STANDARD TABLE OF {{p}}pickup WITH EMPTY KEY.
lt_pickup = VALUE #(
( pickup_id = 1 district = 'N' waste_type = 'PAPER' pickup_date = '20260110' weight_kg = '100.00' )
( pickup_id = 2 district = 'N' waste_type = 'PAPER' pickup_date = '20260210' weight_kg = '50.00' )
( pickup_id = 3 district = 'N' waste_type = 'GLASS' pickup_date = '20260115' weight_kg = '200.00' )
( pickup_id = 4 district = 'S' waste_type = 'PAPER' pickup_date = '20260120' weight_kg = '300.00' ) ).
go_env->insert_test_data( lt_pickup ).
ENDMETHOD.
METHOD class_teardown.
go_env->destroy( ).
ENDMETHOD.
METHOD costs_per_group.
DATA(lt_lines) = NEW lcl_report( )->select_costs(
iv_from = '20260101' iv_to = '20261231'
it_district = VALUE #( ) ).
cl_abap_unit_assert=>assert_equals( exp = 3 act = lines( lt_lines ) ).
cl_abap_unit_assert=>assert_equals( exp = 'S' act = lt_lines[ 1 ]-district ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}price-price_per_kg( '30.00' ) act = lt_lines[ 1 ]-cost ).
ENDMETHOD.
METHOD date_range.
DATA(lt_lines) = NEW lcl_report( )->select_costs(
iv_from = '20260201' iv_to = '20261231'
it_district = VALUE #( ) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_lines ) ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}pickup-weight_kg( '50.00' ) act = lt_lines[ 1 ]-weight ).
ENDMETHOD.
METHOD district_filter.
DATA(lt_lines) = NEW lcl_report( )->select_costs(
iv_from = '20260101' iv_to = '20261231'
it_district = VALUE #( ( sign = 'I' option = 'EQ' low = 'S' ) ) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_lines ) ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}pickup-weight_kg( '300.00' ) act = lt_lines[ 1 ]-weight ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,143 @@
REPORT {{p}}waste_cost.
DATA gv_district TYPE {{p}}pickup-district.
PARAMETERS p_from TYPE d OBLIGATORY.
PARAMETERS p_to TYPE d OBLIGATORY.
SELECT-OPTIONS s_dist FOR gv_district.
CLASS lcl_report DEFINITION FINAL.
PUBLIC SECTION.
TYPES:
BEGIN OF ty_line,
district TYPE {{p}}pickup-district,
waste_type TYPE {{p}}pickup-waste_type,
weight TYPE {{p}}pickup-weight_kg,
cost TYPE {{p}}price-price_per_kg,
END OF ty_line,
tt_line TYPE STANDARD TABLE OF ty_line WITH EMPTY KEY.
TYPES tt_district TYPE RANGE OF {{p}}pickup-district.
METHODS select_costs
IMPORTING iv_from TYPE d
iv_to TYPE d
it_district TYPE tt_district
RETURNING VALUE(rt_lines) TYPE tt_line.
METHODS display
CHANGING ct_lines TYPE tt_line.
PRIVATE SECTION.
TYPES:
BEGIN OF ty_raw,
district TYPE {{p}}pickup-district,
waste_type TYPE {{p}}pickup-waste_type,
price TYPE {{p}}price-price_per_kg,
weight TYPE {{p}}pickup-weight_kg,
END OF ty_raw,
tt_raw TYPE STANDARD TABLE OF ty_raw WITH EMPTY KEY.
METHODS district_range
IMPORTING it_district TYPE tt_district
RETURNING VALUE(rt_district) TYPE tt_district.
ENDCLASS.
CLASS lcl_report IMPLEMENTATION.
METHOD district_range.
rt_district = it_district.
IF rt_district IS INITIAL.
rt_district = VALUE #( ( sign = 'I' option = 'CP' low = '*' ) ).
ENDIF.
ENDMETHOD.
METHOD select_costs.
DATA lt_raw TYPE tt_raw.
DATA(lt_district) = district_range( it_district ).
SELECT p~district, p~waste_type, r~price_per_kg AS price,
SUM( p~weight_kg ) AS weight
FROM {{p}}pickup AS p
INNER JOIN {{p}}price AS r ON r~waste_type = p~waste_type
WHERE p~pickup_date BETWEEN @iv_from AND @iv_to
AND p~district IN @lt_district
GROUP BY p~district, p~waste_type, r~price_per_kg
INTO CORRESPONDING FIELDS OF TABLE @lt_raw.
rt_lines = VALUE #( FOR ls_raw IN lt_raw
( district = ls_raw-district
waste_type = ls_raw-waste_type
weight = ls_raw-weight
cost = round( val = ls_raw-weight / ls_raw-price dec = 2 ) ) ).
SORT rt_lines BY cost DESCENDING district waste_type.
ENDMETHOD.
METHOD display.
TRY.
cl_salv_table=>factory( IMPORTING r_salv_table = DATA(lo_alv)
CHANGING t_table = ct_lines ).
lo_alv->display( ).
CATCH cx_salv_msg INTO DATA(lx_error).
MESSAGE lx_error TYPE 'I' DISPLAY LIKE 'E'.
ENDTRY.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
DATA(go_report) = NEW lcl_report( ).
DATA(gt_lines) = go_report->select_costs(
iv_from = p_from iv_to = p_to it_district = s_dist[] ).
go_report->display( CHANGING ct_lines = gt_lines ).
CLASS ltc_report DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
CLASS-DATA go_env TYPE REF TO if_osql_test_environment.
CLASS-METHODS class_setup.
CLASS-METHODS class_teardown.
METHODS costs_per_group FOR TESTING.
METHODS date_range FOR TESTING.
METHODS district_filter FOR TESTING.
ENDCLASS.
CLASS ltc_report IMPLEMENTATION.
METHOD class_setup.
go_env = cl_osql_test_environment=>create(
i_dependency_list = VALUE #( ( '{{P}}PICKUP' ) ( '{{P}}PRICE' ) ) ).
DATA lt_price TYPE STANDARD TABLE OF {{p}}price WITH EMPTY KEY.
lt_price = VALUE #( ( waste_type = 'PAPER' price_per_kg = '0.10' )
( waste_type = 'GLASS' price_per_kg = '0.05' ) ).
go_env->insert_test_data( lt_price ).
DATA lt_pickup TYPE STANDARD TABLE OF {{p}}pickup WITH EMPTY KEY.
lt_pickup = VALUE #(
( pickup_id = 1 district = 'N' waste_type = 'PAPER' pickup_date = '20260110' weight_kg = '100.00' )
( pickup_id = 2 district = 'N' waste_type = 'PAPER' pickup_date = '20260210' weight_kg = '50.00' )
( pickup_id = 3 district = 'N' waste_type = 'GLASS' pickup_date = '20260115' weight_kg = '200.00' )
( pickup_id = 4 district = 'S' waste_type = 'PAPER' pickup_date = '20260120' weight_kg = '300.00' ) ).
go_env->insert_test_data( lt_pickup ).
ENDMETHOD.
METHOD class_teardown.
go_env->destroy( ).
ENDMETHOD.
METHOD costs_per_group.
DATA(lt_lines) = NEW lcl_report( )->select_costs(
iv_from = '20260101' iv_to = '20261231'
it_district = VALUE #( ) ).
cl_abap_unit_assert=>assert_equals( exp = 3 act = lines( lt_lines ) ).
cl_abap_unit_assert=>assert_equals( exp = 'S' act = lt_lines[ 1 ]-district ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}price-price_per_kg( '30.00' ) act = lt_lines[ 1 ]-cost ).
ENDMETHOD.
METHOD date_range.
DATA(lt_lines) = NEW lcl_report( )->select_costs(
iv_from = '20260201' iv_to = '20261231'
it_district = VALUE #( ) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_lines ) ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}pickup-weight_kg( '50.00' ) act = lt_lines[ 1 ]-weight ).
ENDMETHOD.
METHOD district_filter.
DATA(lt_lines) = NEW lcl_report( )->select_costs(
iv_from = '20260101' iv_to = '20261231'
it_district = VALUE #( ( sign = 'I' option = 'EQ' low = 'S' ) ) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_lines ) ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}pickup-weight_kg( '300.00' ) act = lt_lines[ 1 ]-weight ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,143 @@
REPORT {{p}}waste_cost.
DATA gv_district TYPE {{p}}pickup-district.
PARAMETERS p_from TYPE d OBLIGATORY.
PARAMETERS p_to TYPE d OBLIGATORY.
SELECT-OPTIONS s_dist FOR gv_district.
CLASS lcl_report DEFINITION FINAL.
PUBLIC SECTION.
TYPES:
BEGIN OF ty_line,
district TYPE {{p}}pickup-district,
waste_type TYPE {{p}}pickup-waste_type,
weight TYPE {{p}}pickup-weight_kg,
cost TYPE {{p}}price-price_per_kg,
END OF ty_line,
tt_line TYPE STANDARD TABLE OF ty_line WITH EMPTY KEY.
TYPES tt_district TYPE RANGE OF {{p}}pickup-district.
METHODS select_costs
IMPORTING iv_from TYPE d
iv_to TYPE d
it_district TYPE tt_district
RETURNING VALUE(rt_lines) TYPE tt_line.
METHODS display
CHANGING ct_lines TYPE tt_line.
PRIVATE SECTION.
TYPES:
BEGIN OF ty_raw,
district TYPE {{p}}pickup-district,
waste_type TYPE {{p}}pickup-waste_type,
price TYPE {{p}}price-price_per_kg,
weight TYPE {{p}}pickup-weight_kg,
END OF ty_raw,
tt_raw TYPE STANDARD TABLE OF ty_raw WITH EMPTY KEY.
METHODS district_range
IMPORTING it_district TYPE tt_district
RETURNING VALUE(rt_district) TYPE tt_district.
ENDCLASS.
CLASS lcl_report IMPLEMENTATION.
METHOD district_range.
rt_district = it_district.
IF rt_district IS INITIAL.
rt_district = VALUE #( ( sign = 'I' option = 'CP' low = '*' ) ).
ENDIF.
ENDMETHOD.
METHOD select_costs.
DATA lt_raw TYPE tt_raw.
DATA(lt_district) = district_range( it_district ).
SELECT p~district, p~waste_type, r~price_per_kg AS price,
SUM( p~weight_kg ) AS weight
FROM {{p}}pickup AS p
INNER JOIN {{p}}price AS r ON r~waste_type = p~waste_type
WHERE p~pickup_date BETWEEN @iv_from AND @iv_to
AND p~district IN @lt_district
GROUP BY p~district, p~waste_type, r~price_per_kg
INTO CORRESPONDING FIELDS OF TABLE @lt_raw.
rt_lines = VALUE #( FOR ls_raw IN lt_raw
( district = ls_raw-district
waste_type = ls_raw-waste_type
weight = ls_raw-weight
cost = round( val = ls_raw-weight * ls_raw-price dec = 3 ) ) ).
SORT rt_lines BY cost DESCENDING district waste_type.
ENDMETHOD.
METHOD display.
TRY.
cl_salv_table=>factory( IMPORTING r_salv_table = DATA(lo_alv)
CHANGING t_table = ct_lines ).
lo_alv->display( ).
CATCH cx_salv_msg INTO DATA(lx_error).
MESSAGE lx_error TYPE 'I' DISPLAY LIKE 'E'.
ENDTRY.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
DATA(go_report) = NEW lcl_report( ).
DATA(gt_lines) = go_report->select_costs(
iv_from = p_from iv_to = p_to it_district = s_dist[] ).
go_report->display( CHANGING ct_lines = gt_lines ).
CLASS ltc_report DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
CLASS-DATA go_env TYPE REF TO if_osql_test_environment.
CLASS-METHODS class_setup.
CLASS-METHODS class_teardown.
METHODS costs_per_group FOR TESTING.
METHODS date_range FOR TESTING.
METHODS district_filter FOR TESTING.
ENDCLASS.
CLASS ltc_report IMPLEMENTATION.
METHOD class_setup.
go_env = cl_osql_test_environment=>create(
i_dependency_list = VALUE #( ( '{{P}}PICKUP' ) ( '{{P}}PRICE' ) ) ).
DATA lt_price TYPE STANDARD TABLE OF {{p}}price WITH EMPTY KEY.
lt_price = VALUE #( ( waste_type = 'PAPER' price_per_kg = '0.10' )
( waste_type = 'GLASS' price_per_kg = '0.05' ) ).
go_env->insert_test_data( lt_price ).
DATA lt_pickup TYPE STANDARD TABLE OF {{p}}pickup WITH EMPTY KEY.
lt_pickup = VALUE #(
( pickup_id = 1 district = 'N' waste_type = 'PAPER' pickup_date = '20260110' weight_kg = '100.00' )
( pickup_id = 2 district = 'N' waste_type = 'PAPER' pickup_date = '20260210' weight_kg = '50.00' )
( pickup_id = 3 district = 'N' waste_type = 'GLASS' pickup_date = '20260115' weight_kg = '200.00' )
( pickup_id = 4 district = 'S' waste_type = 'PAPER' pickup_date = '20260120' weight_kg = '300.00' ) ).
go_env->insert_test_data( lt_pickup ).
ENDMETHOD.
METHOD class_teardown.
go_env->destroy( ).
ENDMETHOD.
METHOD costs_per_group.
DATA(lt_lines) = NEW lcl_report( )->select_costs(
iv_from = '20260101' iv_to = '20261231'
it_district = VALUE #( ) ).
cl_abap_unit_assert=>assert_equals( exp = 3 act = lines( lt_lines ) ).
cl_abap_unit_assert=>assert_equals( exp = 'S' act = lt_lines[ 1 ]-district ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}price-price_per_kg( '30.00' ) act = lt_lines[ 1 ]-cost ).
ENDMETHOD.
METHOD date_range.
DATA(lt_lines) = NEW lcl_report( )->select_costs(
iv_from = '20260201' iv_to = '20261231'
it_district = VALUE #( ) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_lines ) ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}pickup-weight_kg( '50.00' ) act = lt_lines[ 1 ]-weight ).
ENDMETHOD.
METHOD district_filter.
DATA(lt_lines) = NEW lcl_report( )->select_costs(
iv_from = '20260101' iv_to = '20261231'
it_district = VALUE #( ( sign = 'I' option = 'EQ' low = 'S' ) ) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_lines ) ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}pickup-weight_kg( '300.00' ) act = lt_lines[ 1 ]-weight ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,34 @@
{
"id": "G0112",
"pool": "eval",
"object_type": "PROG",
"category": "B",
"attempts": [
{
"stage": "validate",
"oracle": 90.0,
"null": 0
},
{
"stage": "validate",
"oracle": 100.0,
"null": 0,
"mutation": {
"valid": 3,
"killed": 2,
"ok": false
}
},
{
"stage": "validate",
"oracle": 100.0,
"null": 0,
"mutation": {
"valid": 3,
"killed": 3,
"ok": true
}
}
],
"accepted": true
}

View File

@@ -0,0 +1,160 @@
CLASS {{p}}waste_hidden DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
TYPES tt_district TYPE RANGE OF {{p}}pickup-district.
CLASS-DATA go_env TYPE REF TO if_osql_test_environment.
CLASS-METHODS class_setup.
CLASS-METHODS class_teardown.
METHODS run
IMPORTING iv_from TYPE d
iv_to TYPE d
it_district TYPE tt_district OPTIONAL
RETURNING VALUE(rr_data) TYPE REF TO data.
METHODS lines_of
IMPORTING ir_data TYPE REF TO data
RETURNING VALUE(rv_lines) TYPE i.
METHODS value_of
IMPORTING ir_data TYPE REF TO data
iv_row TYPE i
iv_col TYPE string
RETURNING VALUE(rv_value) TYPE string.
METHODS all_lines FOR TESTING.
METHODS weights_and_costs FOR TESTING.
METHODS date_range FOR TESTING.
METHODS district_filter FOR TESTING.
METHODS sorted_by_cost FOR TESTING.
METHODS tie_break_order FOR TESTING.
METHODS cost_rounding FOR TESTING.
METHODS double_rounding FOR TESTING.
METHODS empty_result FOR TESTING.
ENDCLASS.
CLASS {{p}}waste_hidden IMPLEMENTATION.
METHOD class_setup.
go_env = cl_osql_test_environment=>create(
i_dependency_list = VALUE #( ( '{{P}}PICKUP' ) ( '{{P}}PRICE' ) ) ).
DATA lt_price TYPE STANDARD TABLE OF {{p}}price WITH EMPTY KEY.
lt_price = VALUE #(
( waste_type = 'PAPER' price_per_kg = '0.10' )
( waste_type = 'GLASS' price_per_kg = '0.05' )
( waste_type = 'METAL' price_per_kg = '0.50' )
( waste_type = 'PLASTIC' price_per_kg = '0.10' ) ).
go_env->insert_test_data( lt_price ).
DATA lt_pickup TYPE STANDARD TABLE OF {{p}}pickup WITH EMPTY KEY.
lt_pickup = VALUE #(
( pickup_id = 1 district = 'N' waste_type = 'PAPER' pickup_date = '20260110' weight_kg = '100.00' )
( pickup_id = 2 district = 'N' waste_type = 'PAPER' pickup_date = '20260210' weight_kg = '50.00' )
( pickup_id = 3 district = 'N' waste_type = 'GLASS' pickup_date = '20260115' weight_kg = '200.00' )
( pickup_id = 4 district = 'S' waste_type = 'PAPER' pickup_date = '20260120' weight_kg = '300.00' )
( pickup_id = 5 district = 'S' waste_type = 'METAL' pickup_date = '20251231' weight_kg = '500.00' )
( pickup_id = 6 district = 'S' waste_type = 'METAL' pickup_date = '20260301' weight_kg = '20.00' )
( pickup_id = 7 district = 'W' waste_type = 'PLASTIC' pickup_date = '20260105' weight_kg = '10.05' )
( pickup_id = 8 district = 'E' waste_type = 'GLASS' pickup_date = '20260112' weight_kg = '20.09' ) ).
go_env->insert_test_data( lt_pickup ).
ENDMETHOD.
METHOD class_teardown.
go_env->destroy( ).
ENDMETHOD.
METHOD run.
cl_salv_bs_runtime_info=>set( display = abap_false metadata = abap_false data = abap_true ).
SUBMIT {{p}}waste_cost
WITH p_from = iv_from
WITH p_to = iv_to
WITH s_dist IN it_district
AND RETURN.
TRY.
cl_salv_bs_runtime_info=>get_data_ref( IMPORTING r_data = rr_data ).
CATCH cx_salv_bs_sc_runtime_info.
ENDTRY.
cl_salv_bs_runtime_info=>clear_all( ).
ENDMETHOD.
METHOD lines_of.
FIELD-SYMBOLS <lt_data> TYPE STANDARD TABLE.
IF ir_data IS BOUND.
ASSIGN ir_data->* TO <lt_data>.
rv_lines = lines( <lt_data> ).
ENDIF.
ENDMETHOD.
METHOD value_of.
FIELD-SYMBOLS <lt_data> TYPE STANDARD TABLE.
ASSIGN ir_data->* TO <lt_data>.
ASSIGN <lt_data>[ iv_row ] TO FIELD-SYMBOL(<ls_line>).
ASSIGN COMPONENT iv_col OF STRUCTURE <ls_line> TO FIELD-SYMBOL(<lv_value>).
cl_abap_unit_assert=>assert_subrc( exp = 0 msg = |Column { iv_col } missing| ).
rv_value = condense( CONV string( <lv_value> ) ).
ENDMETHOD.
METHOD all_lines.
cl_abap_unit_assert=>assert_equals( exp = 6 act = lines_of( run( iv_from = '20260101' iv_to = '20261231' ) ) ).
ENDMETHOD.
METHOD weights_and_costs.
DATA(lr_data) = run( iv_from = '20260101' iv_to = '20261231' ).
cl_abap_unit_assert=>assert_equals( exp = `S` act = value_of( ir_data = lr_data iv_row = 1 iv_col = `DISTRICT` ) ).
cl_abap_unit_assert=>assert_equals( exp = `PAPER` act = value_of( ir_data = lr_data iv_row = 1 iv_col = `WASTE_TYPE` ) ).
cl_abap_unit_assert=>assert_equals( exp = `300.00` act = value_of( ir_data = lr_data iv_row = 1 iv_col = `WEIGHT` ) ).
cl_abap_unit_assert=>assert_equals( exp = `30.00` act = value_of( ir_data = lr_data iv_row = 1 iv_col = `COST` ) ).
cl_abap_unit_assert=>assert_equals( exp = `150.00` act = value_of( ir_data = lr_data iv_row = 2 iv_col = `WEIGHT` ) ).
cl_abap_unit_assert=>assert_equals( exp = `15.00` act = value_of( ir_data = lr_data iv_row = 2 iv_col = `COST` ) ).
ENDMETHOD.
METHOD date_range.
DATA(lr_data) = run( iv_from = '20260201' iv_to = '20261231' ).
cl_abap_unit_assert=>assert_equals( exp = 2 act = lines_of( lr_data ) ).
cl_abap_unit_assert=>assert_equals( exp = `S` act = value_of( ir_data = lr_data iv_row = 1 iv_col = `DISTRICT` ) ).
cl_abap_unit_assert=>assert_equals( exp = `10.00` act = value_of( ir_data = lr_data iv_row = 1 iv_col = `COST` ) ).
cl_abap_unit_assert=>assert_equals( exp = `5.00` act = value_of( ir_data = lr_data iv_row = 2 iv_col = `COST` ) ).
ENDMETHOD.
METHOD district_filter.
DATA(lr_data) = run( iv_from = '20260101' iv_to = '20261231'
it_district = VALUE #( ( sign = 'I' option = 'EQ' low = 'N' ) ) ).
cl_abap_unit_assert=>assert_equals( exp = 2 act = lines_of( lr_data ) ).
cl_abap_unit_assert=>assert_equals( exp = `N` act = value_of( ir_data = lr_data iv_row = 1 iv_col = `DISTRICT` ) ).
cl_abap_unit_assert=>assert_equals( exp = `15.00` act = value_of( ir_data = lr_data iv_row = 1 iv_col = `COST` ) ).
cl_abap_unit_assert=>assert_equals( exp = `10.00` act = value_of( ir_data = lr_data iv_row = 2 iv_col = `COST` ) ).
ENDMETHOD.
METHOD sorted_by_cost.
DATA(lr_data) = run( iv_from = '20260101' iv_to = '20261231' ).
cl_abap_unit_assert=>assert_equals( exp = `30.00` act = value_of( ir_data = lr_data iv_row = 1 iv_col = `COST` ) ).
cl_abap_unit_assert=>assert_equals( exp = `15.00` act = value_of( ir_data = lr_data iv_row = 2 iv_col = `COST` ) ).
cl_abap_unit_assert=>assert_equals( exp = `10.00` act = value_of( ir_data = lr_data iv_row = 3 iv_col = `COST` ) ).
cl_abap_unit_assert=>assert_equals( exp = `10.00` act = value_of( ir_data = lr_data iv_row = 4 iv_col = `COST` ) ).
cl_abap_unit_assert=>assert_equals( exp = `1.01` act = value_of( ir_data = lr_data iv_row = 5 iv_col = `COST` ) ).
cl_abap_unit_assert=>assert_equals( exp = `1.00` act = value_of( ir_data = lr_data iv_row = 6 iv_col = `COST` ) ).
ENDMETHOD.
METHOD tie_break_order.
DATA(lr_data) = run( iv_from = '20260101' iv_to = '20261231' ).
cl_abap_unit_assert=>assert_equals( exp = `N` act = value_of( ir_data = lr_data iv_row = 3 iv_col = `DISTRICT` ) ).
cl_abap_unit_assert=>assert_equals( exp = `GLASS` act = value_of( ir_data = lr_data iv_row = 3 iv_col = `WASTE_TYPE` ) ).
cl_abap_unit_assert=>assert_equals( exp = `S` act = value_of( ir_data = lr_data iv_row = 4 iv_col = `DISTRICT` ) ).
cl_abap_unit_assert=>assert_equals( exp = `METAL` act = value_of( ir_data = lr_data iv_row = 4 iv_col = `WASTE_TYPE` ) ).
ENDMETHOD.
METHOD cost_rounding.
DATA(lr_data) = run( iv_from = '20260101' iv_to = '20261231'
it_district = VALUE #( ( sign = 'I' option = 'EQ' low = 'W' ) ) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines_of( lr_data ) ).
cl_abap_unit_assert=>assert_equals( exp = `1.01` act = value_of( ir_data = lr_data iv_row = 1 iv_col = `COST` ) ).
ENDMETHOD.
METHOD double_rounding.
DATA(lr_data) = run( iv_from = '20260101' iv_to = '20261231'
it_district = VALUE #( ( sign = 'I' option = 'EQ' low = 'E' ) ) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines_of( lr_data ) ).
cl_abap_unit_assert=>assert_equals( exp = `GLASS` act = value_of( ir_data = lr_data iv_row = 1 iv_col = `WASTE_TYPE` ) ).
cl_abap_unit_assert=>assert_equals( exp = `20.09` act = value_of( ir_data = lr_data iv_row = 1 iv_col = `WEIGHT` ) ).
cl_abap_unit_assert=>assert_equals( exp = `1.00` act = value_of( ir_data = lr_data iv_row = 1 iv_col = `COST` ) ).
ENDMETHOD.
METHOD empty_result.
cl_abap_unit_assert=>assert_equals( exp = 0 act = lines_of( run( iv_from = '20270101' iv_to = '20271231' ) ) ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,57 @@
{
"task": "G0112",
"mutants": [
{
"object": "{{P}}WASTE_COST",
"mutant": "line 57: AND -> OR (logic)",
"status": "invalid",
"hidden": "0/0",
"failed_tests": []
},
{
"object": "{{P}}WASTE_COST",
"mutant": "line 58: AND -> OR (logic)",
"status": "killed",
"hidden": "1/9",
"failed_tests": [
"COST_ROUNDING",
"DATE_RANGE",
"DISTRICT_FILTER",
"DOUBLE_ROUNDING",
"EMPTY_RESULT",
"SORTED_BY_COST",
"TIE_BREAK_ORDER",
"WEIGHTS_AND_COSTS"
]
},
{
"object": "{{P}}WASTE_COST",
"mutant": "line 66: * -> / (arith)",
"status": "killed",
"hidden": "2/9",
"failed_tests": [
"COST_ROUNDING",
"DATE_RANGE",
"DISTRICT_FILTER",
"DOUBLE_ROUNDING",
"SORTED_BY_COST",
"TIE_BREAK_ORDER",
"WEIGHTS_AND_COSTS"
]
},
{
"object": "{{P}}WASTE_COST",
"mutant": "line 66: 2 -> 3 (const)",
"status": "killed",
"hidden": "7/9",
"failed_tests": [
"DOUBLE_ROUNDING",
"SORTED_BY_COST"
]
}
],
"valid": 3,
"killed": 3,
"kill_rate": 1.0,
"ok": true
}

View File

@@ -0,0 +1,143 @@
REPORT {{p}}waste_cost.
DATA gv_district TYPE {{p}}pickup-district.
PARAMETERS p_from TYPE d OBLIGATORY.
PARAMETERS p_to TYPE d OBLIGATORY.
SELECT-OPTIONS s_dist FOR gv_district.
CLASS lcl_report DEFINITION FINAL.
PUBLIC SECTION.
TYPES:
BEGIN OF ty_line,
district TYPE {{p}}pickup-district,
waste_type TYPE {{p}}pickup-waste_type,
weight TYPE {{p}}pickup-weight_kg,
cost TYPE {{p}}price-price_per_kg,
END OF ty_line,
tt_line TYPE STANDARD TABLE OF ty_line WITH EMPTY KEY.
TYPES tt_district TYPE RANGE OF {{p}}pickup-district.
METHODS select_costs
IMPORTING iv_from TYPE d
iv_to TYPE d
it_district TYPE tt_district
RETURNING VALUE(rt_lines) TYPE tt_line.
METHODS display
CHANGING ct_lines TYPE tt_line.
PRIVATE SECTION.
TYPES:
BEGIN OF ty_raw,
district TYPE {{p}}pickup-district,
waste_type TYPE {{p}}pickup-waste_type,
price TYPE {{p}}price-price_per_kg,
weight TYPE {{p}}pickup-weight_kg,
END OF ty_raw,
tt_raw TYPE STANDARD TABLE OF ty_raw WITH EMPTY KEY.
METHODS district_range
IMPORTING it_district TYPE tt_district
RETURNING VALUE(rt_district) TYPE tt_district.
ENDCLASS.
CLASS lcl_report IMPLEMENTATION.
METHOD district_range.
rt_district = it_district.
IF rt_district IS INITIAL.
rt_district = VALUE #( ( sign = 'I' option = 'CP' low = '*' ) ).
ENDIF.
ENDMETHOD.
METHOD select_costs.
DATA lt_raw TYPE tt_raw.
DATA(lt_district) = district_range( it_district ).
SELECT p~district, p~waste_type, r~price_per_kg AS price,
SUM( p~weight_kg ) AS weight
FROM {{p}}pickup AS p
INNER JOIN {{p}}price AS r ON r~waste_type = p~waste_type
WHERE p~pickup_date BETWEEN @iv_from AND @iv_to
AND p~district IN @lt_district
GROUP BY p~district, p~waste_type, r~price_per_kg
INTO CORRESPONDING FIELDS OF TABLE @lt_raw.
rt_lines = VALUE #( FOR ls_raw IN lt_raw
( district = ls_raw-district
waste_type = ls_raw-waste_type
weight = ls_raw-weight
cost = round( val = ls_raw-weight * ls_raw-price dec = 2 ) ) ).
SORT rt_lines BY cost DESCENDING district waste_type.
ENDMETHOD.
METHOD display.
TRY.
cl_salv_table=>factory( IMPORTING r_salv_table = DATA(lo_alv)
CHANGING t_table = ct_lines ).
lo_alv->display( ).
CATCH cx_salv_msg INTO DATA(lx_error).
MESSAGE lx_error TYPE 'I' DISPLAY LIKE 'E'.
ENDTRY.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
DATA(go_report) = NEW lcl_report( ).
DATA(gt_lines) = go_report->select_costs(
iv_from = p_from iv_to = p_to it_district = s_dist[] ).
go_report->display( CHANGING ct_lines = gt_lines ).
CLASS ltc_report DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
CLASS-DATA go_env TYPE REF TO if_osql_test_environment.
CLASS-METHODS class_setup.
CLASS-METHODS class_teardown.
METHODS costs_per_group FOR TESTING.
METHODS date_range FOR TESTING.
METHODS district_filter FOR TESTING.
ENDCLASS.
CLASS ltc_report IMPLEMENTATION.
METHOD class_setup.
go_env = cl_osql_test_environment=>create(
i_dependency_list = VALUE #( ( '{{P}}PICKUP' ) ( '{{P}}PRICE' ) ) ).
DATA lt_price TYPE STANDARD TABLE OF {{p}}price WITH EMPTY KEY.
lt_price = VALUE #( ( waste_type = 'PAPER' price_per_kg = '0.10' )
( waste_type = 'GLASS' price_per_kg = '0.05' ) ).
go_env->insert_test_data( lt_price ).
DATA lt_pickup TYPE STANDARD TABLE OF {{p}}pickup WITH EMPTY KEY.
lt_pickup = VALUE #(
( pickup_id = 1 district = 'N' waste_type = 'PAPER' pickup_date = '20260110' weight_kg = '100.00' )
( pickup_id = 2 district = 'N' waste_type = 'PAPER' pickup_date = '20260210' weight_kg = '50.00' )
( pickup_id = 3 district = 'N' waste_type = 'GLASS' pickup_date = '20260115' weight_kg = '200.00' )
( pickup_id = 4 district = 'S' waste_type = 'PAPER' pickup_date = '20260120' weight_kg = '300.00' ) ).
go_env->insert_test_data( lt_pickup ).
ENDMETHOD.
METHOD class_teardown.
go_env->destroy( ).
ENDMETHOD.
METHOD costs_per_group.
DATA(lt_lines) = NEW lcl_report( )->select_costs(
iv_from = '20260101' iv_to = '20261231'
it_district = VALUE #( ) ).
cl_abap_unit_assert=>assert_equals( exp = 3 act = lines( lt_lines ) ).
cl_abap_unit_assert=>assert_equals( exp = 'S' act = lt_lines[ 1 ]-district ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}price-price_per_kg( '30.00' ) act = lt_lines[ 1 ]-cost ).
ENDMETHOD.
METHOD date_range.
DATA(lt_lines) = NEW lcl_report( )->select_costs(
iv_from = '20260201' iv_to = '20261231'
it_district = VALUE #( ) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_lines ) ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}pickup-weight_kg( '50.00' ) act = lt_lines[ 1 ]-weight ).
ENDMETHOD.
METHOD district_filter.
DATA(lt_lines) = NEW lcl_report( )->select_costs(
iv_from = '20260101' iv_to = '20261231'
it_district = VALUE #( ( sign = 'I' option = 'EQ' low = 'S' ) ) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_lines ) ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}pickup-weight_kg( '300.00' ) act = lt_lines[ 1 ]-weight ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,13 @@
@EndUserText.label : 'Waste pickups'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table {{p}}pickup {
key client : abap.clnt not null;
key pickup_id : abap.int4 not null;
district : abap.char(4);
waste_type : abap.char(10);
pickup_date : abap.dats;
weight_kg : abap.dec(15,2);
}

View File

@@ -0,0 +1,10 @@
@EndUserText.label : 'Waste type price'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table {{p}}price {
key client : abap.clnt not null;
key waste_type : abap.char(10) not null;
price_per_kg : abap.dec(15,2);
}

View File

@@ -0,0 +1,26 @@
CLASS {{p}}waste_seed DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
ENDCLASS.
CLASS {{p}}waste_seed IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
DELETE FROM {{p}}pickup.
DELETE FROM {{p}}price.
INSERT {{p}}price FROM TABLE @( VALUE #(
( waste_type = 'PAPER' price_per_kg = '0.10' )
( waste_type = 'GLASS' price_per_kg = '0.05' )
( waste_type = 'METAL' price_per_kg = '0.50' )
( waste_type = 'PLASTIC' price_per_kg = '0.10' ) ) ).
INSERT {{p}}pickup FROM TABLE @( VALUE #(
( pickup_id = 1 district = 'N' waste_type = 'PAPER' pickup_date = '20260110' weight_kg = '100.00' )
( pickup_id = 2 district = 'N' waste_type = 'PAPER' pickup_date = '20260210' weight_kg = '50.00' )
( pickup_id = 3 district = 'N' waste_type = 'GLASS' pickup_date = '20260115' weight_kg = '200.00' )
( pickup_id = 4 district = 'S' waste_type = 'PAPER' pickup_date = '20260120' weight_kg = '300.00' )
( pickup_id = 5 district = 'S' waste_type = 'METAL' pickup_date = '20251231' weight_kg = '500.00' )
( pickup_id = 6 district = 'S' waste_type = 'METAL' pickup_date = '20260301' weight_kg = '20.00' )
( pickup_id = 7 district = 'W' waste_type = 'PLASTIC' pickup_date = '20260105' weight_kg = '10.05' )
( pickup_id = 8 district = 'E' waste_type = 'GLASS' pickup_date = '20260112' weight_kg = '20.09' ) ) ).
out->write( sy-dbcnt ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,55 @@
# 1. Goal
Show the waste collection cost for each district and waste type in an ALV list.
The waste team uses the list to compare the costs of a period.
# 2. Open questions
None.
# 3. Context
- Table {{P}}PICKUP exists in package $TMP. It contains data.
Fields: PICKUP_ID (INT4, key), DISTRICT (CHAR 4), WASTE_TYPE (CHAR 10),
PICKUP_DATE (DATS), WEIGHT_KG (DEC 15,2).
- Table {{P}}PRICE exists in package $TMP. It contains data.
Fields: WASTE_TYPE (CHAR 10, key), PRICE_PER_KG (DEC 15,2).
# 4. Contract
- Create the executable program {{P}}WASTE_COST in package $TMP.
- Selection screen:
- Parameter P_FROM, type DATS, mandatory: the first pickup date to include.
- Parameter P_TO, type DATS, mandatory: the last pickup date to include.
- Select-option S_DIST for the district.
- Show the result with CL_SALV_TABLE. The output table has these columns, with
these names and these types:
- DISTRICT, type {{P}}PICKUP-DISTRICT.
- WASTE_TYPE, type {{P}}PICKUP-WASTE_TYPE.
- WEIGHT, type {{P}}PICKUP-WEIGHT_KG.
- COST, type {{P}}PRICE-PRICE_PER_KG.
# 5. Business rules
1. Include a pickup only if PICKUP_DATE is on or after P_FROM and on or before
P_TO.
2. Include a pickup only if its DISTRICT is in S_DIST. If S_DIST is empty,
include every district.
3. The cost of a pickup is WEIGHT_KG multiplied by the PRICE_PER_KG of its
waste type. Each waste type in {{P}}PICKUP has exactly one row in
{{P}}PRICE.
4. Show one line for each combination of DISTRICT and WASTE_TYPE that has at
least one included pickup.
5. WEIGHT is the sum of the WEIGHT_KG values of the included pickups of the
line.
6. COST is the sum of the costs of the included pickups of the line. Round
COST to 2 decimal places. Round half up.
7. Sort the lines by COST, the highest cost first. If two lines have the same
COST, sort them by DISTRICT in ascending order and then by WASTE_TYPE in
ascending order.
8. If no pickup is included, the list is empty.
# 6. Constraints
- Release target: 8.16.
- Coding standards: Clean ABAP. Read the data with one database access.
- Out of scope: do not change {{P}}PICKUP and {{P}}PRICE.
# 7. Acceptance
- The program is active and has no syntax error.
- The hidden tests pass.
- Write ABAP Unit tests as local test classes in the program.

View File

@@ -0,0 +1,68 @@
{
"id": "G0112",
"category": "B",
"object_type": "PROG",
"difficulty": 2,
"release_target": "v816",
"expected_outcome": "implement",
"budget": {
"max_tool_calls": 40,
"max_activations": 10
},
"seed": [
{
"type": "TABL",
"name": "{{P}}PICKUP",
"file": "seed/pickup.tabl.asabap",
"description": "Waste pickups per district and waste type"
},
{
"type": "TABL",
"name": "{{P}}PRICE",
"file": "seed/price.tabl.asabap",
"description": "Price per kilogram for each waste type"
},
{
"type": "CLAS",
"name": "{{P}}WASTE_SEED",
"file": "seed/waste_seed.clas.abap",
"description": "Waste seed data",
"run": true
}
],
"contract": [
{
"type": "PROG",
"name": "{{P}}WASTE_COST",
"parameters": [
"p_from",
"p_to",
"s_dist"
]
}
],
"out_of_scope": [
"{{P}}PICKUP",
"{{P}}PRICE"
],
"hidden_tests": [
{
"type": "CLAS",
"name": "{{P}}WASTE_HIDDEN",
"file": "hidden/waste_hidden.clas.abap",
"description": "Waste cost hidden tests"
}
],
"reference": [
{
"type": "PROG",
"name": "{{P}}WASTE_COST",
"file": "reference/waste_cost.prog.abap",
"description": "Waste collection cost report"
}
],
"craft_checks": [
"db_operation_in_loop",
"method_length"
]
}