#912: CurrencyConversionServiceSupport.kt

projectforge-business/src/main/kotlin/org/projectforge/business/fibu/CurrencyConversionServiceSupport.kt Type: Internal Spring Service
Package: org.projectforge.business.fibu
Path: projectforge-business/src/main/kotlin/org/projectforge/business/fibu/CurrencyConversionServiceSupport.kt
Author: Kai Reinhard (k.reinhard@micromata.de) 304 lines · 183 code · 103 comments · 18 blank

Internal support class for currency conversion operations. Handles database persistence, validation, and access control. Marked internal — not part of the public API. CurrencyConversionService is the public-facing facade; this class performs the actual data operations and cache invalidation.

Architecture

Dependencies

DependencyRole
BaseDOPersistenceServiceGeneric insert/update/markAsDeleted/undelete operations
PfPersistenceServiceDirect JPA queries (named queries, find by id)
CurrencyPairDaoAccess control checks
CurrencyConversionCacheInvalidation after write operations

Key Methods

Query Methods

MethodDescription
findRate(id)Selects a rate by id; optionally checks user select access
selectAllRates(pair, deleted?)Uses named query FIND_ALL_BY_PAIR; optionally filters by deleted flag
getActiveRate(rates, date)Finds the active rate from a list by latest validFrom not after the given date

Validation

validate(rate) checks uniqueness via named queries:

If a matching deleted rate is found, it is returned to the caller for re-use (undelete + copy-from pattern). This allows users to re-create rates on dates that were previously active but soft-deleted.

CRUD with Deleted-Entry Reuse

Both insert() and updateRate() implement a special algorithm for handling soft-deleted entries:

  1. validate(rate) returns an existing deleted entry if one matches
  2. If a deleted match exists: the deleted entry's fields are copied from the new rate, then it's undeleted, and the new entry is discarded
  3. For updates: the existing record is marked deleted, and the previously-deleted matching record is undeleted and updated
  4. Cache is invalidated in a finally block

Save/Update and Delete Helpers

MethodDescription
saveOrUpdate(rate)Generic insert or update, invalidates cache
delete(rate)Soft-deletes a rate, invalidates cache
markRateAsDeleted(pair, rate)Full mark-delete flow: validate + markDeleted + cache invalidate
markRateAsDeleted(pairId, rateId)Convenience overload that resolves the pair by id
insert(pairId, rate)Insert with deferred-call pattern: resolve pair, then delegate
insert(pair, rate)Actual insert logic with validation and deleted-entry reuse
updateRate(pair, rate)Update with validation, access check, and deleted-entry reuse for date changes

Access Control

All mutating methods (insert, update, delete) check the logged-in user has the appropriate access right via currencyPairDao.checkLoggedInUser*Access(). The checkAccess parameter (defaulting to true) allows bypassing these checks for import/bulk operations.

Git History

868d6abb7 2025 -> 2026
b78da69bc BaseDao.baseDOChangedRegistry ist now private.
75ea9dc1a WIP: currency conversion with Claude Code.
07edc85de WIP: currency conversion with Claude Code.
bd69407de Initial revision with Claude Code.