Skip to content

Conversation

@gsayer
Copy link
Contributor

@gsayer gsayer commented Feb 9, 2026

Summary

  • Add a new GET /api/tenants/{tenantId}/payrolls/{payrollId}/lookups/ranges endpoint that returns lookup range brackets with computed upper bounds
  • Supports both Threshold (single matching bracket) and Progressive (multiple matching brackets) range modes
  • Exposes the range bracket computation logic already present in LookupSetExtensions but previously not accessible via the API

Motivation

Current lookup endpoints return either raw values (without computed bounds) or a single matched value. There is no way to retrieve the complete bracket structure (lower + upper bounds) through the API. This is needed for contribution preview in salary simulation case (For example, giving visibility of the social contribution threshold based on employee cases).

New endpoint

GET /api/tenants/{tid}/payrolls/{pid}/lookups/ranges
  ?lookupNames=X&lookupNames=Y    (required)
  &rangeValue=7200.00              (optional — filters matching bracket(s))
  &regulationDate=...              (optional)
  &evaluationDate=...              (optional)
  &culture=fr-CH                   (optional)

Returns LookupRangeResult[] with allBrackets, matchingBracket (threshold), matchingBrackets (progressive).

Changes

Layer Files Description
Domain.Model LookupRangeBracket.cs, LookupRangeResult.cs, LookupSetExtensions.cs New POCOs + BuildRangeBrackets() method
Api.Model LookupRangeBracket.cs, LookupRangeResult.cs API DTOs
Api.Map LookupRangeBracketMap.cs, LookupRangeResultMap.cs Mapperly mappers
Api.Controller PayrollController.cs Internal controller with business logic
Backend.Controller PayrollController.cs Public route [HttpGet("{payrollId}/lookups/ranges")]

Test plan

  • dotnet build passes with TreatWarningsAsErrors
  • dotnet test passes
  • E2E tested via Docker Compose (SQL Server 2022 + backend):
    • Threshold lookup: single matchingBracket returned for a given rangeValue
    • Progressive lookup: all applicable matchingBrackets returned
    • Upper bounds correctly computed from next bracket's lower bound (+ rangeSize for last bracket)
    • Error handling: 400 for unknown lookup names, 400 for missing lookupNames

… with computed upper bounds

Added LookupRangeBracket and LookupRangeResult POCOs, BuildRangeBrackets extension method on LookupSet, API DTOs, Mapperly mappers, and payroll controller endpoint at {payrollId}/lookups/ranges supporting threshold and progressive range modes with optional range value matching. Updated swagger.json with new path and component schemas.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gsayer gsayer force-pushed the feature/lookup-ranges-endpoint branch from 2a07b3b to 8fd72be Compare February 9, 2026 17:57
@gsayer gsayer changed the title VR-181: GET /lookups/ranges endpoint Add GET /lookups/ranges endpoint for lookup range brackets Feb 9, 2026
@gsayer gsayer marked this pull request as draft February 9, 2026 21:41
@Giannoudis
Copy link
Contributor

@gsayer Thank you for this useful extension. There are two conceptual points that we should consider:

Closed value ranges

Currently, the UpperBound value in LookupRangeBracket can be null for the last bracket. Using the type becomes easier if the value range is always defined. The last bracket should have Decimal.MaxValue as its upper limit.

Action

Change the value of LookupRangeBracket.UpperBound from decimal? to decimal and set it to Decimal.MaxValue instead of null.

Unique lookup bracket

The result should be that I get one bracket for each range value only. Currently, the UpperBound of one bracket has the same value as the LowerBound of the next one.

Action

The UpperBound of each bracket should be the next smallest LowerBound value. This value must be calculated based on the decimal precision.

var precision = (decimal)Math.Pow(10, -SystemSpecification.DecimalScale);
currentBracket.UpperBound = nextBracket.LowerBound - precision;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants