Fix execution-correctness bugs in RFQExecutionSaga#21
Open
devin-ai-integration[bot] wants to merge 1 commit into
Open
Fix execution-correctness bugs in RFQExecutionSaga#21devin-ai-integration[bot] wants to merge 1 commit into
devin-ai-integration[bot] wants to merge 1 commit into
Conversation
- Guard against zero/negative/null notional and price (validation was never enforced; negative amounts previously inflated inventory and credit) - Normalise monetary amounts to 2dp with explicit BigDecimal HALF_UP rounding - Harden Bond/Counterparty deduct/add to reject non-positive amounts so balances can never go negative (defends PATCH endpoints too) - Add InvalidAmountException and clearer ResourceNotFoundException messages - Add RFQExecutionSagaTest covering happy path, insufficient credit/notional, rollback-on-failure, rounding, zero/negative qty, unknown IDs Co-Authored-By: Achal Channarasappa <achal.channarasappa@cognition.ai>
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
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.
Summary
Audit + fix of
RFQExecutionSagaand its collaborators (Bond,Counterparty) for fixed-income execution-correctness bugs. The REST contract is unchanged../mvnw clean verifyis green: 16 tests pass (7 existing + 9 new).Bugs found & fixed
1. Zero/negative/null amounts were never rejected — they corrupted inventory & credit.
The
@Positiveconstraints onRfqDto.notionalAmount/executionPricewere never enforced becauseRfqController.createRfqhas no@Valid. Worse, the entity guard only checkedamount > available, so a negative amount passed the check andsubtract(negative)increased balances:Fix: the saga now validates both monetary inputs up front and throws a clear
InvalidAmountException(HTTP 400) for null/zero/negative values, failing fast before any mutation. As defense-in-depth,Bond/Counterpartydeduct*/add*also reject non-positive amounts, soavailableNotional/availableCreditcan never go negative even via thePATCHinventory/credit endpoints.2. Monetary math had no explicit rounding / scale normalization.
DB columns are
scale=2, but amounts were deducted in-memory at arbitrary precision, so the sufficiency check and the persisted value could disagree. Fix: amounts are normalized to 2 decimal places with explicitBigDecimal+RoundingMode.HALF_UPbefore being applied and stored. All money staysBigDecimal— nodoubleanywhere (verified).3. Atomicity of the two deductions — verified and locked in with a test.
Both
deductNotionalanddeductCreditalready run inside the single@Transactionalboundary, so they commit or roll back together. There was no test proving it; addedrollbackOnFailure_...which asserts that when credit is insufficient after notional was deducted, the bond'savailableNotionalis restored.4. Clearer domain exceptions for unknown IDs.
ResourceNotFoundExceptionnow carries a message ("Bond not found: <id>"/"Counterparty not found: <id>"); the no-arg constructor is retained for existing callers.New tests (
RFQExecutionSagaTest)happy path · insufficient notional (+state unchanged) · insufficient credit · rollback-on-failure · rounding (HALF_UP to cents, scale==2) · zero quantity · negative quantity (asserts inventory not inflated) · unknown bond · unknown counterparty.
Note: this test shares
IntegrationTest's context config (@AutoConfigureMockMvc) so Spring reuses one cached context and the seedCommandLineRunnerruns once against the shared in-memory DB (otherwise a second context re-seeds and hits a PK collision).Notes
master(repo's default/main branch; there is nomain).Link to Devin session: https://app.devin.ai/sessions/42802f33896449dca1fac83f9a6ffcfe
Requested by: @achalc
Devin Review