Skip to content

Commit

Permalink
Enhance jar expense record with expense category name
Browse files Browse the repository at this point in the history
  • Loading branch information
semotpan committed Aug 19, 2024
1 parent 8cbfc3a commit 28eec22
Show file tree
Hide file tree
Showing 15 changed files with 85 additions and 43 deletions.
18 changes: 11 additions & 7 deletions server/src/main/java/io/myfinbox/expense/ExpenseCreated.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.time.LocalDate;
import java.util.UUID;

import static io.myfinbox.shared.Guards.notBlank;
import static io.myfinbox.shared.Guards.notNull;

/**
Expand All @@ -22,17 +23,19 @@ public record ExpenseCreated(UUID expenseId,
UUID categoryId,
MonetaryAmount amount,
LocalDate expenseDate,
PaymentType paymentType) implements DomainEvent {
PaymentType paymentType,
String categoryName) implements DomainEvent {

/**
* Constructor for the ExpenseCreated record.
*
* @param expenseId The unique identifier of the expense.
* @param accountId The identifier of the account associated with the expense.
* @param categoryId The identifier of the category associated with the expense.
* @param amount The amount of the expense.
* @param expenseDate The date of the expense.
* @param paymentType The payment type of the expense.
* @param expenseId The unique identifier of the expense.
* @param accountId The identifier of the account associated with the expense.
* @param categoryId The identifier of the category associated with the expense.
* @param amount The amount of the expense.
* @param expenseDate The date of the expense.
* @param paymentType The payment type of the expense.
* @param categoryName The category name associated with the expense.
*/
public ExpenseCreated {
notNull(expenseId, "expenseId cannot be null.");
Expand All @@ -41,5 +44,6 @@ public record ExpenseCreated(UUID expenseId,
notNull(amount, "amount cannot be null.");
notNull(expenseDate, "expenseDate cannot be null.");
notNull(paymentType, "paymentType cannot be null.");
notBlank(categoryName, "categoryName cannot be blank.");
}
}
18 changes: 11 additions & 7 deletions server/src/main/java/io/myfinbox/expense/ExpenseDeleted.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.time.LocalDate;
import java.util.UUID;

import static io.myfinbox.shared.Guards.notBlank;
import static io.myfinbox.shared.Guards.notNull;

/**
Expand All @@ -22,17 +23,19 @@ public record ExpenseDeleted(UUID expenseId,
UUID categoryId,
MonetaryAmount amount,
LocalDate expenseDate,
PaymentType paymentType) implements DomainEvent {
PaymentType paymentType,
String categoryName) implements DomainEvent {

/**
* Constructor for the ExpenseDeleted record.
*
* @param expenseId The unique identifier of the expense.
* @param accountId The identifier of the account associated with the expense.
* @param categoryId The identifier of the category associated with the expense.
* @param amount The amount of the expense.
* @param expenseDate The date of the expense.
* @param paymentType The payment type of the expense.
* @param expenseId The unique identifier of the expense.
* @param accountId The identifier of the account associated with the expense.
* @param categoryId The identifier of the category associated with the expense.
* @param amount The amount of the expense.
* @param expenseDate The date of the expense.
* @param paymentType The payment type of the expense.
* @param categoryName The category name associated with the expense.
*/
public ExpenseDeleted {
notNull(expenseId, "expenseId cannot be null.");
Expand All @@ -41,5 +44,6 @@ public record ExpenseDeleted(UUID expenseId,
notNull(amount, "amount cannot be null.");
notNull(expenseDate, "expenseDate cannot be null.");
notNull(paymentType, "paymentType cannot be null.");
notBlank(categoryName, "categoryName cannot be blank.");
}
}
18 changes: 11 additions & 7 deletions server/src/main/java/io/myfinbox/expense/ExpenseUpdated.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.time.LocalDate;
import java.util.UUID;

import static io.myfinbox.shared.Guards.notBlank;
import static io.myfinbox.shared.Guards.notNull;

