feat: add volume commitment feature and analytics - #375
Open
GauravRawat369 wants to merge 9 commits into
Open
Conversation
…ng-rule machinery Adds a typed DSL for expressing enterprise volume-commitment contracts (PSP volume/GMV goals with lumpsum or tiered rebates) and stores it via the existing euclid rule engine — no new tables, endpoints, or handlers: - New StaticRoutingAlgorithm::VolumeContract variant carrying a VolumeContractConfig document (new src/euclid/volume_contract.rs), and a dedicated AlgorithmType::VolumeCommitment activation slot; the pairing is enforced by validate_routing_rule in both directions. - Archetypes: lumpsum (A) and tiered (C) writable; min_commitment (B) parses — wire format frozen for forward compatibility — but is gated off by validation. A reserved per-contract `scope` field will later take euclid Comparison conditions for payment-cluster scoping. - Write-time canonicalization: amounts accepted as integers or decimal strings in major/minor units and stored as integer minor currency units; tolerance accepted as "5pp"/"550bps"/bps and stored as bps. Unknown fields are rejected (manual Deserialize around serde-flatten), timezones validated against the IANA database (chrono-tz). - /routing/update now canonicalizes and runs the same validation as create (previously updates were stored unvalidated). Hot-path scoping fixes this feature depends on (pre-existing bugs for payout/3DS rows): the /routing/evaluate mapper lookup and the activate-time Redis cache write are now payment-scoped, so a merchant's non-payment mapper rows can neither shadow nor poison live payment routing; load_active_ab_test gets the same mapper filter. The ab_test evaluator/preview reject volume-contract arms explicitly. Covered by unit tests (serde round-trips, canonicalization, validation catalog, slot pairing) and a Playwright API spec including the isolation regression: activating a volume contract leaves same-merchant /routing/evaluate untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… the volume-contract DSL Shapes the DSL to what the routing engine consumes, still storing raw contract facts only — no derived values (goals, rewards, period-end dates, fractions) are computed or persisted; resolution stays the engine's job: - Merchant level: expected_daily_traffic (required, canonicalized like every other amount), and optional forecast_interval_secs / steering_interval_secs overrides (omit = engine's global default). - One metric and one currency per document: metric and currency move from per-contract to the document root, since the engine has no concept of currencies and compares expected_daily_traffic against per-PSP goals in a single unit. Per-connector uniqueness of active contracts follows (the (connector, metric) pair rule is gone). - Tiered contracts mark exactly one tier `targeted: true` (validated; must be a retroactive tier — a marginal tier's reward at its own threshold is zero), so the engine can read one (goal, reward) per PSP without interpreting the ladder. Wire-format change is safe: schema_version 1 has never been stored (same unmerged PR). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds a Volume Contracts page (Routing section of the sidebar, beta badge) for configuring volume-commitment contract documents through the existing /routing/* endpoints with algorithm_for: volume_commitment: - Builder covering the whole DSL: routing mode, tolerance (pp), metric, currency + amount units, expected daily traffic, optional forecast/steering interval overrides, and per-PSP contracts with lumpsum (target + flat/percentage reward) and tiered (rebate ladder with a single targeted retroactive tier, enforced in the form) archetypes, billing cycle + IANA timezone. - Document list with active badge, expandable stored-JSON view, and the activate/deactivate/delete lifecycle with confirm dialogs, mirroring the Rule-Based page's patterns (SWR + POST fetchers, cache revalidation, permission gating via routing:write). - Reuses the existing UI kit (Card/InsetPanel/Button/Badge/Combobox/ SearchableSelect/ConfirmDialog/typography) so the page matches the rest of the dashboard. - types/api.ts: VolumeContractConfig types + volume_contract in the algorithm type unions. - EuclidRulesPage now excludes volume_contract documents from its rules list (they live on their own page). Verified against a local backend: create canonicalizes (5pp -> 500 bps, major -> minor units), activate/deactivate round-trips, tsc + vite build green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SearchableSelect's compact cond-select trigger (built for the dense Euclid condition builder) and unstyled Combobox inputs looked cramped next to the regular form fields. SearchableSelect gains an opt-in triggerClassName prop that swaps the compact trigger for full input styling (block-level, no 10rem label truncation); existing call sites are untouched. The volume contracts page passes its shared input class to every dropdown so selects, comboboxes and text inputs render at identical height, padding and type size. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
added 4 commits
August 27, 2026 17:17
… add-volume-contracts-based-routing # Conflicts: # src/euclid/handlers/routing_rules.rs # website/dist/decision-engine/index.html # website/dist/index.html # website/src/App.tsx # website/src/components/pages/AnalyticsPage.tsx # website/src/components/ui/SearchableSelect.tsx
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.
This pull request introduces a new volume commitment scheduling system and related API endpoints, along with several supporting changes and improvements. The main focus is on adding a scheduler that periodically forecasts merchant volume commitments, exposes a dedicated server for scheduling, and integrates this functionality into the main application. Additional changes include enhancements to analytics, new API routes, and CI workflow optimizations.
Volume Commitment Scheduling and API Integration:
[volume_commitment]section inconfig/development.tomlto configure the scheduler, including enabling/disabling the feature, scheduling intervals, and dedicated server settings.src/bin/open_router.rs, ensuring it shares state with the main server. [1] [2]GlobalConfigto includeVolumeCommitmentConfigfor centralized configuration management.New and Updated API Endpoints:
/merchant-account/:merchant-id/volume-commitment(including/series,/audit,/impact), and a scheduler callback at/volume-commitment/run-forecast./routing/evaluate/batch.Analytics and Flow Types:
FlowType::VolumeCommitmentForecastto track forecast runs and updated its string representation. [1] [2]PAYMENT_AMOUNT_EXPRinsrc/analytics/clickhouse/common.rsand updated its usage in cost savings metrics. [1] [2]CI/CD and Build Improvements:
changesjob and path filters. [1] [2]rdkafkain the push CI workflow to ensure successful builds.Documentation: