Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions timeless-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,16 @@
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-security</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-security-oidc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
Expand Down
30 changes: 27 additions & 3 deletions timeless-api/src/main/java/dev/matheuscruz/domain/Record.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.matheuscruz.domain;

import dev.matheuscruz.presentation.data.UpdateRecordRequest;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
Expand All @@ -9,6 +10,7 @@
import jakarta.persistence.Table;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.util.Objects;
import java.util.Optional;

Expand All @@ -27,19 +29,21 @@ public class Record {
@Enumerated(EnumType.STRING)
private Categories category;
private Instant createdAt;
private LocalDate transactionDate;

protected Record() {
}

private Record(String userId, BigDecimal amount, String description, Transactions transaction,
Categories category) {
private Record(String userId, BigDecimal amount, String description, Transactions transaction, Categories category,
LocalDate transactionDate) {
this.userId = userId;
this.amount = amount;
this.description = description;
this.transaction = transaction;
this.category = category;
this.createdAt = Instant.now();
this.category = Optional.ofNullable(category).orElse(Categories.NONE);
this.transactionDate = Optional.ofNullable(transactionDate).orElse(java.time.LocalDate.now());
}

public Long getId() {
Expand Down Expand Up @@ -70,12 +74,25 @@ public Instant getCreatedAt() {
return createdAt;
}

public LocalDate getTransactionDate() {
return transactionDate;
}

public void update(UpdateRecordRequest request) {
this.amount = Objects.requireNonNull(request.amount());
this.description = Objects.requireNonNull(request.description());
this.transaction = Objects.requireNonNull(request.transaction());
this.category = Objects.requireNonNull(request.category());
this.transactionDate = Objects.requireNonNull(request.transactionDate());
}

public static class Builder {
private String userId;
private BigDecimal amount;
private String description;
private Transactions transaction;
private Categories category;
private LocalDate transactionDate;

public Builder userId(String userId) {
this.userId = userId;
Expand All @@ -102,18 +119,25 @@ public Builder category(Categories category) {
return this;
}

public Builder transactionDate(LocalDate transactionDate) {
this.transactionDate = transactionDate;
return this;
}

public Record build() {
Objects.requireNonNull(userId, "userId must not be null");
Objects.requireNonNull(amount, "amount must not be null");
Objects.requireNonNull(description, "description must not be null");
Objects.requireNonNull(transaction, "transaction must not be null");
Objects.requireNonNull(transactionDate, "transactionDate must not be null");

if (transaction == Transactions.IN) {
category = Categories.NONE;
}
category = Optional.ofNullable(category).orElse(Categories.GENERAL);

return new Record(userId, amount, description, transaction, category);
return new Record(userId, amount, description, transaction, category, transactionDate);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import dev.matheuscruz.presentation.data.CreateRecordRequest;
import dev.matheuscruz.presentation.data.PageRecord;
import dev.matheuscruz.presentation.data.RecordItemResponse;
import dev.matheuscruz.presentation.data.UpdateRecordRequest;
import io.quarkus.narayana.jta.QuarkusTransaction;
import io.quarkus.panache.common.Page;
import io.quarkus.panache.common.Parameters;
Expand All @@ -19,6 +20,7 @@
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.core.Response;
Expand Down Expand Up @@ -58,6 +60,27 @@ public Response delete(@PathParam("id") Long id) {
return Response.status(Response.Status.NO_CONTENT).build();
}

@PUT
@Path("/{id}")
public Response update(@PathParam("id") Long id, @Valid UpdateRecordRequest req) {

QuarkusTransaction.requiringNew().run(() -> {
Record record = this.recordRepository.findById(id);

if (record == null) {
throw new jakarta.ws.rs.NotFoundException();
}

if (!record.getUserId().equals(upn)) {
throw new jakarta.ws.rs.ForbiddenException();
}

record.update(req);
});

return Response.noContent().build();
}

@POST
public Response createRecord(@Valid CreateRecordRequest req) {

Expand Down Expand Up @@ -85,10 +108,11 @@ public Response getRecords(@RestQuery("page") String p, @RestQuery("limit") Stri
// pagination
List<RecordItemResponse> output = recordRepository.find("userId = :userId", Parameters.with("userId", upn))
.page(Page.of(page, limit)).list().stream().map(record -> {
String format = record.getCreatedAt().atZone(ZoneId.of("America/Sao_Paulo")).toLocalDate()
String createdAt = record.getCreatedAt().atZone(ZoneId.of("America/Sao_Paulo")).toLocalDate()
.format(formatter);
String transactionDate = record.getTransactionDate().format(formatter);
return new RecordItemResponse(record.getId(), record.getAmount(), record.getDescription(),
record.getTransaction().name(), format, record.getCategory().name());
record.getTransaction().name(), transactionDate, createdAt, record.getCategory().name());
}).toList();

// calculate total expenses and total in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.PositiveOrZero;
import java.math.BigDecimal;
import java.time.LocalDate;

public record CreateRecordRequest(@PositiveOrZero BigDecimal amount, @NotBlank String description,
@NotNull Transactions transaction, @NotBlank String from, @NotNull Categories category) {
@NotNull Transactions transaction, @NotBlank String from, @NotNull Categories category,
LocalDate transactionDate) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

import java.math.BigDecimal;

public record RecordItemResponse(Long id, BigDecimal amount, String description, String transaction, String createdAt,
String category) {
public record RecordItemResponse(Long id, BigDecimal amount, String description, String transaction, String date,
String createdAt, String category) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package dev.matheuscruz.presentation.data;

import dev.matheuscruz.domain.Categories;
import dev.matheuscruz.domain.Transactions;
import java.math.BigDecimal;
import java.time.LocalDate;

public record UpdateRecordRequest(BigDecimal amount, String description, Transactions transaction, Categories category,
LocalDate transactionDate) {
}
10 changes: 9 additions & 1 deletion timeless-api/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,12 @@ quarkus.quinoa.build-dir=dist/timeless/browser
# jwt
mp.jwt.verify.publickey=${JWT_PUBLIC_KEY}
mp.jwt.verify.issuer=https://timelessapp.platformoon.com/issuer
smallrye.jwt.sign.key=${JWT_PRIVATE_KEY}
smallrye.jwt.sign.key=${JWT_PRIVATE_KEY}
# TEST CONFIGURATION
%test.quarkus.langchain4j.openai.api-key=test-key
%test.quarkus.langchain4j.openai.gpt-4-turbo.api-key=test-key
%test.security.sensible.secret=YS0xNi1ieXRlLXNlY3JldA==
%test.mp.jwt.verify.publickey=test-public-key
%test.smallrye.jwt.sign.key=test-private-key
%test.whatsapp.incoming-message.queue-url=test-queue
%test.whatsapp.recognized-message.queue-url=test-queue
Loading