/**
Expand All @@ -22,17 +23,19 @@ public record ExpenseUpdated(UUID expenseId,
UUID categoryId,
MonetaryAmount amount,
LocalDate expenseDate,
PaymentType paymentType) implements DomainEvent {
PaymentType paymentType,
String categoryName) implements DomainEvent {

/**
* Constructor for the ExpenseUpdated record.
*
* @param expenseId The unique identifier of the expense.
* @param accountId The identifier of the account associated with the expense.
* @param categoryId The identifier of the category associated with the expense.
* @param amount The amount of the expense.
* @param expenseDate The date of the expense.
* @param paymentType The payment type of the expense.
* @param expenseId The unique identifier of the expense.
* @param accountId The identifier of the account associated with the expense.
* @param categoryId The identifier of the category associated with the expense.
* @param amount The amount of the expense.
* @param expenseDate The date of the expense.
* @param paymentType The payment type of the expense.
* @param categoryName The category name associated with the expense.
*/
public ExpenseUpdated {
notNull(expenseId, "expenseId cannot be null.");
Expand All @@ -41,5 +44,6 @@ public record ExpenseUpdated(UUID expenseId,
notNull(amount, "amount cannot be null.");
notNull(expenseDate, "expenseDate cannot be null.");
notNull(paymentType, "paymentType cannot be null.");
notBlank(categoryName, "categoryName cannot be blank.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public Either<Failure, Void> delete(UUID expenseId) {
return Either.left(Failure.ofNotFound(EXPENSE_NOT_FOUND_MESSAGE));
}

var possibleExpense = expenses.findById(new ExpenseIdentifier(expenseId));
var possibleExpense = expenses.findByIdEagerCategory(new ExpenseIdentifier(expenseId));
if (possibleExpense.isEmpty()) {
return Either.left(Failure.ofNotFound(EXPENSE_NOT_FOUND_MESSAGE));
}
Expand Down
3 changes: 3 additions & 0 deletions server/src/main/java/io/myfinbox/expense/domain/Expense.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public Expense(AccountIdentifier account,
.amount(this.amount)
.expenseDate(this.expenseDate)
.paymentType(this.paymentType)
.categoryName(category.getName())
.build());
}

Expand All @@ -94,6 +95,7 @@ public void update(ExpenseBuilder builder) {
.amount(this.amount)
.expenseDate(this.expenseDate)
.paymentType(this.paymentType)
.categoryName(builder.category.getName())
.build());
}

Expand All @@ -113,6 +115,7 @@ public void delete() {
.amount(this.amount)
.expenseDate(this.expenseDate)
.paymentType(this.paymentType)
.categoryName(getCategory().getName())
.build());
}

