# 1. Goal A grain cooperative accepts deliveries of grain at its silo. The weighbridge program calls one function module for each delivery. The function module checks the delivery before the silo accepts it. The function module rejects a delivery that breaks a quality rule. Each rejection is a class-based exception with a reason and a text. # 2. Open questions None. # 3. Context - Function group {{P}}FG_GRAIN is in package $TMP. - Function module {{P}}GRAIN_SAMPLE is in this group. It translates a grain type into a name. It shows the style of the group. - The weighbridge program calls the check module for each delivery. # 4. Contract Create the exception class {{P}}CX_GRAIN in package $TMP. - Superclass: CX_STATIC_CHECK. - Public read-only attribute MV_REASON of type string. - Public read-only attribute MV_TEXT of type string. - Constructor with importing parameter IV_REASON of type string. Create the function module {{P}}GRAIN_CHECK in function group {{P}}FG_GRAIN. - Importing parameter IV_GRAIN_TYPE of type string. - Importing parameter IV_WEIGHT_KG of type decfloat34. - Importing parameter IV_MOISTURE_PCT of type decfloat34. - Importing parameter IV_SUPPLIER of type string. - Exporting parameter EV_ACCEPTED of type abap_bool. - Exporting parameter EV_DRYING_COST of type decfloat34. - Raising exception {{P}}CX_GRAIN. # 5. Business rules The function module checks the rules in the given order. It raises the exception for the first rule that matches. 1. IV_WEIGHT_KG is less than or equal to 0: raise {{P}}CX_GRAIN with reason 'WEIGHT'. 2. IV_SUPPLIER is initial: raise {{P}}CX_GRAIN with reason 'SUPPLIER'. 3. IV_GRAIN_TYPE is not 'WHEAT', 'BARLEY' or 'RYE': raise {{P}}CX_GRAIN with reason 'GRAIN_TYPE'. 4. IV_MOISTURE_PCT is less than 0 or greater than 100: raise {{P}}CX_GRAIN with reason 'MOISTURE_RANGE'. 5. The maximum moisture is 14.5 for WHEAT, 14.0 for BARLEY and 15.0 for RYE. IV_MOISTURE_PCT is greater than the maximum moisture of the grain type: raise {{P}}CX_GRAIN with reason 'MOISTURE'. 6. No rule above matches: set EV_ACCEPTED to true. 7. The target moisture of a grain type is 2.0 below its maximum moisture. IV_MOISTURE_PCT is greater than the target moisture: EV_DRYING_COST is IV_WEIGHT_KG multiplied by the difference between IV_MOISTURE_PCT and the target moisture, multiplied by 0.75. Round the result half up to 2 decimals. Otherwise EV_DRYING_COST is 0. 8. The constructor of {{P}}CX_GRAIN sets MV_REASON to IV_REASON. The constructor also sets MV_TEXT to the text of the reason: - 'WEIGHT': Weight must be greater than zero - 'SUPPLIER': Supplier is not filled - 'GRAIN_TYPE': Grain type is not supported - 'MOISTURE_RANGE': Moisture is outside the range 0 to 100 - 'MOISTURE': Moisture is above the limit of the grain type # 6. Constraints - Release target: 8.16. - Use class-based exceptions. Do not use the classic EXCEPTIONS list. - Follow Clean ABAP. Keep each method below 40 statements. - Out of scope: do not change {{P}}GRAIN_SAMPLE. # 7. Acceptance - The exception class and the function module are active and have no syntax error. - The hidden tests pass. - Write ABAP Unit tests for the function module in a global test class.