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,79 @@
CLASS {{p}}laundry_pricer DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES:
ty_weight_kg TYPE p LENGTH 5 DECIMALS 2,
ty_amount TYPE p LENGTH 8 DECIMALS 2,
ty_service TYPE c LENGTH 4.
CONSTANTS:
c_service_wash TYPE ty_service VALUE 'WASH',
c_service_dry TYPE ty_service VALUE 'DRY',
c_service_iron TYPE ty_service VALUE 'IRON'.
METHODS calculate
IMPORTING
iv_weight_kg TYPE ty_weight_kg
iv_service TYPE ty_service
iv_express TYPE abap_bool
iv_member TYPE abap_bool
RETURNING
VALUE(rv_price) TYPE ty_amount.
PRIVATE SECTION.
CONSTANTS:
c_rate_wash TYPE ty_amount VALUE '2.50',
c_rate_dry TYPE ty_amount VALUE '4.00',
c_rate_iron TYPE ty_amount VALUE '1.50',
c_express_fee TYPE ty_amount VALUE '5.00',
c_min_price TYPE ty_amount VALUE '10.00',
c_member_discount TYPE ty_amount VALUE '0.90'.
METHODS rate_per_kg
IMPORTING iv_service TYPE ty_service
RETURNING VALUE(rv_rate) TYPE ty_amount.
METHODS round_currency
IMPORTING iv_amount TYPE ty_amount
RETURNING VALUE(rv_amount) TYPE ty_amount.
ENDCLASS.
CLASS {{p}}laundry_pricer IMPLEMENTATION.
METHOD calculate.
IF iv_weight_kg <= 0.
rv_price = 0.
RETURN.
ENDIF.
DATA lv_rate TYPE ty_amount.
DATA lv_price TYPE ty_amount.
lv_rate = rate_per_kg( iv_service ).
lv_price = iv_weight_kg * lv_rate.
IF iv_member <> abap_true.
lv_price = lv_price * c_member_discount.
ENDIF.
IF iv_express = abap_true.
lv_price = lv_price + c_express_fee.
ENDIF.
IF lv_price < c_min_price.
lv_price = c_min_price.
ENDIF.
rv_price = round_currency( lv_price ).
ENDMETHOD.
METHOD rate_per_kg.
CASE iv_service.
WHEN c_service_wash.
rv_rate = c_rate_wash.
WHEN c_service_dry.
rv_rate = c_rate_dry.
WHEN c_service_iron.
rv_rate = c_rate_iron.
WHEN OTHERS.
rv_rate = c_rate_wash.
ENDCASE.
ENDMETHOD.
METHOD round_currency.
rv_amount = round( val = iv_amount dec = 2 ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,79 @@
CLASS {{p}}laundry_pricer DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES:
ty_weight_kg TYPE p LENGTH 5 DECIMALS 2,
ty_amount TYPE p LENGTH 8 DECIMALS 2,
ty_service TYPE c LENGTH 4.
CONSTANTS:
c_service_wash TYPE ty_service VALUE 'WASH',
c_service_dry TYPE ty_service VALUE 'DRY',
c_service_iron TYPE ty_service VALUE 'IRON'.
METHODS calculate
IMPORTING
iv_weight_kg TYPE ty_weight_kg
iv_service TYPE ty_service
iv_express TYPE abap_bool
iv_member TYPE abap_bool
RETURNING
VALUE(rv_price) TYPE ty_amount.
PRIVATE SECTION.
CONSTANTS:
c_rate_wash TYPE ty_amount VALUE '2.50',
c_rate_dry TYPE ty_amount VALUE '4.00',
c_rate_iron TYPE ty_amount VALUE '1.50',
c_express_fee TYPE ty_amount VALUE '5.00',
c_min_price TYPE ty_amount VALUE '10.00',
c_member_discount TYPE ty_amount VALUE '0.90'.
METHODS rate_per_kg
IMPORTING iv_service TYPE ty_service
RETURNING VALUE(rv_rate) TYPE ty_amount.
METHODS round_currency
IMPORTING iv_amount TYPE ty_amount
RETURNING VALUE(rv_amount) TYPE ty_amount.
ENDCLASS.
CLASS {{p}}laundry_pricer IMPLEMENTATION.
METHOD calculate.
IF iv_weight_kg <= 0.
rv_price = 0.
RETURN.
ENDIF.
DATA lv_rate TYPE ty_amount.
DATA lv_price TYPE ty_amount.
lv_rate = rate_per_kg( iv_service ).
lv_price = iv_weight_kg * lv_rate.
IF iv_member = abap_true.
lv_price = lv_price * c_member_discount.
ENDIF.
IF iv_express = abap_false.
lv_price = lv_price + c_express_fee.
ENDIF.
IF lv_price < c_min_price.
lv_price = c_min_price.
ENDIF.
rv_price = round_currency( lv_price ).
ENDMETHOD.
METHOD rate_per_kg.
CASE iv_service.
WHEN c_service_wash.
rv_rate = c_rate_wash.
WHEN c_service_dry.
rv_rate = c_rate_dry.
WHEN c_service_iron.
rv_rate = c_rate_iron.
WHEN OTHERS.
rv_rate = c_rate_wash.
ENDCASE.
ENDMETHOD.
METHOD round_currency.
rv_amount = round( val = iv_amount dec = 2 ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,79 @@
CLASS {{p}}laundry_pricer DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES:
ty_weight_kg TYPE p LENGTH 5 DECIMALS 2,
ty_amount TYPE p LENGTH 8 DECIMALS 2,
ty_service TYPE c LENGTH 4.
CONSTANTS:
c_service_wash TYPE ty_service VALUE 'WASH',
c_service_dry TYPE ty_service VALUE 'DRY',
c_service_iron TYPE ty_service VALUE 'IRON'.
METHODS calculate
IMPORTING
iv_weight_kg TYPE ty_weight_kg
iv_service TYPE ty_service
iv_express TYPE abap_bool
iv_member TYPE abap_bool
RETURNING
VALUE(rv_price) TYPE ty_amount.
PRIVATE SECTION.
CONSTANTS:
c_rate_wash TYPE ty_amount VALUE '2.50',
c_rate_dry TYPE ty_amount VALUE '4.00',
c_rate_iron TYPE ty_amount VALUE '1.50',
c_express_fee TYPE ty_amount VALUE '5.00',
c_min_price TYPE ty_amount VALUE '10.00',
c_member_discount TYPE ty_amount VALUE '0.90'.
METHODS rate_per_kg
IMPORTING iv_service TYPE ty_service
RETURNING VALUE(rv_rate) TYPE ty_amount.
METHODS round_currency
IMPORTING iv_amount TYPE ty_amount
RETURNING VALUE(rv_amount) TYPE ty_amount.
ENDCLASS.
CLASS {{p}}laundry_pricer IMPLEMENTATION.
METHOD calculate.
IF iv_weight_kg <= 0.
rv_price = 0.
RETURN.
ENDIF.
DATA lv_rate TYPE ty_amount.
DATA lv_price TYPE ty_amount.
lv_rate = rate_per_kg( iv_service ).
lv_price = iv_weight_kg * lv_rate.
IF iv_member = abap_true.
lv_price = lv_price * c_member_discount.
ENDIF.
IF iv_express = abap_true.
lv_price = lv_price - c_express_fee.
ENDIF.
IF lv_price < c_min_price.
lv_price = c_min_price.
ENDIF.
rv_price = round_currency( lv_price ).
ENDMETHOD.
METHOD rate_per_kg.
CASE iv_service.
WHEN c_service_wash.
rv_rate = c_rate_wash.
WHEN c_service_dry.
rv_rate = c_rate_dry.
WHEN c_service_iron.
rv_rate = c_rate_iron.
WHEN OTHERS.
rv_rate = c_rate_wash.
ENDCASE.
ENDMETHOD.
METHOD round_currency.
rv_amount = round( val = iv_amount dec = 2 ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,79 @@
CLASS {{p}}laundry_pricer DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES:
ty_weight_kg TYPE p LENGTH 5 DECIMALS 2,
ty_amount TYPE p LENGTH 8 DECIMALS 2,
ty_service TYPE c LENGTH 4.
CONSTANTS:
c_service_wash TYPE ty_service VALUE 'WASH',
c_service_dry TYPE ty_service VALUE 'DRY',
c_service_iron TYPE ty_service VALUE 'IRON'.
METHODS calculate
IMPORTING
iv_weight_kg TYPE ty_weight_kg
iv_service TYPE ty_service
iv_express TYPE abap_bool
iv_member TYPE abap_bool
RETURNING
VALUE(rv_price) TYPE ty_amount.
PRIVATE SECTION.
CONSTANTS:
c_rate_wash TYPE ty_amount VALUE '2.50',
c_rate_dry TYPE ty_amount VALUE '4.00',
c_rate_iron TYPE ty_amount VALUE '1.50',
c_express_fee TYPE ty_amount VALUE '5.00',
c_min_price TYPE ty_amount VALUE '10.00',
c_member_discount TYPE ty_amount VALUE '0.90'.
METHODS rate_per_kg
IMPORTING iv_service TYPE ty_service
RETURNING VALUE(rv_rate) TYPE ty_amount.
METHODS round_currency
IMPORTING iv_amount TYPE ty_amount
RETURNING VALUE(rv_amount) TYPE ty_amount.
ENDCLASS.
CLASS {{p}}laundry_pricer IMPLEMENTATION.
METHOD calculate.
IF iv_weight_kg <= 0.
rv_price = 0.
RETURN.
ENDIF.
DATA lv_rate TYPE ty_amount.
DATA lv_price TYPE ty_amount.
lv_rate = rate_per_kg( iv_service ).
lv_price = iv_weight_kg * lv_rate.
IF iv_member = abap_true.
lv_price = lv_price * c_member_discount.
ENDIF.
IF iv_express = abap_true.
lv_price = lv_price + c_express_fee.
ENDIF.
IF lv_price >= c_min_price.
lv_price = c_min_price.
ENDIF.
rv_price = round_currency( lv_price ).
ENDMETHOD.
METHOD rate_per_kg.
CASE iv_service.
WHEN c_service_wash.
rv_rate = c_rate_wash.
WHEN c_service_dry.
rv_rate = c_rate_dry.
WHEN c_service_iron.
rv_rate = c_rate_iron.
WHEN OTHERS.
rv_rate = c_rate_wash.
ENDCASE.
ENDMETHOD.
METHOD round_currency.
rv_amount = round( val = iv_amount dec = 2 ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,24 @@
{
"id": "G0188",
"pool": "eval",
"object_type": "CLAS",
"category": "I",
"attempts": [
{
"stage": "validate",
"oracle": null,
"null": null
},
{
"stage": "validate",
"oracle": 100.0,
"null": 0,
"mutation": {
"valid": 5,
"killed": 4,
"ok": true
}
}
],
"accepted": true
}

View File

@@ -0,0 +1,113 @@
CLASS {{p}}t02_hidden DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
DATA mo_cut TYPE REF TO {{p}}laundry_pricer.
METHODS setup.
METHODS wash_basic FOR TESTING.
METHODS dry_basic FOR TESTING.
METHODS iron_basic FOR TESTING.
METHODS iron_above_min FOR TESTING.
METHODS express_no_member FOR TESTING.
METHODS member_no_express FOR TESTING.
METHODS member_then_express FOR TESTING.
METHODS min_after_discount FOR TESTING.
METHODS unknown_service FOR TESTING.
METHODS rounding FOR TESTING.
ENDCLASS.
CLASS {{p}}t02_hidden IMPLEMENTATION.
METHOD setup.
mo_cut = NEW {{p}}laundry_pricer( ).
ENDMETHOD.
METHOD wash_basic.
DATA(lv_price) = mo_cut->calculate( iv_weight_kg = '2.00'
iv_service = {{p}}laundry_pricer=>c_service_wash
iv_express = abap_false
iv_member = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}laundry_pricer=>ty_amount( '10.00' )
act = lv_price ).
ENDMETHOD.
METHOD dry_basic.
DATA(lv_price) = mo_cut->calculate( iv_weight_kg = '3.00'
iv_service = {{p}}laundry_pricer=>c_service_dry
iv_express = abap_false
iv_member = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}laundry_pricer=>ty_amount( '12.00' )
act = lv_price ).
ENDMETHOD.
METHOD iron_basic.
DATA(lv_price) = mo_cut->calculate( iv_weight_kg = '5.00'
iv_service = {{p}}laundry_pricer=>c_service_iron
iv_express = abap_false
iv_member = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}laundry_pricer=>ty_amount( '10.00' )
act = lv_price ).
ENDMETHOD.
METHOD iron_above_min.
DATA(lv_price) = mo_cut->calculate( iv_weight_kg = '8.00'
iv_service = {{p}}laundry_pricer=>c_service_iron
iv_express = abap_false
iv_member = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}laundry_pricer=>ty_amount( '12.00' )
act = lv_price ).
ENDMETHOD.
METHOD express_no_member.
DATA(lv_price) = mo_cut->calculate( iv_weight_kg = '4.00'
iv_service = {{p}}laundry_pricer=>c_service_wash
iv_express = abap_true
iv_member = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}laundry_pricer=>ty_amount( '15.00' )
act = lv_price ).
ENDMETHOD.
METHOD member_no_express.
DATA(lv_price) = mo_cut->calculate( iv_weight_kg = '5.00'
iv_service = {{p}}laundry_pricer=>c_service_wash
iv_express = abap_false
iv_member = abap_true ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}laundry_pricer=>ty_amount( '11.25' )
act = lv_price ).
ENDMETHOD.
METHOD member_then_express.
DATA(lv_price) = mo_cut->calculate( iv_weight_kg = '4.00'
iv_service = {{p}}laundry_pricer=>c_service_wash
iv_express = abap_true
iv_member = abap_true ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}laundry_pricer=>ty_amount( '14.00' )
act = lv_price ).
ENDMETHOD.
METHOD min_after_discount.
DATA(lv_price) = mo_cut->calculate( iv_weight_kg = '2.00'
iv_service = {{p}}laundry_pricer=>c_service_wash
iv_express = abap_false
iv_member = abap_true ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}laundry_pricer=>ty_amount( '10.00' )
act = lv_price ).
ENDMETHOD.
METHOD unknown_service.
DATA(lv_price) = mo_cut->calculate( iv_weight_kg = '2.00'
iv_service = 'XXXX'
iv_express = abap_false
iv_member = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}laundry_pricer=>ty_amount( '10.00' )
act = lv_price ).
ENDMETHOD.
METHOD rounding.
DATA(lv_price) = mo_cut->calculate( iv_weight_kg = '2.23'
iv_service = {{p}}laundry_pricer=>c_service_wash
iv_express = abap_true
iv_member = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}laundry_pricer=>ty_amount( '10.58' )
act = lv_price ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,74 @@
{
"task": "G0188",
"mutants": [
{
"object": "{{P}}LAUNDRY_PRICER",
"mutant": "line 48: = -> <> (eq)",
"status": "killed",
"hidden": "4/10",
"failed_tests": [
"DRY_BASIC",
"EXPRESS_NO_MEMBER",
"IRON_ABOVE_MIN",
"MEMBER_NO_EXPRESS",
"MEMBER_THEN_EXPRESS",
"ROUNDING"
]
},
{
"object": "{{P}}LAUNDRY_PRICER",
"mutant": "line 52: abap_true -> abap_false (bool)",
"status": "killed",
"hidden": "3/10",
"failed_tests": [
"DRY_BASIC",
"EXPRESS_NO_MEMBER",
"IRON_ABOVE_MIN",
"IRON_BASIC",
"MEMBER_NO_EXPRESS",
"MEMBER_THEN_EXPRESS",
"ROUNDING"
]
},
{
"object": "{{P}}LAUNDRY_PRICER",
"mutant": "line 53: + -> - (arith)",
"status": "killed",
"hidden": "7/10",
"failed_tests": [
"EXPRESS_NO_MEMBER",
"MEMBER_THEN_EXPRESS",
"ROUNDING"
]
},
{
"object": "{{P}}LAUNDRY_PRICER",
"mutant": "line 56: < -> >= (rel)",
"status": "killed",
"hidden": "0/10",
"failed_tests": [
"DRY_BASIC",
"EXPRESS_NO_MEMBER",
"IRON_ABOVE_MIN",
"IRON_BASIC",
"MEMBER_NO_EXPRESS",
"MEMBER_THEN_EXPRESS",
"MIN_AFTER_DISCOUNT",
"ROUNDING",
"UNKNOWN_SERVICE",
"WASH_BASIC"
]
},
{
"object": "{{P}}LAUNDRY_PRICER",
"mutant": "line 77: 2 -> 3 (const)",
"status": "survived",
"hidden": "10/10",
"failed_tests": []
}
],
"valid": 5,
"killed": 4,
"kill_rate": 0.8,
"ok": true
}

