feat(fygaro): per-level daily top-up limits (L1 $125 / L2 $1000 / L3 $2500) - #482
Merged
Conversation
…$2500) Adds operator-tunable daily gross caps per account level to the Fygaro auto-credit gate, summed over a rolling 24h window from the ERPNext audit rows (Fiat Received + Completed, excluding the current delivery's own row). Over-cap and unknown-level payments record-only for manual review; a failed history read is transient (500) so the provider retries. Limits are exposed on globals.fygaroTopup so the app can cap the amount before the card is charged. Requires the matching frappe-flash-admin Fygaro Settings fields (l1/l2/l3_daily_limit) deployed and saved first — a settings row without them hard-stops auto-credit (fail closed), same as any malformed row.
- Filter the trailing-24h window on last_seen_at (written in UTC by this code) instead of Frappe's creation field, which is stored naive in the ERP site's configured time zone — a UTC-rendered cutoff against it shrank the window by the site's UTC offset, letting the full daily allowance recur every ~19h on a UTC-5 site. - Scope the sum to currency = USD: non-USD payments get Fiat Received audit rows carrying the raw foreign-currency amount, so a 5,000 JMD payment counted at face value would read as $5,000 of prior gross and wrongly lock the account out of auto-credit for a day. - Fail closed on a null row amount — Number(null) is 0, which silently under-counted instead of surfacing FygaroTopupHistoryQueryError. - Skip the ERPNext history read when the settings auto-credit kill switch is off or the payment is non-USD; gate ordering fails those on auto-credit-disabled/non-usd before the history gates, so the tightened guard saves a wasted list query per webhook without ever producing a false history-unavailable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nt7JxbX5W9o7viKegnXJPH
…view Covers the untested translation between the payment handler and the ErpNext history query: the fygaro: prefix on excludeRequestId (a broken prefix would double-count the payment's own audit row and silently halve the effective daily cap), the now-minus-24h since computation, and the fail-closed FygaroTopupHistoryQueryError when the ERPNext client is not configured. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nt7JxbX5W9o7viKegnXJPH
bobodread876
approved these changes
Aug 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds operator-tunable daily gross caps per account level to the Fygaro auto-credit gate:
evaluateCreditGate, evaluated afterover-limit: sums the account's captured Fygaro top-ups (Fiat Received + Completed, Cancelled excluded) over the trailing 24h from the ERPNext audit rows, excluding the current delivery's own row, and refuses auto-credit when gross + prior would exceed the level's cap (inclusive at the cap). Over-cap payments record-only with a reason-named ops alert and stay at Fiat Received for manual review.no-daily-limit-for-level.settings-unavailable: 500 so Fygaro retries — never coerced to "no history".ErpNext.sumFygaroTopupGrossCentsSince(fails closed on bad shape / non-numeric amounts,limit_page_length: 0so pagination can't under-count).globals.fygaroTopup(l1DailyLimit/l2DailyLimit/l3DailyLimit) so the app can cap the amount BEFORE the card is charged (companion PR in flash-mobile).Deploy order (matters)
l1/l2/l3_daily_limitto Fygaro Settings + a post-migrate patch seeding the defaults) — deploy via v-tag →make erp.Tests
fees.spec.ts: cap exceeded / exactly-at-cap inclusive / per-level selection / no-limit-for-level / history-unavailable / gate ordering.payment.spec.ts: record-only + alert fordaily-limit-exceededandno-daily-limit-for-level; 500-retry forhistory-unavailable; own-row exclusion; history read skipped when credit disabled or settings unavailable; at-cap credit path.ErpNext.spec.ts: filter/window/exclusion contract, cents summing, fail-closed paths.fygaro-settings.spec.ts+globals.spec.ts: field validation and exposure.Full unit suite: 183 suites / 1621 passed.
tsc-check+ eslint clean; public SDL + supergraph snapshots updated.🤖 Generated with Claude Code
https://claude.ai/code/session_01Nt7JxbX5W9o7viKegnXJPH