Expand Down
8 changes: 8 additions & 0 deletions server/src/main/java/io/myfinbox/expense/domain/Expenses.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.myfinbox.expense.domain;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.Optional;
Expand All @@ -10,6 +11,13 @@
@Repository
public interface Expenses extends JpaRepository<Expense, ExpenseIdentifier> {

@Query(value = """
SELECT e FROM Expense e
JOIN FETCH e.category
WHERE e.id = :id
""")
Optional<Expense> findByIdEagerCategory(ExpenseIdentifier id);

boolean existsByCategory(Category category);

Optional<Expense> findByIdAndAccount(ExpenseIdentifier id, AccountIdentifier account);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public void on(ExpenseCreated event) {
.amount(event.amount())
.paymentType(event.paymentType())
.expenseDate(event.expenseDate())
.categoryName(event.categoryName())
.build());

if (expenseRecord.isEmpty()) {
Expand All @@ -61,6 +62,7 @@ public void on(ExpenseUpdated event) {
.amount(event.amount())
.paymentType(event.paymentType())
.expenseDate(event.expenseDate())
.categoryName(event.categoryName())
.build());

if (expenseRecord.isEmpty()) {
Expand All @@ -85,6 +87,7 @@ public void on(ExpenseDeleted event) {
.amount(event.amount())
.paymentType(event.paymentType())
.expenseDate(event.expenseDate())
.categoryName(event.categoryName())
.build());

if (expenseRecord.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public List<ExpenseRecord> recordCreated(ExpenseModificationRecord createdRecord
.amount(createdRecord.amount())
.paymentType(createdRecord.paymentType())
.expenseDate(createdRecord.expenseDate())
.categoryName(createdRecord.categoryName())
.jarExpenseCategory(category)
.build())
.toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.List;
import java.util.UUID;

import static io.myfinbox.shared.Guards.notBlank;
import static io.myfinbox.shared.Guards.notNull;

/**
Expand Down Expand Up @@ -49,7 +50,8 @@ record ExpenseModificationRecord(UUID expenseId,
UUID categoryId,
MonetaryAmount amount,
LocalDate expenseDate,
PaymentType paymentType) {
PaymentType paymentType,
String categoryName) {
public ExpenseModificationRecord {
// Validate non-null fields
notNull(expenseId, "expenseId cannot be null.");
Expand All @@ -58,6 +60,7 @@ record ExpenseModificationRecord(UUID expenseId,
notNull(amount, "amount cannot be null.");
notNull(expenseDate, "expenseDate cannot be null.");
notNull(paymentType, "paymentType cannot be null.");
notBlank(categoryName, "categoryName cannot be blank.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.time.LocalDate;
import java.util.UUID;

import static io.myfinbox.shared.Guards.notBlank;
import static io.myfinbox.shared.Guards.notNull;
import static lombok.AccessLevel.PACKAGE;

Expand Down Expand Up @@ -47,6 +48,7 @@ public class ExpenseRecord {
private PaymentType paymentType;

private LocalDate expenseDate;
private String categoryName;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "jar_expense_category_id", referencedColumnName = "id", nullable = false)
Expand All @@ -58,12 +60,14 @@ public ExpenseRecord(ExpenseIdentifier expenseId,
MonetaryAmount amount,
PaymentType paymentType,
LocalDate expenseDate,
String categoryName,
JarExpenseCategory jarExpenseCategory) {
this.expenseId = notNull(expenseId, "expenseId cannot be null.");
this.categoryId = notNull(categoryId, "categoryId cannot be null.");
this.amount = notNull(amount, "amount cannot be null.");
this.paymentType = notNull(paymentType, "paymentType cannot be null.");
this.expenseDate = notNull(expenseDate, "expenseDate cannot be null.");
this.categoryName = notBlank(categoryName, "categoryName cannot be blank.");
this.jarExpenseCategory = notNull(jarExpenseCategory, "jarExpenseCategory cannot be null.");
this.creationTimestamp = Instant.now();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ CREATE TABLE IF NOT EXISTS jar_expense_record
amount DECIMAL(19, 4) NOT NULL,
currency VARCHAR(3) NOT NULL,
expense_date DATE NOT NULL,
category_name VARCHAR(100) NOT NULL,
jar_expense_category_id BIGINT NOT NULL,
FOREIGN KEY (jar_expense_category_id) REFERENCES spending_jar_expense_category (id)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class DeleteExpenseServiceSpec extends Specification {

def "should fail delete when expense not found"() {
setup: 'repository mock behavior and interaction'
1 * expenses.findById(_ as Expense.ExpenseIdentifier) >> Optional.empty()
1 * expenses.findByIdEagerCategory(_ as Expense.ExpenseIdentifier) >> Optional.empty()

when: 'expense failed to delete'
def either = service.delete(UUID.randomUUID())
Expand All @@ -47,7 +47,7 @@ class DeleteExpenseServiceSpec extends Specification {
def "should delete an expense"() {
setup: 'repository mock behavior and interaction'
def expense = newSampleExpense()
1 * expenses.findById(_ as Expense.ExpenseIdentifier) >> Optional.of(expense)
1 * expenses.findByIdEagerCategory(_ as Expense.ExpenseIdentifier) >> Optional.of(expense)

when: 'expense is deleted'
def either = service.delete(UUID.randomUUID())
Expand Down
39 changes: 21 additions & 18 deletions server/src/test/groovy/io/myfinbox/spendingplan/DataSamples.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -131,30 +131,33 @@ class DataSamples {
]

static EXPENSE_MODIFICATION_RECORD = [
expenseId : expenseId,
accountId : accountId,
categoryId : jarCategoryId,
paymentType: "CASH",
amount : AMOUNT,
expenseDate: expenseDate,
expenseId : expenseId,
accountId : accountId,
categoryId : jarCategoryId,
paymentType : "CASH",
amount : AMOUNT,
expenseDate : expenseDate,
categoryName: categoryName,
]

static EXPENSE_EVENT = [
expenseId : expenseId,
accountId : accountId,
categoryId : jarCategoryId,
paymentType: "CASH",
amount : AMOUNT,
expenseDate: expenseDate,
expenseId : expenseId,
accountId : accountId,
categoryId : jarCategoryId,
paymentType : "CASH",
amount : AMOUNT,
expenseDate : expenseDate,
categoryName: categoryName,
]

static EXPENSE_RECORD = [
id : 1L,
expenseId : [id: expenseId],
categoryId : [id: jarCategoryId],
paymentType: "CASH",
amount : AMOUNT,
expenseDate: expenseDate,
id : 1L,
expenseId : [id: expenseId],
categoryId : [id: jarCategoryId],
paymentType : "CASH",
amount : AMOUNT,
categoryName: categoryName,
expenseDate : expenseDate,
]

static JAR_EXPENSE_CATEGORY = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class ExpenseEventsListenerSpec extends Specification {
assert recordedExpense.amount == Money.of(amount, "EUR")
assert recordedExpense.paymentType == PaymentType.CASH
assert recordedExpense.expenseDate == LocalDate.parse(expenseDate)
assert recordedExpense.categoryName == categoryName
}

@Sql(['/spendingplan/messaging/create-complete-plan-structure.sql', '/spendingplan/messaging/create-expense-records.sql'])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ INSERT INTO server.jar_expense_record(id,
amount,
currency,
expense_date,
category_name,
jar_expense_category_id)
VALUES (1,
'3b257779-a5db-4e87-9365-72c6f8d4977d',
Expand All @@ -13,6 +14,7 @@ VALUES (1,
1000.0,
'EUR',
'2024-03-23',
'Clothing',
1),
(2,
'6bd32beb-5f79-409a-8c50-ecbd3593dc12',
Expand All @@ -21,4 +23,5 @@ VALUES (1,
1000.0,
'EUR',
'2024-03-23',
'Clothing',
2);

0 comments on commit 28eec22

Please sign in to comment.