Skip to content

Conversation

@knightjoel
Copy link

When entering a batch of historical transactions (catching up on buys, sells, dividends, etc.), the date picker requires multiple clicks to navigate back to the correct month for each transaction. This change remembers the last entered transaction date and uses it as the default, eliminating repeated month navigation when entering transactions from the same period.

Changes

  • Add date memory to PresetValues (follows existing timePreset pattern)
  • Change transaction models to use PresetValues.getLastTransactionDate()
  • Capture date after applyChanges() in AbstractTransactionDialog
  • Reset date memory in ClientInput.setClient() when switching files
  • Add unit tests for date memory functionality

Behavior

  • Memory is session-scoped (clears on app restart)
  • Dates older than 1 year fall back to current date
  • Cancelled dialogs don't update the remembered date
  • Works across all transaction types

Testing

  • 9 unit tests added in PresetValuesTest
  • All existing tests pass

Co-authored-by: Claude Code [email protected]

Implement session-scoped memory for last entered transaction date to
support remembering the date from the most recently entered transaction.
This enables users to enter multiple historical transactions without
manually adjusting the date field each time.

Changes:
- Add lastTransactionDate static field to store the date in memory
- Add getLastTransactionDate() method with 1-year age guard to prevent
  accidental entry of transactions way in the past
- Add setLastTransactionDate() method to update the stored date
- Add resetLastTransactionDate() method to clear the stored date
- Follow existing timePreset pattern for consistency

The 1-year age limit ensures that if a stored date is older than one
year, the method returns the current date instead. This prevents users
from accidentally creating new transactions with very old dates after
the remembered date has become stale.
Change AbstractSecurityTransactionModel to initialize the date field
with PresetValues.getLastTransactionDate() instead of LocalDate.now().
This allows security transaction dialogs (BUY, SELL, DELIVERY_INBOUND,
DELIVERY_OUTBOUND) to default to the last entered transaction date,
enabling users to enter multiple transactions without manually adjusting
the date each time.

The date will automatically fall back to the current date if no date has
been stored yet or if the stored date is more than 1 year old.
Change AccountTransactionModel to initialize the date field with
PresetValues.getLastTransactionDate() instead of LocalDate.now().
This allows account transaction dialogs (DIVIDENDS, DEPOSITS, REMOVALS,
INTEREST, FEES, TAXES, etc.) to default to the last entered transaction
date, enabling users to enter multiple transactions without manually
adjusting the date each time.

The date will automatically fall back to the current date if no date has
been stored yet or if the stored date is more than 1 year old.
Add logic to AbstractTransactionDialog to capture and store the
transaction date after successful saves. This completes the feedback
loop for the date memory feature.

Changes:
- In okPressed(): Store date after applyChanges() for Save button
- In buttonPressed(): Store date after applyChanges() for Save & New button

The date is captured AFTER applyChanges() to ensure the transaction was
successfully saved. This enables the workflow where users can enter
multiple historical transactions and each subsequent dialog defaults to
the date from the previously saved transaction.
Add reset logic to ClientInput.setClient() to clear the remembered
transaction date when a new portfolio file is loaded. This prevents
dates from one portfolio file being used as defaults in a different
portfolio file.

The reset is called every time a client is loaded, which includes both
the initial file open and when switching between files. This ensures
that each portfolio file starts with a clean slate, defaulting to the
current date until a transaction is saved within that file.
Create comprehensive test suite for the last transaction date memory
functionality in PresetValues. Tests cover all core scenarios including
basic get/set operations, the 1-year age limit, reset functionality,
and edge cases around the age boundary.

Test coverage:
- Default behavior when no date is stored
- Set and get round-trip operations
- Date exactly 1 year old (boundary case - should be retained)
- Date older than 1 year (should return current date)
- Reset functionality clears stored date
- Multiple set/get cycles (ensures overwriting works)
- Recent dates are retained
- Edge cases: 1 year ± 1 day around the age limit boundary
  Fixes compilation error where AbstractTransactionDialog calls getDate()
  on AbstractModel. All transaction model subclasses now implement this
  method, with InvestmentPlanModel returning its 'start' date.

  Fixes issue introduced in 'Capture transaction date on save' commit.
Changed from isAfter() to !isBefore() to correctly include dates that
are exactly 1 year old.
Changed test dates from hardcoded 2024 dates to relative dates using
LocalDate.now().minusMonths(). This prevents tests from failing as
time passes and ensures they continue testing the 1-year boundary
logic correctly.
Replace fully qualified class name with proper import statement in
ClientInput.java, following project convention to "add import instead
of qualified name".
@buchen
Copy link
Member

buchen commented Nov 22, 2025

Hi @knightjoel,

thanks for the contribution. I get the idea: when entering multiple older transactions, it is cumbersome to pick the older date again and again.

Some observations on the proposed change:

The reset is called every time a client is loaded, which includes both
the initial file open and when switching between files. This ensures
that each portfolio file starts with a clean slate, defaulting to the
current date until a transaction is saved within that file.

The second part "when switching between files" is definitely not the case. There is no event if the users switches between two open files. In fact, the user could arrange the windows to both files next to each other. I do not think that is a problem - the comment in the commit is just not correct.

Then: I understand the "guard" with dates older than 1 year. But isn't that contradicting the goal of this change? Say I start entering my historical transactions, then the date is reverted back to today.

An alternative strategy could be: if the date was entered within the last 15 minutes, then we preset the dialog with the last date. If the date was entered more than 15 minutes, then today is used.

However, in both cases I wonder if the user experience is "predictable" for the user. Neither the "1 year rule" nor the "15 minute rule" is something that the user can derive on its own. Any thoughts?

@knightjoel
Copy link
Author

The reset is called every time a client is loaded, which includes both
the initial file open and when switching between files. This ensures
that each portfolio file starts with a clean slate, defaulting to the
current date until a transaction is saved within that file.

The second part "when switching between files" is definitely not the case. There is no event if the users switches between two open files. In fact, the user could arrange the windows to both files next to each other. I do not think that is a problem - the comment in the commit is just not correct.

Ah, thank you for pointing that out. I was thinking about this as closing and then opening a new file. Let me try this feature with multiple files. It feels like this won't play well if someone closes one file they have open and then enter transactions in another file that's already open.

Then: I understand the "guard" with dates older than 1 year. But isn't that contradicting the goal of this change? Say I start entering my historical transactions, then the date is reverted back to today.

An alternative strategy could be: if the date was entered within the last 15 minutes, then we preset the dialog with the last date. If the date was entered more than 15 minutes, then today is used.

However, in both cases I wonder if the user experience is "predictable" for the user. Neither the "1 year rule" nor the "15 minute rule" is something that the user can derive on its own. Any thoughts?

I'm glad you commented on this. I'm also unsure if this bit makes sense. I'm leaning more to removing any guard: the user knows best about the data they're entering.

I'll iterate this and push some changes.

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

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants