Read the policy header
- 1
Name should describe the population and purpose clearly enough for approvers to recognize it.
- 2
Partner Account is an exact match; blank is not a tenant-wide wildcard for populated claims.
- 3
Grade narrows the rule set to the corresponding employee grade.
- 4
Effective From and Effective To bound when the policy participates.
- 5
Is Active enables evaluation; business or approval flows must still consume block and higher-approval signals.
The policy header answers three questions before any rule evaluates: what the rule set is called, which exact partner account and employee grade it scopes, and when it is effective. Partner Account is an exact match when present; a null partner is not a tenant-wide wildcard in the current evaluator. Grade narrows applicability to an employee band, the effective dates bound the window, and Is Active is the final participation switch.
Design policy changes as versioned time windows rather than silently rewriting a rule that already influenced approved claims. Check for overlaps between global and grade-specific policies, verify that employee grade data is populated, and test boundary dates and each enforcement action with a representative draft claim. Deactivate a retired header only after its replacement is effective. That preserves the old policy and its violations as intelligible audit evidence while directing new claims to the current controls.
An expense policy is a named set of rules that can be evaluated against a claim. Each breach is recorded as a violation, and the evaluator returns isBlocked and requiresHigherApproval signals while applying any disallowed excess. Those signals affect submission or routing only when a business rule, action or approval entry consumes them; the policy service is not a universal gate by itself.
Which policies apply to a claim
A policy header carries an active flag, Partner Account, an optional grade, and an optional effective window. The current evaluator requires an exact partner-account match, including null-to-null; leaving Partner Account blank does not make a policy tenant-wide for claims that carry a partner. A blank grade applies across grades within that exact partner scope, while a populated grade must match the claimant's employee record. The claim date must fall inside the effective window.
What gets checked
Each rule names a rule type, an optional category scope (blank means every category), a threshold where the type needs one, and the action to take on breach. Line amounts are checked inclusive of tax.
| Check | Fires when | Typical action |
|---|---|---|
| Category limit | a line in the scoped category exceeds the threshold amount | Auto-disallow the excess |
| Grade hotel limit | a hotel line exceeds the cap set for the grade's policy | Auto-disallow or higher approval |
| Receipt mandatory above | a line over the threshold has no receipt attached | Hard block or warn |
| Blocked category | a line uses a category the policy forbids outright | Hard block |
| Late submission | a line's expense date is more than N days before the claim date | Warn or higher approval |
| Duplicate detection | same merchant, invoice number and amount appear on another line of this claim or on a prior claim by the same employee | Warn or hard block |
One check runs regardless of any policy: a deactivated category on a claim line is always a blocking violation, and posting refuses it too. Deactivating a category is how you retire it without touching history.
Duplicate detection skips lines with neither a merchant nor an invoice number — there is nothing reliable to match on — which is why claimants should fill both in.
What each action does
| Action | Effect | Hard or soft |
|---|---|---|
| Hard block | The evaluator returns isBlocked; the calling submission or approval flow must honor it | Hard only when wired |
| Auto-disallow | The excess is added to the line's disallowed amount; re-running evaluation can add it again | Mutating |
| Require higher approval | The evaluator returns requiresHigherApproval; routing must consume the signal | Extra sign-off only when wired |
| Warn | The violation is recorded, nothing else changes | Soft |
Every evaluation also sets a claim-level flag saying violations exist, so approvers and reports can filter for flagged claims without opening each one. Disallowed amounts and warnings stay on the claim permanently — approval does not erase them.
When evaluation runs
Evaluation runs on demand through Evaluate Policy, and organizations can wire it into submission or approval. The current implementation is not idempotent: it appends violation rows, does not clear earlier results, and increments disallowed amounts again on a repeat run. Do not re-evaluate the same unchanged claim casually. Test the single intended invocation path, and if a claim needs reevaluation, review and correct its prior violations and disallowed amounts under a controlled procedure first.
Common questions
What is the practical difference between a hard block and everything else?
A hard-block rule makes the evaluator return a blocked result; it stops the claim only if the submission or approval entry is wired to honor that result. Auto-disallow mutates the line, higher-approval returns a routing signal, and warn records a violation. Validate the consuming flow for every action in a test claim.
Who decides the caps for different seniority levels?
The policy author, by creating one policy per grade. The grade lives on the employee record, the policy header pins to a grade, and evaluation matches the claimant's grade to the right policy — the claimant never chooses which limits apply to them.
Does a warning stop reimbursement?
A warning records a violation. A hard block stops the claim only when the caller consumes isBlocked, and higher approval changes routing only when the approval flow consumes requiresHigherApproval; auto-disallow directly changes the disallowed amount.
Can a rule apply to just one category?
Yes — scope the rule to a category and it checks only lines in that category; leave the scope blank and it checks every line. A per-diem cap on Meals and a receipt threshold across the board coexist in the same policy.
