feat: persist splitMode/splitPercentage and list defaultSplitPercentage

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-07 21:55:55 +02:00
parent 7fd7882188
commit da0cf48dc3
7 changed files with 54 additions and 0 deletions
@@ -6,6 +6,8 @@ import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonBackReference;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@@ -36,6 +38,12 @@ public class Expense {
private Double personalUseAmount;
private Double otherPersonAmount;
private String category;
@Enumerated(EnumType.STRING)
private SplitMode splitMode;
private Integer splitPercentage;
private LocalDate date;
private LocalDateTime lastModified;
@@ -33,6 +33,9 @@ public class ExpenseChangeRequest {
private Double personalUseAmount;
private Double otherPersonAmount;
private SplitMode splitMode;
private Integer splitPercentage;
@NotNull(message = "Date is required")
private LocalDate date;
@@ -55,6 +58,8 @@ public class ExpenseChangeRequest {
// The edit dialog sends "" for a missing category; store null so the
// stub state stays uniform and history diffs don't report null -> "".
expense.setCategory(category == null || category.isBlank() ? null : category);
expense.setSplitMode(splitMode == null ? SplitMode.DETAILED : splitMode);
expense.setSplitPercentage(splitPercentage);
return expense;
}
@@ -33,6 +33,9 @@ public class ExpenseInput {
private Double personalUseAmount;
private Double otherPersonAmount;
private SplitMode splitMode;
private Integer splitPercentage;
@NotNull(message = "Date is required")
private LocalDate date;
@@ -56,6 +59,8 @@ public class ExpenseInput {
expense.setOwner(appUser);
expense.setTitle(title);
expense.setCategory(category);
expense.setSplitMode(splitMode == null ? SplitMode.DETAILED : splitMode);
expense.setSplitPercentage(splitPercentage);
return expense;
}
@@ -31,6 +31,8 @@ public class ExpenseList {
private String name;
private Integer defaultSplitPercentage = 50;
private String inviteCode;
@JsonIgnore
private LocalDateTime inviteCodeExpiration;
@@ -0,0 +1,6 @@
package de.zendric.app.xpensely_server.model;
public enum SplitMode {
DETAILED,
PERCENTAGE
}
@@ -137,6 +137,8 @@ public class ExpenseListService {
existingExpense.setDate(updatedExpense.getDate());
existingExpense.setOwner(updatedExpense.getOwner());
existingExpense.setCategory(updatedExpense.getCategory());
existingExpense.setSplitMode(updatedExpense.getSplitMode());
existingExpense.setSplitPercentage(updatedExpense.getSplitPercentage());
existingExpense.setLastModified(LocalDateTime.now());
Expense saved = expenseRepository.save(existingExpense);
@@ -153,6 +155,8 @@ public class ExpenseListService {
copy.setPersonalUseAmount(e.getPersonalUseAmount());
copy.setOtherPersonAmount(e.getOtherPersonAmount());
copy.setCategory(e.getCategory());
copy.setSplitMode(e.getSplitMode());
copy.setSplitPercentage(e.getSplitPercentage());
copy.setDate(e.getDate());
copy.setOwner(e.getOwner());
return copy;
@@ -3,6 +3,7 @@ package de.zendric.app.xpensely_Server.services;
import de.zendric.app.xpensely_server.model.AppUser;
import de.zendric.app.xpensely_server.model.Expense;
import de.zendric.app.xpensely_server.model.ExpenseList;
import de.zendric.app.xpensely_server.model.SplitMode;
import de.zendric.app.xpensely_server.repo.ExpenseListRepository;
import de.zendric.app.xpensely_server.repo.ExpenseRepository;
import de.zendric.app.xpensely_server.repo.XpenselyCustomCategoryRepository;
@@ -109,6 +110,29 @@ class ExpenseListServiceTest {
assertThat(beforeCaptor.getValue().getAmount()).isEqualTo(12.0);
}
@Test
void updateExpense_persistsSplitModeAndPercentage() {
AppUser actor = new AppUser(); actor.setId(1L);
ExpenseList list = new ExpenseList(); list.setId(10L); list.setOwner(actor);
Expense existing = makeExpense(5L, "Groceries", 100.0);
list.setExpenses(new ArrayList<>(List.of(existing)));
Expense incoming = makeExpense(5L, "Groceries", 100.0);
incoming.setDate(LocalDate.now());
incoming.setOwner(list.getOwner());
incoming.setSplitMode(SplitMode.PERCENTAGE);
incoming.setSplitPercentage(70);
when(repository.findById(10L)).thenReturn(Optional.of(list));
when(expenseRepository.findById(5L)).thenReturn(Optional.of(existing));
when(expenseRepository.save(any(Expense.class))).thenAnswer(inv -> inv.getArgument(0));
Expense saved = service.updateExpense(10L, incoming, actor);
assertThat(saved.getSplitMode()).isEqualTo(SplitMode.PERCENTAGE);
assertThat(saved.getSplitPercentage()).isEqualTo(70);
}
@Test
void deleteById_deletesHistoryEntriesBeforeDeletingList() {
service.deleteById(10L);