Skip to content

Commit 10ba0a7

Browse files
tastybentoclaude
andcommitted
Address PR #66 review: localize latest-transaction placeholder, harden history parsing
- PhManager: the _latest_transaction placeholder now localizes transaction type names via the existing bank.statement.* locale keys (reused from StatementTab) instead of returning hardcoded English. User is threaded through formatTransaction/getTxTypeDisplay. - BankManager: extract shared parseEntry() helper so getHistory() and getLatestHistory() parse stored entries identically. getLatestHistory no longer casts the history Map to NavigableMap — that cast risked a ClassCastException when Gson deserializes the map from the database into a non-TreeMap; instead find the latest key via Collections.max. - PhManagerTest: stub user.getTranslation for the statement keys and assert on the localized output. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 9ef07aa commit 10ba0a7

3 files changed

Lines changed: 54 additions & 43 deletions

File tree

src/main/java/world/bentobox/bank/BankManager.java

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -318,19 +318,31 @@ public List<AccountHistory> getHistory(Island island) {
318318
BankAccounts account = getAccount(island.getUniqueId());
319319
// Calculate interest
320320
this.getBalancePlusInterest(account);
321-
return account.getHistory().entrySet().stream().map(en -> {
322-
String[] split = en.getValue().split(":");
323-
if (split.length == 3) {
324-
TxType type = Enums.getIfPresent(TxType.class, split[1]).or(TxType.UNKNOWN);
325-
return new AccountHistory(en.getKey(), split[0], Double.parseDouble(split[2]), type);
326-
}
327-
return null;
328-
}).filter(Objects::nonNull).toList();
321+
return account.getHistory().entrySet().stream().map(en -> parseEntry(en.getKey(), en.getValue()))
322+
.filter(Objects::nonNull).toList();
329323
} catch (IOException e) {
330324
return Collections.emptyList();
331325
}
332326
}
333327

