MB-820 study materials
MB-820 study resources

Designing an Equipment Rental extension for scale

MB-820 · Put your knowledge to work in context.

All case studies

Designing an Equipment Rental extension for scale

A partner is building an Equipment Rental per-tenant extension. Requirements: on the Customer card, a "Rental Blocked" boolean and "Max Open Rentals" integer; a new "Rental Contract" header and line table; the Customer list must display an "Open Rental Count"; the rental line page must only offer items in the Rental Item category; and the Customer card must warn the user when Max Open Rentals is exceeded at contract release. Current data volume is 400,000 customers and 2,000,000 rental lines. A first prototype added a FlowField that sums line amounts onto Customer, and the customer list page now takes 20 seconds to open.

1. Which AL object types should be used for each requirement, and why?

Read the worked answer
  • Customer fields → tableextension on Customer, plus a pageextension on the Customer Card and Customer List to surface them. Never modify the base table; the extension travels with the app and survives upgrades.
  • Rental Contract header and lines → new tables in the 50100+ range with a TableRelation from line to header on "No.", and a LookupPageId/DrillDownPageId on the header so lookups work.
  • Item category restriction → a TableRelation with a filter on the line's Item No. field, or an OnLookup trigger if the rule needs to consider contract context. Prefer declarative TableRelation when the rule is static - it also protects programmatic assignment via Validate.
  • Warning at release → a codeunit that subscribes to the release event of the sales/rental document; not a page trigger, because the rule must hold for any caller, including APIs and job queue entries.
  • Option vs Enum → use Enum for the category and any new status field; Enums are extensible by other extensions and avoid the Option-extension limitations.

Judgment being tested: choose the object type by who must be protected from the rule, and prefer declarative validation over UI-level code.

2. The prototype's FlowField makes the customer list take 20 seconds. Diagnose the cause and propose a design that scales.

Read the worked answer

A SumFlowField over 2,000,000 lines is computed per visible row on a list page. With 400,000 customers, the page issues an aggregate query for each row rendered, and each aggregate has to scan the line table. Twenty seconds is the expected consequence, not a bug.

Options, in order of preference:

  1. Denormalize a counter. Store Open Rental Count on the Customer table and maintain it in the same transaction that creates, releases or closes a rental contract. Reads become a single field fetch; writes cost one Modify. Choose this when the counter is read constantly and changed rarely relative to reads.
  2. Keep a FlowField but make it cheap. A Count formula with a properly indexed key on the line table (Customer No. as the leading key field) is far cheaper than a sum across many columns - but it is still N queries per page.
  3. Compute on demand. Do not put the FlowField on the list page by default; show it on the card and calculate when the user opens it (CalcFields). Good when the number is informational.
  4. Avoid FlowFilter on a huge table - a filtered FlowField is the most expensive variant of an already expensive pattern.

Also check the page: if a FlowField is displayed, ensure only the fields actually needed are calculated, and keep the list page's source table narrow. The exam judgment is recognizing that a FlowField is a query, and a list page multiplies it by row count.

3. Where should the "blocked" and "max open rentals" validation live, and should the release check raise an error or a warning?

Read the worked answer

Split the rule by consequence:

  • Field-level rules (for example: Max Open Rentals cannot be negative, or cannot be set while Rental Blocked is true) belong in the OnValidate trigger of the table field, so every write path - page, API, job queue - is covered. Put the rule in the table, not in the page's trigger, and let the page inherit it.
  • Cross-record rules (open rentals exceed the maximum) cannot be enforced on OnValidate of a single field, because contract lines are not yet saved at that point. Enforce them in an event subscriber at the point where the contract is released or confirmed.

Error vs warning:

  • If releasing an over-limit contract would produce an operation the business considers invalid, raise an error so the transaction rolls back and there is no half-released document.
  • If it is a policy that a supervisor may override, use a confirm dialog and record who overrode it. A confirm in an event subscriber that is not handled correctly can still let the base logic continue - verify the event's IsHandled semantics rather than assuming.

Judgment point: the same business rule may need error at release and warning at entry. Decide by whether a partial state is acceptable, and put each rule where it cannot be bypassed.