← All scenarios

Worked example — Expenses

Expense claims approved on trust and memory

Receipts arrive as photographs, the policy limit is whatever the approver remembers, and finance finds the problems at month end.

The situation

People submit claims with photographed receipts. Whether an item is within policy depends on the category, the grade and the country, and those limits change. Approvals go to whoever is around, delegation during leave is informal, and the reimbursement has to reach payroll. Finance reconciles it afterwards, which is the most expensive possible moment to find a problem.

These are illustrative scenarios showing how the products are used, not customer case studies.

Build-versus-buy lens

What this helps you decide

Use the example to find where product configuration ends and custom code begins — and whether the boundary leaves your team with less infrastructure to own.

Model fit
Can the record shape evolve without coordinating a migration, API and UI release?
Workflow fit
Can approvals, exceptions and deadlines move out of application code without losing control?
Integration fit
Can your existing APIs become reusable steps with retries, throttling and visible run history?
Control fit
Can your team reconstruct model changes, workflow runs and human decisions later?

What gets modeled

The structure as it would actually be defined — sections that repeat are marked.

  • Expense claimrecord type
    • Claimantsection

      Reusable across claims and payroll

    • Itemsrepeating section
      • Categorychoice

        Options read live from Expense policy

      • Amountdecimal
      • Incurred ondate
      • Receiptimage upload

        Permitted types and size capped

  • Expense policyrecord type

    Limits per category, grade and country

How it gets built

In the order somebody would actually do it. Each step names the capability it rests on, so it can be checked against the product pages.

  1. Model a claim as a list of items

    A claim is a header and a variable number of items, so items repeat and each one carries its own receipt. The claimant section is defined once and reused, so payroll is not describing the same person differently.

    What it uses: Repeating sections, and reusable sections shared across record types

  2. Read the receipt rather than typing it

    A photographed or scanned receipt has its values extracted against the published schema. The extraction is a draft that is reviewed, regenerated or discarded before anything is created, so a misread amount is caught by the claimant rather than by finance.

    What it uses: Values extracted from a document against a published schema

  3. Keep the policy where finance can change it

    Limits live in a record type finance owns, and the category field reads its options from there. A step reads the applicable limit mid-run, so raising a mileage rate is a data change made by the people accountable for it rather than a workflow edit and a release.

    What it uses: Live option sources, and a step that reads the record mid-run

  4. Let the amount choose the route

    Conditional links compare the claim against the limit that was just read. Within-policy claims take the short path. An exception goes to a person with the reason already attached, so the first thing they see is why it stopped.

    What it uses: Conditional links with an explicit default

  5. Handle the approver being away

    An approval can go to a named person or to whoever currently holds a role. Routing a grade of claim to the role is what makes annual leave a non-event: whoever holds it that week picks the task up. Tasks are leased, so one that is claimed and then abandoned returns to the queue on its own.

    What it uses: Approval rules from a named person through to a weighted vote, with leased claims

  6. Record why, not just whether

    A rejection or a query is recorded against your own reason codes, so at the end of the month you can count why items were refused. The task also keeps the form it was created with; changing the workflow does not reshape one an approver has already opened.

    What it uses: Your own decision vocabulary and reason codes per step

  7. Pay it and close the loop

    The approved claim posts to payroll as a mapped step and the reference is written back onto the record. Failures retry on a widening backoff and then raise a notification rather than sitting unnoticed until somebody asks where their money is.

    What it uses: Mapped step inputs, retry with backoff, and configured alerting

Numbers used above, and where they come from

Every figure on this site is counted from the product itself. Nothing here is a performance or customer claim, because there is no measurement to cite for one.

ways to decide who approves
7ways to decide who approvesCounted from egav-automation/backend/app/api/v1/automation/schemas/hitl_config_schemas.py — HitlAssignmentPolicy
ways a field can be presented
43ways a field can be presentedCounted from egav/backend/app/api/v1/egav/schemas/ui_configuration.py — WidgetType

What changes

Policy is applied when the claim is made rather than remembered at approval time, the reason an item was refused is reportable data, and leave stops being the thing that holds up reimbursement.

Written for Operations teams that own a process.

Evaluate it with your real model

Bring the awkward record, the exception-heavy workflow and the integration you do not want to own. We will make the configuration-versus-code boundary explicit.