0065

One Interface, Three Calculators

Extensibility
Medium
interface
enum
implements
strategy-pattern

One Interface, Three Calculators

Your company keeps changing how it charges shipping: this quarter it's a flat fee, the webshop team wants weight-based pricing, and marketing just promised free shipping on large orders. Every change so far has meant editing a growing case statement buried in posting code. You are going to end that: model the fee schemes the way the base application models price calculation — an enum picks the strategy, an interface defines the contract, and the calling code never knows which codeunit does the math.

Requirements

  1. Keep the interface "Shipping Fee Calculator" exactly as the starter declares it — one procedure:
procedure CalculateFee(ParcelWeightKg: Decimal; OrderAmount: Decimal): Decimal
  1. Wire the enum "Shipping Fee Method" to real calculators. The starter's enum already implements the interface, but every value falls back to the "Shipping Fee Placeholder" codeunit, whose CalculateFee only raises an error. Give each of its three values — "Flat Rate", "By Weight", "Free Over Threshold" — its own Implementation, so that assigning any of them to a variable of type Interface "Shipping Fee Calculator" yields a working calculator for that scheme. Once every value is wired, you may delete the placeholder, or keep it as the default for values nobody has wired yet — either is fine.
  2. Implement three calculator codeunits (their names are your choice — the tests never reference them directly), one per enum value, with these exact rules:
    • "Flat Rate" — the fee is always 9.90, whatever the weight or the order amount.
    • "By Weight" — the fee is the parcel weight in kg times 1.60, rounded to the nearest cent (0.01); when that computed fee is below the 5.00 minimum, the fee is exactly 5.00. The order amount plays no part.
    • "Free Over Threshold" — orders with an amount of 100.00 or more ship free (fee 0); below 100.00 the fee is a flat 7.50. The parcel weight plays no part.

What the tests check

The grading tests never name your codeunits: each test assigns one "Shipping Fee Method" value to an Interface "Shipping Fee Calculator" variable and calls CalculateFee through it, so the enum wiring itself is under test — against the unchanged starter every test fails with the placeholder's error, No shipping fee calculator is wired to this Shipping Fee Method yet. The tests probe randomized weights and amounts (a hardcoded fee won't survive "By Weight"), the cent rounding in both directions (a 4.03 kg parcel is 6.448, expected 6.45; a 4.02 kg parcel is 6.432, expected 6.43), the minimum-fee boundary (a 3.125 kg parcel costs exactly 5.00), and the free-shipping threshold at exactly 100.00, just below it (99.99) and above it. Every test passes a random value for the parameter its scheme is supposed to ignore.

Learn More

Hint 1
The base application's Price Calculation has exactly this shape: an enum value picks the strategy, an interface defines the contract, and the calling code never names a concrete codeunit. The AL keywords to research are interface and implements.
Hint 2
Three pieces have to agree: the interface declares the signature, each calculator codeunit declares implements "Shipping Fee Calculator" and provides that exact procedure, and the enum — which already declares implements in the starter — lets each value name its own codeunit. The placeholder codeunit shows the exact shape a calculator must have; it is only what the enum's DefaultImplementation falls back to for values that have not been wired.
Hint 3
Each enum value wires itself with Implementation = "Shipping Fee Calculator" = <Your Codeunit Name>; inside its value(...) { } block — a value's own Implementation overrides the enum's DefaultImplementation. Once that compiles, assigning the value to an Interface "Shipping Fee Calculator" variable dispatches straight to your codeunit instead of the placeholder, which is exactly what the tests do.
ALBusiness Central 28.4
Press Compile to check your code compiles — Submit runs the tests.
The code editor is desktop-only
Open this problem on a computer to write and run code. Reading the description, tests and discussion works fine here.