Skip to content

Implement SELL flow for crypto-trading test app with comprehensive tests and fix BigDecimal serialization#207

Merged
jwijgerd merged 12 commits into
mainfrom
copilot/add-sell-flow-logic
Dec 31, 2025
Merged

Implement SELL flow for crypto-trading test app with comprehensive tests and fix BigDecimal serialization#207
jwijgerd merged 12 commits into
mainfrom
copilot/add-sell-flow-logic

Conversation

Copilot AI commented Dec 27, 2025

Copy link
Copy Markdown
Contributor

Implementation Plan: SELL Flow for Crypto Trading

Analysis Complete

  • Analyzed existing BUY flow structure
  • Identified all components that need SELL equivalents

Components Created

Aggregates Module

  • Create PlaceSellOrderCommand (command) - ✅ Uses quantity parameter
  • Create FillSellOrderCommand (command)
  • Create SellOrderCreatedEvent (event) - ✅ Uses quantity field
  • Create SellOrderPlacedEvent (event) - ✅ Uses quantity field
  • Create SellOrderFilledEvent (event)
  • Create SellOrderRejectedEvent (event)
  • Create SellOrderProcess (process manager) - ✅ Has both size and amount fields
  • Update OrderProcess interface - ✅ Keeps amount() method
  • Update OrderProcessManager to handle SELL flow
  • Keep BuyOrderProcess with amount field

Commands Module

  • Create SellOrderInput DTO - ✅ Uses quantity field
  • Update OrdersCommandController to add /sell endpoint

Queries Module

  • Update OrdersQueryModelState to include SellOrder record
  • Update OrdersQueryModel to handle SELL events
  • Update OrdersQueryController to query both buy and sell orders

Testing & Validation

  • Build successful - All modules compiled without errors
  • All existing tests passing
  • 6 new tests added for SELL order flow
  • BigDecimal serialization using framework's serializer

API Changes - BigDecimal Serialization

Problem: Using doubles for financial values is dangerous due to floating-point precision issues.

Solution: Use framework's org.elasticsoftware.akces.serialization.BigDecimalSerializer instead of Jackson's ToStringSerializer:

Files Updated:

  • BalanceOutput - amount, balance fields
  • OrderOutput - size, amount fields
  • OrdersQueryModelState.BuyOrder - amount field
  • OrdersQueryModelState.SellOrder - quantity field
  • WalletQueryModelState.Balance - amount, reservedAmount fields

Benefits:

  • Uses framework's consistent serialization approach
  • Serializes using toPlainString() for exact decimal representation
  • Maintains financial precision throughout the API layer
  • Follows framework conventions and patterns
Original prompt

On crypto-trading, based on the current BUY flow logic in the crypto-trading test app, create the SELL flow. Including the Commands, DomainEvents and RESTful ApIs in the commands and queries modules


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Co-authored-by: jwijgerd <914840+jwijgerd@users.noreply.github.com>
Copilot AI changed the title [WIP] Add sell flow logic to crypto-trading app Implement SELL flow for crypto-trading test app Dec 27, 2025
Copilot AI requested a review from jwijgerd December 27, 2025 12:51

@jwijgerd jwijgerd left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot implement the change request

