CLASS {{p}}freight_calc DEFINITION PUBLIC FINAL CREATE PUBLIC. PUBLIC SECTION. TYPES ty_cost TYPE p LENGTH 15 DECIMALS 2. TYPES ty_weight TYPE p LENGTH 15 DECIMALS 3. TYPES: BEGIN OF ty_result, cost TYPE ty_cost, currency TYPE c LENGTH 5, END OF ty_result. METHODS calculate IMPORTING iv_zone_code TYPE c LENGTH 4 iv_weight_kg TYPE ty_weight iv_express TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rs_result) TYPE ty_result RAISING {{p}}cx_freight_error. PRIVATE SECTION. CONSTANTS c_express_factor TYPE p LENGTH 5 DECIMALS 2 VALUE '1.50'. CONSTANTS c_minimum_charge TYPE ty_cost VALUE '6.00'. METHODS find_zone IMPORTING iv_zone_code TYPE c LENGTH 4 RETURNING VALUE(rs_zone) TYPE {{p}}zone_master=>ty_zone RAISING {{p}}cx_freight_error. ENDCLASS. CLASS {{p}}freight_calc IMPLEMENTATION. METHOD calculate. DATA lv_zone_code TYPE c LENGTH 4. lv_zone_code = to_upper( iv_zone_code ). IF iv_weight_kg <= 0. DATA(lo_invalid) = NEW {{p}}cx_invalid_weight( ). lo_invalid->mv_zone_code = lv_zone_code. lo_invalid->mv_weight_kg = iv_weight_kg. RAISE EXCEPTION lo_invalid. ENDIF. DATA(ls_zone) = find_zone( lv_zone_code ). IF iv_weight_kg > ls_zone-max_weight_kg. DATA(lo_limit) = NEW {{p}}cx_weight_limit( ). lo_limit->mv_zone_code = lv_zone_code. lo_limit->mv_weight_kg = iv_weight_kg. lo_limit->mv_max_weight_kg = ls_zone-max_weight_kg. RAISE EXCEPTION lo_limit. ENDIF. DATA lv_cost TYPE p LENGTH 15 DECIMALS 5. lv_cost = ls_zone-base_fee + iv_weight_kg * ls_zone-price_per_kg. IF iv_express = abap_true. lv_cost = lv_cost * c_express_factor. ENDIF. lv_cost = round( val = lv_cost dec = 2 ). IF lv_cost < c_minimum_charge. lv_cost = c_minimum_charge. ENDIF. rs_result-cost = lv_cost. rs_result-currency = ls_zone-currency. ENDMETHOD. METHOD find_zone. DATA(lt_zone) = {{p}}zone_master=>get_all( ). READ TABLE lt_zone INTO rs_zone WITH KEY zone_code = iv_zone_code. IF sy-subrc <> 0. DATA(lo_unknown) = NEW {{p}}cx_unknown_zone( ). lo_unknown->mv_zone_code = iv_zone_code. RAISE EXCEPTION lo_unknown. ENDIF. ENDMETHOD. ENDCLASS.