Pipeline controller: plan 2 (hard +, error +50 %), backlog throttle, 2 trajectory workers, stop rules, summaries every 50; budget reserve

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Kral
2026-10-05 13:35:54 +02:00
parent 1c4667a0fc
commit 13360292dd
781 changed files with 50211 additions and 22 deletions

View File

@@ -0,0 +1,77 @@
CLASS {{p}}licence_merger DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES {{p}}if_licence_merge.
PRIVATE SECTION.
TYPES tt_merged TYPE HASHED TABLE OF {{p}}if_licence_merge=>ty_licence
WITH UNIQUE KEY product cost_centre.
METHODS add_rows
IMPORTING it_rows TYPE {{p}}if_licence_merge=>tt_licences
CHANGING ct_merged TYPE tt_merged.
METHODS normalize
IMPORTING is_row TYPE {{p}}if_licence_merge=>ty_licence
RETURNING VALUE(rs_row) TYPE {{p}}if_licence_merge=>ty_licence.
METHODS is_relevant
IMPORTING is_row TYPE {{p}}if_licence_merge=>ty_licence
RETURNING VALUE(rv_relevant) TYPE abap_bool.
METHODS trim_upper
IMPORTING iv_text TYPE string
RETURNING VALUE(rv_text) TYPE string.
ENDCLASS.
CLASS {{p}}licence_merger IMPLEMENTATION.
METHOD {{p}}if_licence_merge~merge.
DATA lt_merged TYPE tt_merged.
add_rows( EXPORTING it_rows = it_primary CHANGING ct_merged = lt_merged ).
add_rows( EXPORTING it_rows = it_secondary CHANGING ct_merged = lt_merged ).
rt_merged = lt_merged.
SORT rt_merged BY product cost_centre.
ENDMETHOD.
METHOD add_rows.
LOOP AT it_rows INTO DATA(ls_row).
DATA(ls_norm) = normalize( ls_row ).
IF is_relevant( ls_norm ) = abap_false.
CONTINUE.
ENDIF.
READ TABLE ct_merged ASSIGNING FIELD-SYMBOL(<ls_merged>)
WITH TABLE KEY product = ls_norm-product
cost_centre = ls_norm-cost_centre.
IF sy-subrc = 0.
<ls_merged>-seats = <ls_merged>-seats + ls_norm-seats.
IF ls_norm-unit_price > <ls_merged>-unit_price.
<ls_merged>-unit_price = ls_norm-unit_price.
ENDIF.
ELSE.
INSERT ls_norm INTO TABLE ct_merged.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD normalize.
rs_row = is_row.
rs_row-product = trim_upper( CONV string( is_row-product ) ).
rs_row-cost_centre = trim_upper( CONV string( is_row-cost_centre ) ).
ENDMETHOD.
METHOD is_relevant.
rv_relevant = xsdbool( is_row-product IS NOT INITIAL
AND is_row-cost_centre IS NOT INITIAL
AND is_row-seats >= 1 ).
ENDMETHOD.
METHOD trim_upper.
DATA(lv_text) = iv_text.
SHIFT lv_text LEFT DELETING LEADING space.
SHIFT lv_text RIGHT DELETING TRAILING space.
rv_text = to_upper( lv_text ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,92 @@
CLASS ltc_licence_merger DEFINITION FINAL FOR TESTING
DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
DATA mo_cut TYPE REF TO {{p}}if_licence_merge.
METHODS setup.
METHODS merges_two_lists FOR TESTING.
METHODS ignores_invalid_rows FOR TESTING.
METHODS normalizes_keys FOR TESTING.
METHODS sorts_the_result FOR TESTING.
METHODS empty_input FOR TESTING.
ENDCLASS.
CLASS ltc_licence_merger IMPLEMENTATION.
METHOD setup.
mo_cut = NEW {{p}}licence_merger( ).
ENDMETHOD.
METHOD merges_two_lists.
DATA(lt_primary) = VALUE {{p}}if_licence_merge=>tt_licences(
( product = 'ALPHA' cost_centre = '1000' seats = 5 unit_price = '100.00' ) ).
DATA(lt_secondary) = VALUE {{p}}if_licence_merge=>tt_licences(
( product = 'ALPHA' cost_centre = '1000' seats = 2 unit_price = '120.00' ) ).
DATA(lt_act) = mo_cut->merge( it_primary = lt_primary
it_secondary = lt_secondary ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_act ) ).
DATA(ls_row) = lt_act[ 1 ].
cl_abap_unit_assert=>assert_equals( exp = 7 act = ls_row-seats ).
cl_abap_unit_assert=>assert_equals(
exp = CONV {{p}}if_licence_merge=>ty_price( '120.00' )
act = ls_row-unit_price ).
ENDMETHOD.
METHOD ignores_invalid_rows.
DATA(lt_primary) = VALUE {{p}}if_licence_merge=>tt_licences(
( product = '' cost_centre = '1000' seats = 5 unit_price = '10.00' )
( product = 'ALPHA' cost_centre = '1000' seats = 0 unit_price = '10.00' )
( product = 'BETA' cost_centre = '2000' seats = 2 unit_price = '3.00' ) ).
DATA(lt_secondary) = VALUE {{p}}if_licence_merge=>tt_licences( ).
DATA(lt_act) = mo_cut->merge( it_primary = lt_primary
it_secondary = lt_secondary ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_act ) ).
DATA(ls_row) = lt_act[ 1 ].
cl_abap_unit_assert=>assert_equals( exp = 'BETA' act = ls_row-product ).
ENDMETHOD.
METHOD normalizes_keys.
DATA(lt_primary) = VALUE {{p}}if_licence_merge=>tt_licences(
( product = ' alpha ' cost_centre = '1000' seats = 1 unit_price = '2.00' ) ).
DATA(lt_secondary) = VALUE {{p}}if_licence_merge=>tt_licences(
( product = 'ALPHA' cost_centre = '1000' seats = 1 unit_price = '2.00' ) ).
DATA(lt_act) = mo_cut->merge( it_primary = lt_primary
it_secondary = lt_secondary ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_act ) ).
DATA(ls_row) = lt_act[ 1 ].
cl_abap_unit_assert=>assert_equals( exp = 'ALPHA' act = ls_row-product ).
cl_abap_unit_assert=>assert_equals( exp = 2 act = ls_row-seats ).
ENDMETHOD.
METHOD sorts_the_result.
DATA(lt_primary) = VALUE {{p}}if_licence_merge=>tt_licences(
( product = 'BETA' cost_centre = '2000' seats = 1 unit_price = '1.00' )
( product = 'ALPHA' cost_centre = '3000' seats = 1 unit_price = '1.00' )
( product = 'ALPHA' cost_centre = '1000' seats = 1 unit_price = '1.00' ) ).
DATA(lt_secondary) = VALUE {{p}}if_licence_merge=>tt_licences( ).
DATA(lt_act) = mo_cut->merge( it_primary = lt_primary
it_secondary = lt_secondary ).
cl_abap_unit_assert=>assert_equals( exp = 3 act = lines( lt_act ) ).
DATA(ls_row) = lt_act[ 1 ].
cl_abap_unit_assert=>assert_equals( exp = 'ALPHA' act = ls_row-product ).
cl_abap_unit_assert=>assert_equals( exp = '1000' act = ls_row-cost_centre ).
ls_row = lt_act[ 3 ].
cl_abap_unit_assert=>assert_equals( exp = 'BETA' act = ls_row-product ).
ENDMETHOD.
METHOD empty_input.
DATA(lt_empty) = VALUE {{p}}if_licence_merge=>tt_licences( ).
DATA(lt_act) = mo_cut->merge( it_primary = lt_empty
it_secondary = lt_empty ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lines( lt_act ) ).
ENDMETHOD.
ENDCLASS.