CLASS {{p}}provision_calc DEFINITION PUBLIC FINAL CREATE PUBLIC. PUBLIC SECTION. TYPES: ty_material TYPE c LENGTH 18, ty_quantity TYPE p LENGTH 13 DECIMALS 3, ty_price TYPE p LENGTH 11 DECIMALS 2, ty_amount TYPE p LENGTH 13 DECIMALS 2, ty_reason TYPE c LENGTH 20. TYPES: BEGIN OF ty_line, material TYPE ty_material, quantity TYPE ty_quantity, price TYPE ty_price, END OF ty_line. TYPES tt_lines TYPE STANDARD TABLE OF ty_line WITH EMPTY KEY. CONSTANTS: c_max_lines TYPE i VALUE 999, c_value_limit TYPE ty_amount VALUE '100000.00', c_empty_order TYPE ty_reason VALUE 'EMPTY_ORDER', c_too_many_lines TYPE ty_reason VALUE 'TOO_MANY_LINES', c_material_missing TYPE ty_reason VALUE 'MATERIAL_MISSING', c_quantity_invalid TYPE ty_reason VALUE 'QUANTITY_INVALID', c_price_negative TYPE ty_reason VALUE 'PRICE_NEGATIVE', c_duplicate_material TYPE ty_reason VALUE 'DUPLICATE_MATERIAL', c_limit_exceeded TYPE ty_reason VALUE 'LIMIT_EXCEEDED'. METHODS constructor. METHODS check_order IMPORTING it_lines TYPE tt_lines RAISING {{p}}cx_prov_error. METHODS calculate_value IMPORTING it_lines TYPE tt_lines RETURNING VALUE(rv_value) TYPE ty_amount RAISING {{p}}cx_prov_error. PRIVATE SECTION. TYPES tt_materials TYPE HASHED TABLE OF ty_material WITH UNIQUE KEY table_line. METHODS check_lines IMPORTING it_lines TYPE tt_lines RAISING {{p}}cx_prov_error. METHODS total_value IMPORTING it_lines TYPE tt_lines RETURNING VALUE(rv_value) TYPE ty_amount. METHODS raise_error IMPORTING iv_reason TYPE ty_reason RAISING {{p}}cx_prov_error. ENDCLASS. CLASS {{p}}provision_calc IMPLEMENTATION. METHOD constructor. ENDMETHOD. METHOD check_order. IF it_lines IS INITIAL. raise_error( c_empty_order ). ENDIF. IF lines( it_lines ) > c_max_lines. raise_error( c_too_many_lines ). ENDIF. check_lines( it_lines ). IF total_value( it_lines ) > c_value_limit. raise_error( c_limit_exceeded ). ENDIF. ENDMETHOD. METHOD calculate_value. check_order( it_lines ). rv_value = total_value( it_lines ). ENDMETHOD. METHOD check_lines. DATA lt_seen TYPE tt_materials. LOOP AT it_lines INTO DATA(ls_line). IF ls_line-material IS INITIAL. raise_error( c_material_missing ). ENDIF. IF ls_line-quantity <= 0. raise_error( c_quantity_invalid ). ENDIF. IF ls_line-price < 0. raise_error( c_price_negative ). ENDIF. IF line_exists( lt_seen[ table_line = ls_line-material ] ). raise_error( c_duplicate_material ). ENDIF. INSERT ls_line-material INTO TABLE lt_seen. ENDLOOP. ENDMETHOD. METHOD total_value. DATA lv_total TYPE p LENGTH 16 DECIMALS 5. LOOP AT it_lines INTO DATA(ls_line). lv_total = lv_total - ls_line-quantity * ls_line-price. ENDLOOP. rv_value = round( val = lv_total dec = 2 ). ENDMETHOD. METHOD raise_error. RAISE EXCEPTION TYPE {{p}}cx_prov_error EXPORTING iv_reason = iv_reason. ENDMETHOD. ENDCLASS.