public record PlaceSellOrderCommand(
@NotNull @AggregateIdentifier String userId,
@NotNull CryptoMarket market,
@NotNull BigDecimal amount,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this parameter should be named quantity. This change should be reflected in all classes

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated all SELL flow classes to use quantity instead of amount. Also updated the OrderProcess interface and BuyOrderProcess to maintain consistency. Changes applied in commit e585487.

… interface

Co-authored-by: jwijgerd <914840+jwijgerd@users.noreply.github.com>
@jwijgerd
jwijgerd marked this pull request as ready for review December 31, 2025 09:35

Copilot AI commented Dec 31, 2025

Copy link
Copy Markdown
Contributor Author

@copilot implement the change request

Change request implemented. Renamed the amount parameter to quantity throughout the SELL flow in all affected classes (commands, events, processes, DTOs, query models, and handlers). Also updated the OrderProcess interface and BuyOrderProcess for consistency. All tests passing. See commit e585487.

@jwijgerd jwijgerd left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot fix the BuyOrderProcess and related classes to keep using amount

public BuyOrderProcess(String orderId,
CryptoMarket market,
BigDecimal amount,
BigDecimal quantity,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BuyOrderProcess should not be changed, here we should keep using amount. A Buy order is always specified in the monetary value while a Sell order is always specified in the quantity

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted BuyOrderProcess to use amount field for monetary value. SellOrderProcess now uses size field to store quantity and implements amount() method to return size. Changes in commit 245527c.

@Override
public OrderProcess withState(OrderProcessState state) {
return new BuyOrderProcess(orderId(), market, size(), amount(), clientReference(), state);
return new BuyOrderProcess(orderId(), market, size(), quantity(), clientReference(), state);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keep using amount

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 245527c - withState() now uses amount() as before.

BigDecimal size();

BigDecimal amount();
BigDecimal quantity();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keep using amount. For the Sell order process use size (which is identical to quantity)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted to amount() method. SellOrderProcess implements this by returning size field. Changes in commit 245527c.

…ize' implementing amount()

Co-authored-by: jwijgerd <914840+jwijgerd@users.noreply.github.com>

Copilot AI commented Dec 31, 2025

Copy link
Copy Markdown
Contributor Author

@copilot fix the BuyOrderProcess and related classes to keep using amount

Fixed. BuyOrderProcess now uses amount (monetary value), SellOrderProcess uses size (quantity) and implements amount() to return size. OrderProcess interface keeps amount() method. All tests passing. See commit 245527c.

public record SellOrderProcess(
String orderId,
CryptoMarket market,
BigDecimal size,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keep size and amount properties like in the BuyOrderProcess but set the amount to null in the constructor

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added amount field to SellOrderProcess record. Constructor now sets size to quantity and amount to null, matching BuyOrderProcess structure. Changes in commit 98bab9f.

Co-authored-by: jwijgerd <914840+jwijgerd@users.noreply.github.com>
@jwijgerd

Copy link
Copy Markdown
Contributor

@copilot the code looks good, now also add tests for the sell order flow in the various modules. Also add a E2E sell order flow test, even though you cannot run it yourself

Co-authored-by: jwijgerd <914840+jwijgerd@users.noreply.github.com>

Copilot AI commented Dec 31, 2025

Copy link
Copy Markdown
Contributor Author

@copilot the code looks good, now also add tests for the sell order flow in the various modules. Also add a E2E sell order flow test, even though you cannot run it yourself

Added comprehensive tests for SELL order flow in commit a8588f2:

Queries Module (CryptoTradingQueryApiTest.java):

  • testPlaceSellOrder() - Tests placing a sell order with BTC
  • testGetOpenSellOrders() - Tests retrieving multiple sell orders

Commands Module (CryptoTradingCommandApiTest.java):

  • testPlaceSellOrder() - Tests sell order creation via REST API
  • testSellOrderWithInsufficientBalance() - Tests edge case with insufficient crypto balance

Aggregates Module (CryptoTradingApplicationTest.java):

  • testSellOrderFlow() - Tests sell order processing at aggregate level

E2E Tests (CryptoTradingE2ETests.java):

  • testSellCrypto() - Complete E2E test for selling BTC for EUR
  • waitForSellOrderTerminalState() - Helper method to wait for order completion

All tests follow the same patterns as existing BUY order tests and compile successfully.

Co-authored-by: jwijgerd <914840+jwijgerd@users.noreply.github.com>
Copilot AI changed the title Implement SELL flow for crypto-trading test app Implement SELL flow for crypto-trading test app with comprehensive tests Dec 31, 2025

@jwijgerd jwijgerd left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot change the test to test for a String instead of a double and ensure we always return Strings for BigDecimals in the API

.jsonPath("$.openSellOrders.length()").isEqualTo(2)
.jsonPath("$.openSellOrders[0].orderId").exists()
.jsonPath("$.openSellOrders[0].market.id").isEqualTo("BTC-EUR")
.jsonPath("$.openSellOrders[0].quantity").isEqualTo(0.5)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the quantity should be a String ("0.5") and not a double. using doubles is dangerous in financial applications. Change to String and fix any code that fails due to this test

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 42539d6. All BigDecimal fields in DTOs now serialize as Strings using @JsonSerialize(using = ToStringSerializer.class). Updated all tests to expect String values instead of doubles (e.g., "0.5" instead of 0.5).

Co-authored-by: jwijgerd <914840+jwijgerd@users.noreply.github.com>

Copilot AI commented Dec 31, 2025

Copy link
Copy Markdown
Contributor Author

@copilot change the test to test for a String instead of a double and ensure we always return Strings for BigDecimals in the API

Implemented in commit 42539d6. Added @JsonSerialize(using = ToStringSerializer.class) to all BigDecimal fields across:

  • OrderOutput (size, amount)
  • BalanceOutput (amount, balance)
  • OrdersQueryModelState records (amount, quantity)
  • WalletQueryModelState.Balance (amount, reservedAmount)

All tests updated to compare String representations, ensuring financial precision is maintained.

Copilot AI changed the title Implement SELL flow for crypto-trading test app with comprehensive tests Implement SELL flow for crypto-trading test app with comprehensive tests and fix BigDecimal serialization Dec 31, 2025

public record BalanceOutput(String id,
String currency,
@JsonSerialize(using = ToStringSerializer.class)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use org.elasticsoftware.akces.serialization.BigDecimalSerializer

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in commit be5ccb2. Replaced ToStringSerializer with org.elasticsoftware.akces.serialization.BigDecimalSerializer across all DTOs and query model states (BalanceOutput, OrderOutput, OrdersQueryModelState, WalletQueryModelState).

Co-authored-by: jwijgerd <914840+jwijgerd@users.noreply.github.com>
@jwijgerd
jwijgerd merged commit 07d6cf1 into main Dec 31, 2025
5 checks passed
@jwijgerd
jwijgerd deleted the copilot/add-sell-flow-logic branch December 31, 2025 13:47
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