View File

@@ -0,0 +1,79 @@
CLASS {{p}}laundry_pricer DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES:
ty_weight_kg TYPE p LENGTH 5 DECIMALS 2,
ty_amount TYPE p LENGTH 8 DECIMALS 2,
ty_service TYPE c LENGTH 4.
CONSTANTS:
c_service_wash TYPE ty_service VALUE 'WASH',
c_service_dry TYPE ty_service VALUE 'DRY',
c_service_iron TYPE ty_service VALUE 'IRON'.
METHODS calculate
IMPORTING
iv_weight_kg TYPE ty_weight_kg
iv_service TYPE ty_service
iv_express TYPE abap_bool
iv_member TYPE abap_bool
RETURNING
VALUE(rv_price) TYPE ty_amount.
PRIVATE SECTION.
CONSTANTS:
c_rate_wash TYPE ty_amount VALUE '2.50',
c_rate_dry TYPE ty_amount VALUE '4.00',
c_rate_iron TYPE ty_amount VALUE '1.50',
c_express_fee TYPE ty_amount VALUE '5.00',
c_min_price TYPE ty_amount VALUE '10.00',
c_member_discount TYPE ty_amount VALUE '0.90'.
METHODS rate_per_kg
IMPORTING iv_service TYPE ty_service
RETURNING VALUE(rv_rate) TYPE ty_amount.
METHODS round_currency
IMPORTING iv_amount TYPE ty_amount
RETURNING VALUE(rv_amount) TYPE ty_amount.
ENDCLASS.
CLASS {{p}}laundry_pricer IMPLEMENTATION.
METHOD calculate.
IF iv_weight_kg <= 0.
rv_price = 0.
RETURN.
ENDIF.
DATA lv_rate TYPE ty_amount.
DATA lv_price TYPE ty_amount.
lv_rate = rate_per_kg( iv_service ).
lv_price = iv_weight_kg * lv_rate.
IF iv_member = abap_true.
lv_price = lv_price * c_member_discount.
ENDIF.
IF iv_express = abap_true.
lv_price = lv_price + c_express_fee.
ENDIF.
IF lv_price < c_min_price.
lv_price = c_min_price.
ENDIF.
rv_price = round_currency( lv_price ).
ENDMETHOD.
METHOD rate_per_kg.
CASE iv_service.
WHEN c_service_wash.
rv_rate = c_rate_wash.
WHEN c_service_dry.
rv_rate = c_rate_dry.
WHEN c_service_iron.
rv_rate = c_rate_iron.
WHEN OTHERS.
rv_rate = c_rate_wash.
ENDCASE.
ENDMETHOD.
METHOD round_currency.
rv_amount = round( val = iv_amount dec = 2 ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,62 @@
CLASS ltc_laundry_pricer DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
DATA mo_cut TYPE REF TO {{p}}laundry_pricer.
METHODS setup.
METHODS wash_basic FOR TESTING.
METHODS iron_rate FOR TESTING.
METHODS member_then_express FOR TESTING.
METHODS min_after_discount FOR TESTING.
METHODS unknown_service FOR TESTING.
ENDCLASS.
CLASS ltc_laundry_pricer IMPLEMENTATION.
METHOD setup.
mo_cut = NEW {{p}}laundry_pricer( ).
ENDMETHOD.
METHOD wash_basic.
DATA(lv_price) = mo_cut->calculate( iv_weight_kg = '2.00'
iv_service = {{p}}laundry_pricer=>c_service_wash
iv_express = abap_false
iv_member = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}laundry_pricer=>ty_amount( '10.00' )
act = lv_price ).
ENDMETHOD.
METHOD iron_rate.
DATA(lv_price) = mo_cut->calculate( iv_weight_kg = '8.00'
iv_service = {{p}}laundry_pricer=>c_service_iron
iv_express = abap_false
iv_member = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}laundry_pricer=>ty_amount( '12.00' )
act = lv_price ).
ENDMETHOD.
METHOD member_then_express.
DATA(lv_price) = mo_cut->calculate( iv_weight_kg = '4.00'
iv_service = {{p}}laundry_pricer=>c_service_wash
iv_express = abap_true
iv_member = abap_true ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}laundry_pricer=>ty_amount( '14.00' )
act = lv_price ).
ENDMETHOD.
METHOD min_after_discount.
DATA(lv_price) = mo_cut->calculate( iv_weight_kg = '2.00'
iv_service = {{p}}laundry_pricer=>c_service_wash
iv_express = abap_false
iv_member = abap_true ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}laundry_pricer=>ty_amount( '10.00' )
act = lv_price ).
ENDMETHOD.
METHOD unknown_service.
DATA(lv_price) = mo_cut->calculate( iv_weight_kg = '2.00'
iv_service = 'XXXX'
iv_express = abap_false
iv_member = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = CONV {{p}}laundry_pricer=>ty_amount( '10.00' )
act = lv_price ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,7 @@
{
"decision": "accept",
"note": "Real in-place I task: wash/dry rates, unknown service and rounding come only from the legacy code; tests check them. Survived mutant: round dec const.",
"by": "Claude",
"date": "2026-10-03",
"failed_checks": {}
}

View File

@@ -0,0 +1,71 @@
CLASS {{p}}laundry_pricer DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES:
ty_weight_kg TYPE p LENGTH 5 DECIMALS 2,
ty_amount TYPE p LENGTH 8 DECIMALS 2,
ty_service TYPE c LENGTH 4.
CONSTANTS:
c_service_wash TYPE ty_service VALUE 'WASH',
c_service_dry TYPE ty_service VALUE 'DRY',
c_service_iron TYPE ty_service VALUE 'IRON'.
METHODS calculate
IMPORTING
iv_weight_kg TYPE ty_weight_kg
iv_service TYPE ty_service
iv_express TYPE abap_bool
iv_member TYPE abap_bool
RETURNING
VALUE(rv_price) TYPE ty_amount.
PRIVATE SECTION.
CONSTANTS c_member_discount TYPE ty_amount VALUE '0.90'.
METHODS rate_per_kg
IMPORTING iv_service TYPE ty_service
RETURNING VALUE(rv_rate) TYPE ty_amount.
METHODS round_currency
IMPORTING iv_amount TYPE ty_amount
RETURNING VALUE(rv_amount) TYPE ty_amount.
ENDCLASS.
CLASS {{p}}laundry_pricer IMPLEMENTATION.
METHOD calculate.
IF iv_weight_kg <= 0.
rv_price = 0.
RETURN.
ENDIF.
DATA lv_rate TYPE ty_amount.
DATA lv_price TYPE ty_amount.
lv_rate = rate_per_kg( iv_service ).
lv_price = iv_weight_kg * lv_rate.
IF lv_price < 10.
lv_price = 10.
ENDIF.
IF iv_express = abap_true.
lv_price = lv_price + 5.
ENDIF.
IF iv_member = abap_true.
lv_price = lv_price * c_member_discount.
ENDIF.
rv_price = round_currency( lv_price ).
ENDMETHOD.
METHOD rate_per_kg.
CASE iv_service.
WHEN c_service_dry.
rv_rate = '4.00'.
WHEN c_service_iron.
rv_rate = '2.50'.
WHEN OTHERS.
rv_rate = '2.50'.
ENDCASE.
ENDMETHOD.
METHOD round_currency.
rv_amount = round( val = iv_amount dec = 2 ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,49 @@
# 1. Goal
Fix the class {{P}}LAUNDRY_PRICER. A laundry service uses the class to calculate the price of a laundry order. Users report three defects:
- A member pays the wrong price for a small order.
- A member gets a discount on the express surcharge.
- Ironing is much too expensive.
The class must calculate the correct price for every order.
# 2. Open questions
None.
# 3. Context
- The class {{P}}LAUNDRY_PRICER exists in package $TMP. It is active.
- The class is public and final. It has a public method CALCULATE with the
importing parameters iv_weight_kg, iv_service, iv_express, iv_member and the
returning parameter rv_price.
- The class has the public types ty_weight_kg, ty_amount and ty_service and the
public constants c_service_wash, c_service_dry and c_service_iron.
- The class has the private methods rate_per_kg and round_currency.
- A laundry order has a weight in kg, a service, an express flag and a member
flag. The services are WASH, DRY and IRON.
# 4. Contract
- Fix the class {{P}}LAUNDRY_PRICER in place.
- Do not change the public method signature, the public types or the public
constants.
- Do not add other public methods.
# 5. Business rules
Apply the rules in this sequence. All other behavior stays the same.
1. The base price is the weight multiplied by the rate per kg. A member gets a
discount of 10 percent on the base price. An express order costs a fixed
surcharge of 5.00. The member discount does not apply to the express
surcharge. Add the express surcharge after the member discount.
2. The minimum order value is 10.00. Apply the minimum after all discounts and
surcharges. If the price after all discounts and surcharges is below 10.00,
the price is 10.00.
3. The ironing service uses its own rate. The rate for ironing is 1.50 per kg.
# 6. Constraints
- Release target: 8.16.
- Coding standards: Clean ABAP. Method length below 40 statements. No global
variables. No comment that restates the code.
- Out of scope: do not change the public method signature, the public types or
the public constants.
# 7. Acceptance
- The class is active and has no syntax error.
- The hidden tests pass.
- Write your own ABAP Unit tests for the class.

View File

@@ -0,0 +1,47 @@
{
"id": "G0188",
"category": "I",
"object_type": "CLAS",
"difficulty": 2,
"release_target": "v816",
"expected_outcome": "implement",
"budget": {
"max_tool_calls": 40,
"max_activations": 10
},
"seed": [
{
"type": "CLAS",
"name": "{{P}}LAUNDRY_PRICER",
"file": "seed/laundry_pricer.clas.abap",
"description": "Faulty laundry price calculator"
}
],
"contract": [
{
"type": "CLAS",
"name": "{{P}}LAUNDRY_PRICER"
}
],
"out_of_scope": [],
"hidden_tests": [
{
"type": "CLAS",
"name": "{{P}}T02_HIDDEN",
"file": "hidden/t02_hidden.clas.abap",
"description": "Hidden tests for the laundry price calculator"
}
],
"reference": [
{
"type": "CLAS",
"name": "{{P}}LAUNDRY_PRICER",
"file": "reference/laundry_pricer.clas.abap",
"description": "Fixed laundry price calculator",
"testclasses_file": "reference/laundry_pricer.testclasses.abap"
}
],
"craft_checks": [
"method_length"
]
}