0121

Wrap It in a TryFunction

tryfunction
getlasterrortext
table

Wrap It in a TryFunction

Every night a job imports amount lines from a legacy system, and every night one malformed line kills the entire run with a raw runtime error. The fix is not to make the conversion infallible — it's to catch its failure, report why it failed, and make sure a failed line never leaves half-written data behind.

Requirements

The starter ships a table "Legacy Amount Entry" (primary key "Entry Code" of type Code[20], plus Amount of type Decimal). Keep it exactly as given — the tests read it by name.

Implement the codeunit named "Legacy Amount Import" with three public procedures:

procedure ParseAmount(AmountText: Text): Decimal
procedure TryParseAmount(AmountText: Text; var Amount: Decimal; var FailureReason: Text): Boolean
procedure ImportLine(EntryCode: Code[20]; AmountText: Text): Boolean

Rules:

  1. An amount text is valid when Evaluate accepts it as a Decimal and the value is not negative. Zero is valid.
  2. ParseAmount returns the decimal value of a valid amount text. For an invalid one — garbage text or a negative number — it raises an error with a message that contains the offending text wrapped in single quotes, followed by is not a valid amount (so for input abc the message contains 'abc' is not a valid amount — note the quotes and the exact phrase).
  3. TryParseAmount must never raise an error, whatever AmountText contains. On success it returns true, puts the value into Amount, and leaves FailureReason empty. On failure it returns false and puts the message of the error that ParseAmount would raise into FailureReason.
  4. FailureReason always describes the latest attempt: after two failed calls it names the second input, and after a failure followed by a success it is empty again — no stale error text may leak through.
  5. ImportLine converts AmountText and, if it is valid, inserts one "Legacy Amount Entry" with that code and the parsed amount, returning true. If it is invalid, it returns false, raises no error, and inserts nothing — the table must hold no row for that entry code, not even a partially filled one.

What the tests check

The tests call ParseAmount with generated valid amounts, zero, garbage and negatives, asserting the returned value or (via a caught error) the exact message phrase from rule 2. TryParseAmount is called directly — if it raises, the test fails — and its return value, Amount and FailureReason are checked for success, failure, failure-after-failure and success-after-failure. ImportLine is checked both ways: a valid line must land in "Legacy Amount Entry" with the right amount, and an invalid line must return false and leave the table without any row for that code.

Learn More

Hint 1
A raised error normally ends execution — but AL can call a procedure so that the error is caught and turned into a false return value instead. Look for a method attribute in the error-handling area of the docs.
Hint 2
A procedure marked [TryFunction] returns an implicit Boolean when called inside a condition — and it cannot declare its own return value, which is why TryParseAmount is a plain procedure wrapping a local try helper. After a failed try call, GetLastErrorText() holds the caught message; call ClearLastError() before the attempt so a stale text can't survive into a later success.
Hint 3
Keep Insert out of the try scope. The server blocks database writes inside try functions by default (DisableWriteInsideTryFunctions), and even where they are allowed, a caught error does not roll them back — the classic write-inside-try trap. Parse inside the try; write only after it has returned true.
ALBusiness Central 28.5
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.