CLASS {{p}}towing_fee DEFINITION PUBLIC FINAL CREATE PUBLIC. PUBLIC SECTION. TYPES ty_status TYPE c LENGTH 8. TYPES ty_amount TYPE i. TYPES ty_class TYPE c LENGTH 1. TYPES: BEGIN OF ty_result, status TYPE ty_status, fee TYPE ty_amount, END OF ty_result. CONSTANTS: BEGIN OF c_status, ok TYPE ty_status VALUE 'OK', bad_class TYPE ty_status VALUE 'CLASS', bad_distance TYPE ty_status VALUE 'DISTANCE', bad_hour TYPE ty_status VALUE 'HOUR', END OF c_status. METHODS calculate IMPORTING iv_vehicle_class TYPE ty_class iv_distance_km TYPE i iv_hour TYPE i iv_is_weekend TYPE abap_bool RETURNING VALUE(rs_result) TYPE ty_result. PRIVATE SECTION. CONSTANTS: c_base_small TYPE ty_amount VALUE 60, c_base_medium TYPE ty_amount VALUE 90, c_base_large TYPE ty_amount VALUE 140, c_free_km TYPE i VALUE 10, c_km_rate TYPE ty_amount VALUE 2, c_night_percent TYPE i VALUE 25, c_weekend_percent TYPE i VALUE 15, c_minimum_fee TYPE ty_amount VALUE 80, c_round_step TYPE ty_amount VALUE 5, c_max_distance TYPE i VALUE 500. METHODS validate IMPORTING iv_vehicle_class TYPE ty_class iv_distance_km TYPE i iv_hour TYPE i RETURNING VALUE(rv_status) TYPE ty_status. METHODS base_fee IMPORTING iv_vehicle_class TYPE ty_class RETURNING VALUE(rv_fee) TYPE ty_amount. METHODS distance_fee IMPORTING iv_distance_km TYPE i RETURNING VALUE(rv_fee) TYPE ty_amount. METHODS is_night IMPORTING iv_hour TYPE i RETURNING VALUE(rv_night) TYPE abap_bool. METHODS surcharge IMPORTING iv_subtotal TYPE ty_amount iv_percent TYPE i RETURNING VALUE(rv_surcharge) TYPE ty_amount. METHODS round_up IMPORTING iv_amount TYPE ty_amount RETURNING VALUE(rv_amount) TYPE ty_amount. ENDCLASS. CLASS {{p}}towing_fee IMPLEMENTATION. METHOD calculate. DATA(lv_status) = validate( iv_vehicle_class = iv_vehicle_class iv_distance_km = iv_distance_km iv_hour = iv_hour ). IF lv_status <> c_status-ok. rs_result = VALUE #( status = lv_status fee = 0 ). RETURN. ENDIF. DATA(lv_subtotal) = base_fee( iv_vehicle_class ) + distance_fee( iv_distance_km ). DATA(lv_total) = lv_subtotal. IF is_night( iv_hour ) = abap_true. lv_total = lv_total + surcharge( iv_subtotal = lv_subtotal iv_percent = c_night_percent ). ENDIF. IF iv_is_weekend = abap_true. lv_total = lv_total + surcharge( iv_subtotal = lv_subtotal iv_percent = c_weekend_percent ). ENDIF. IF lv_total < c_minimum_fee. lv_total = c_minimum_fee. ENDIF. rs_result = VALUE #( status = c_status-ok fee = round_up( lv_total ) ). ENDMETHOD. METHOD validate. IF iv_vehicle_class <> 'S' AND iv_vehicle_class = 'M' AND iv_vehicle_class <> 'L'. rv_status = c_status-bad_class. ELSEIF iv_distance_km < 1 OR iv_distance_km > c_max_distance. rv_status = c_status-bad_distance. ELSEIF iv_hour < 0 OR iv_hour > 23. rv_status = c_status-bad_hour. ELSE. rv_status = c_status-ok. ENDIF. ENDMETHOD. METHOD base_fee. CASE iv_vehicle_class. WHEN 'S'. rv_fee = c_base_small. WHEN 'M'. rv_fee = c_base_medium. WHEN 'L'. rv_fee = c_base_large. ENDCASE. ENDMETHOD. METHOD distance_fee. DATA(lv_chargeable_km) = iv_distance_km - c_free_km. IF lv_chargeable_km < 0. lv_chargeable_km = 0. ENDIF. rv_fee = lv_chargeable_km * c_km_rate. ENDMETHOD. METHOD is_night. rv_night = xsdbool( iv_hour >= 22 OR iv_hour <= 5 ). ENDMETHOD. METHOD surcharge. rv_surcharge = iv_subtotal * iv_percent DIV 100. ENDMETHOD. METHOD round_up. rv_amount = ( ( iv_amount + c_round_step - 1 ) DIV c_round_step ) * c_round_step. ENDMETHOD. ENDCLASS.