-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathExpense.java
134 lines (113 loc) · 4.63 KB
/
Expense.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package io.myfinbox.expense.domain;
import io.hypersistence.utils.hibernate.type.money.MonetaryAmountType;
import io.myfinbox.expense.ExpenseCreated;
import io.myfinbox.expense.ExpenseDeleted;
import io.myfinbox.expense.ExpenseUpdated;
import io.myfinbox.shared.PaymentType;
import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.CompositeType;
import org.springframework.data.domain.AbstractAggregateRoot;
import javax.money.MonetaryAmount;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.util.UUID;
import static io.myfinbox.shared.Guards.greaterThanZero;
import static io.myfinbox.shared.Guards.notNull;
import static java.util.Objects.isNull;
import static lombok.AccessLevel.PRIVATE;
@Entity
@Table(name = "expenses")
@Getter
@ToString
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor(access = PRIVATE, force = true)
public class Expense extends AbstractAggregateRoot<Expense> {
@EmbeddedId
private final ExpenseIdentifier id;
private final Instant creationTimestamp;
@Embedded
@AttributeOverride(name = "id", column = @Column(name = "account_id"))
private final AccountIdentifier account;
@AttributeOverride(name = "amount", column = @Column(name = "amount"))
@AttributeOverride(name = "currency", column = @Column(name = "currency"))
@CompositeType(MonetaryAmountType.class)
private MonetaryAmount amount;
@Enumerated(EnumType.STRING)
private PaymentType paymentType;
private LocalDate expenseDate;
private String description;
@ManyToOne(fetch = FetchType.LAZY)
private Category category;
@Builder
public Expense(AccountIdentifier account,
MonetaryAmount amount,
PaymentType paymentType,
LocalDate expenseDate,
String description,
Category category) {
this.id = new ExpenseIdentifier(UUID.randomUUID());
this.creationTimestamp = Instant.now();
this.account = notNull(account, "account cannot be null.");
this.amount = greaterThanZero(amount, "amount must be greater than 0.");
this.category = notNull(category, "category cannot be null.");
this.paymentType = isNull(paymentType) ? PaymentType.CARD : paymentType;
this.expenseDate = isNull(expenseDate) ? LocalDate.now() : expenseDate;
this.description = description;
registerEvent(ExpenseCreated.builder()
.expenseId(this.id.id())
.accountId(this.account.id())
.categoryId(this.category.getId().id())
.amount(this.amount)
.expenseDate(this.expenseDate)
.paymentType(this.paymentType)
.categoryName(category.getName())
.build());
}
public void update(ExpenseBuilder builder) {
notNull(builder, "builder cannot be null.");
this.amount = greaterThanZero(builder.amount, "amount must be greater than 0.");
this.category = notNull(builder.category, "category cannot be null.");
this.paymentType = isNull(builder.paymentType) ? PaymentType.CARD : builder.paymentType;
this.expenseDate = isNull(builder.expenseDate) ? LocalDate.now() : builder.expenseDate;
this.description = builder.description;
registerEvent(ExpenseUpdated.builder()
.expenseId(this.id.id())
.accountId(this.account.id())
.categoryId(this.category.getId().id())
.amount(this.amount)
.expenseDate(this.expenseDate)
.paymentType(this.paymentType)
.categoryName(builder.category.getName())
.build());
}
public BigDecimal getAmountAsNumber() {
return amount.getNumber().numberValue(BigDecimal.class);
}
public String getCurrencyCode() {
return amount.getCurrency().getCurrencyCode();
}
public void delete() {
registerEvent(ExpenseDeleted.builder()
.expenseId(this.id.id())
.accountId(this.account.id())
.categoryId(this.category.getId().id())
.amount(this.amount)
.expenseDate(this.expenseDate)
.paymentType(this.paymentType)
.categoryName(getCategory().getName())
.build());
}
@Embeddable
public record ExpenseIdentifier(UUID id) implements Serializable {
public ExpenseIdentifier {
notNull(id, "id cannot be null.");
}
@Override
public String toString() {
return id.toString();
}
}
}