328+
/**
329+
* Parse a single stored history entry ({@code name:type:amount}) into an {@link AccountHistory}.
330+
* @param key - timestamp key
331+
* @param value - stored value
332+
* @return parsed {@link AccountHistory} or null if the value is malformed
333+
*/
334+
private AccountHistory parseEntry(Long key, String value) {
335+
if (value == null) return null;
336+
String[] split = value.split(":");
337+
if (split.length != 3) return null;
338+
TxType type = Enums.getIfPresent(TxType.class, split[1]).or(TxType.UNKNOWN);
339+
try {
340+
return new AccountHistory(key, split[0], Double.parseDouble(split[2]), type);
341+
} catch (NumberFormatException e) {
342+
return null;
343+
}
344+
}
345+
334346
/**
335347
* Get the latest transaction history entry for an island
336348
* @param island - island
@@ -343,24 +355,12 @@ public AccountHistory getLatestHistory(Island island) {
343355
// Keep behavior consistent with getHistory(): apply interest before reading history
344356
this.getBalancePlusInterest(account);
345357

358+
// Find the most recent entry by timestamp key. Don't assume the concrete Map type:
359+
// when loaded from the database Gson may not preserve the TreeMap, so avoid casting to NavigableMap.
346360
Map<Long, String> history = account.getHistory();
347361
if (history.isEmpty()) return null;
348-
349-
java.util.Map.Entry<Long, String> latest = ((java.util.NavigableMap<Long, String>) history).lastEntry();
350-
if (latest == null || latest.getValue() == null) return null;
351-
352-
Long latestKey = latest.getKey();
353-
String value = latest.getValue();
354-
355-
String[] split = value.split(":", 3);
356-
if (split.length != 3) return null;
357-
358-
TxType type = Enums.getIfPresent(TxType.class, split[1]).or(TxType.UNKNOWN);
359-
try {
360-
return new AccountHistory(latestKey, split[0], Double.parseDouble(split[2]), type);
361-
} catch (NumberFormatException e) {
362-
return null;
363-
}
362+
Long latestKey = Collections.max(history.keySet());
363+
return parseEntry(latestKey, history.get(latestKey));
364364
} catch (IOException e) {
365365
return null;
366366
}

src/main/java/world/bentobox/bank/PhManager.java

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -128,37 +128,38 @@ String getLatestTransaction(User user, World world) {
128128
if (user == null || !user.isPlayer() || world == null) return "";
129129
Island island = addon.getIslands().getIsland(world, user);
130130
if (island == null) return "";
131-
return formatTransaction(bankManager.getLatestHistory(island));
131+
return formatTransaction(user, bankManager.getLatestHistory(island));
132132
}
133133

134134
/**
135135
* Format an AccountHistory entry as "[Name] [TxType] [Amount]"
136+
* @param user - user, used to localise the transaction type
136137
* @param history - the account history entry
137138
* @return formatted string or empty string if null
138139
*/
139-
private String formatTransaction(AccountHistory history) {
140+
private String formatTransaction(User user, AccountHistory history) {
140141
if (history == null) return "";
141-
return history.getName() + " " + getTxTypeDisplay(history.getType()) + " " + addon.getVault().format(history.getAmount());
142+
return history.getName() + " " + getTxTypeDisplay(user, history.getType()) + " " + addon.getVault().format(history.getAmount());
142143
}
143144

144145
/**
145-
* Get display-friendly name for transaction type
146+
* Get the localised, display-friendly name for a transaction type. Reuses the
147+
* same {@code bank.statement.*} locale keys as the statement panel.
148+
* @param user - user whose locale is used
146149
* @param type - transaction type
147-
* @return display name
150+
* @return localised display name
148151
*/
149-
private String getTxTypeDisplay(TxType type) {
150-
if (type == null) {
151-
return "Unknown";
152-
}
153-
return switch (type) {
154-
case DEPOSIT -> "Deposited";
155-
case WITHDRAW -> "Withdrew";
156-
case GIVE -> "Received";
157-
case TAKE -> "Lost";
158-
case SET -> "Set";
159-
case INTEREST -> "Earned";
160-
default -> "Unknown";
152+
private String getTxTypeDisplay(User user, TxType type) {
153+
String key = switch (type == null ? TxType.UNKNOWN : type) {
154+
case DEPOSIT -> "deposit";
155+
case WITHDRAW -> "withdrawal";
156+
case GIVE -> "give";
157+
case TAKE -> "take";
158+
case SET -> "set";
159+
case INTEREST -> "interest";
160+
default -> "unknown";
161161
};
162+
return user.getTranslation("bank.statement." + key);
162163
}
163164

164165
/**

src/test/java/world/bentobox/bank/PhManagerTest.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,16 @@ public void setUp() {
106106
when(plm.getName(any())).thenAnswer(arg -> arg.getArgument(0, UUID.class).toString());
107107
when(user.isPlayer()).thenReturn(true);
108108
when(im.getIsland(any(World.class), any(User.class))).thenReturn(island);
109+
// Localised transaction type names (see bank.statement.* in the locale files)
110+
when(user.getTranslation(anyString())).thenAnswer(arg -> switch (arg.getArgument(0, String.class)) {
111+
case "bank.statement.deposit" -> "Deposit";
112+
case "bank.statement.withdrawal" -> "Withdrawal";
113+
case "bank.statement.interest" -> "Interest";
114+
case "bank.statement.give" -> "Admin Give";
115+
case "bank.statement.take" -> "Admin Take";
116+
case "bank.statement.set" -> "Admin Set";
117+
default -> "Unknown Type";
118+
});
109119
pm = new PhManager(addon, bm);
110120
}
111121

@@ -312,7 +322,7 @@ void testCheckCacheOutOfBounds() {
312322
void testGetLatestTransactionDeposit() {
313323
AccountHistory ah = new AccountHistory(System.currentTimeMillis(), "tastybento", 500.0, TxType.DEPOSIT);
314324
when(bm.getLatestHistory(eq(island))).thenReturn(ah);
315-
assertEquals("tastybento Deposited $500.0", pm.getLatestTransaction(user, world));
325+
assertEquals("tastybento Deposit $500.0", pm.getLatestTransaction(user, world));
316326
}
317327

318328
/**
@@ -322,7 +332,7 @@ void testGetLatestTransactionDeposit() {
322332
void testGetLatestTransactionWithdraw() {
323333
AccountHistory ah = new AccountHistory(System.currentTimeMillis(), "tastybento", 200.0, TxType.WITHDRAW);
324334
when(bm.getLatestHistory(eq(island))).thenReturn(ah);
325-
assertEquals("tastybento Withdrew $200.0", pm.getLatestTransaction(user, world));
335+
assertEquals("tastybento Withdrawal $200.0", pm.getLatestTransaction(user, world));
326336
}
327337

328338
/**

0 commit comments

Comments
 (0)