Skip to content

Commit

Permalink
✨ (#232): New Logic and changes in the TransactionRecord
Browse files Browse the repository at this point in the history
  • Loading branch information
Manuel Klaus committed Jan 9, 2025
1 parent bea9c4b commit b0de5f8
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ private void handleInvoice(TransactionRecord transactionRecord, InvoiceData data

// Optional
data.customerName().ifPresent(transactionRecord::setName);
data.billingAddress().ifPresent(address -> transactionRecord.setAddress(AddressHelper.convertToJpa(address)));
data.billingAddress().ifPresent(address -> transactionRecord.setSender(AddressHelper.convertToJpa(address)));
data.purchaseOrderNumber().ifPresent(transactionRecord::setOrderNumber);
data.invoiceId().ifPresent(transactionRecord::setInvoiceId);
data.dueDate()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ private void handleReceipt(TransactionRecord transactionRecord, ReceiptData data

// Optional
data.storeName().ifPresent(transactionRecord::setName);
data.storeAddress().ifPresent(addrees -> transactionRecord.setAddress(AddressHelper.convertToJpa(addrees)));
data.storeAddress().ifPresent(addrees -> transactionRecord.setSender(AddressHelper.convertToJpa(addrees)));
data.transactionTime()
.ifPresent(
transactionTime -> transactionRecord
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;
import software.amazon.awssdk.services.s3.model.CreateBucketRequest;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.HeadBucketRequest;
import software.amazon.awssdk.services.s3.model.NoSuchBucketException;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;

import java.io.InputStream;

Expand All @@ -34,6 +38,7 @@ public InputStream getFile(String documentKey) {
.key(documentKey)
.build());

LOG.info("Content-Type of downloaded image: {}", object.response().contentType());
return object.asInputStream();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.SecurityContext;
import org.jboss.resteasy.reactive.PartType;
import org.jboss.resteasy.reactive.RestForm;
import org.jboss.resteasy.reactive.multipart.FileUpload;
Expand All @@ -36,13 +38,15 @@ public class DocumentResource {
private final DocumentProducer documentProducer;
private final S3Handler s3Handler;
private final TransactionRecordRepository repository;
private final SecurityContext context;

@Inject
public DocumentResource(DocumentProducer documentProducer, S3Handler s3Handler,
TransactionRecordRepository repository) {
TransactionRecordRepository repository, SecurityContext context) {
this.documentProducer = documentProducer;
this.s3Handler = s3Handler;
this.repository = repository;
this.context = context;
}

@GET
Expand All @@ -68,18 +72,24 @@ public InputStream getDocumentByKey(@PathParam("documentKey") String documentKey
public Response uploadDocument(
@RestForm("file") FileUpload file,
@RestForm @PartType(MediaType.TEXT_PLAIN) Optional<Long> bommelId,
@RestForm @PartType(MediaType.TEXT_PLAIN) Optional<DocumentType> type) {
@RestForm @PartType(MediaType.TEXT_PLAIN) boolean privatelyPaid,
@RestForm @PartType(MediaType.TEXT_PLAIN) DocumentType type) {
if (file == null || type == null) {
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST).entity("'file' or 'type' not set!").build());
}

s3Handler.saveFile(file);

// Save in database
TransactionRecord transactionRecord = new TransactionRecord(BigDecimal.ZERO);
TransactionRecord transactionRecord = new TransactionRecord(BigDecimal.ZERO, type, context.getUserPrincipal().getName());
transactionRecord.setDocumentKey(file.fileName());
transactionRecord.setPrivatelyPaid(privatelyPaid);
bommelId.ifPresent(transactionRecord::setBommelId);

persistTransactionRecord(transactionRecord);

// Sent to kafka to process
documentProducer.sendToProcess(transactionRecord, type.orElse(DocumentType.INVOICE));
documentProducer.sendToProcess(transactionRecord, type);

return Response.accepted().build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
package app.hopps.fin.jpa.entities;

import jakarta.persistence.Embeddable;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.SequenceGenerator;

@Embeddable
@Entity(name = "trade_party")
@SequenceGenerator(allocationSize = 1, name = "trade_party_sequence")
public class Address {
@Id
@GeneratedValue(generator = "trade_party_sequence")
private long id;
private String city;
private String country;
private String state;
private String zipCode;
private String city;
private String street;
private String streetNumber;
private String zipCode;

public long getId() {
return id;
}

public String getCountry() {
return country;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
package app.hopps.fin.jpa.entities;

import jakarta.persistence.*;
import app.hopps.commons.DocumentType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.OneToOne;
import jakarta.persistence.SequenceGenerator;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.Generated;

import java.math.BigDecimal;
import java.time.Instant;
Expand All @@ -18,17 +26,31 @@ public class TransactionRecord {
@Column(name = "document_key", nullable = false)
private String documentKey;

@Column(nullable = false, updatable = false)
private String uploader;

// That's the only required common column in the kafka events
@Column(nullable = false)
private BigDecimal total;

@Generated
@Column(name = "privately_paid")
@ColumnDefault("false")
private boolean privatelyPaid;

@Column(nullable = false)
private DocumentType document;

// invoice = invoice date
// receipt = transaction time
@Column(name = "transaction_time")
private Instant transactionTime;

@Embedded
private Address address;
@OneToOne
private Address sender;

@OneToOne
private Address recipient;

private String name;

Expand All @@ -39,11 +61,13 @@ public class TransactionRecord {
private BigDecimal amountDue;
private String currencyCode;

public TransactionRecord() {
protected TransactionRecord() {
}

public TransactionRecord(BigDecimal total) {
public TransactionRecord(BigDecimal total, DocumentType document, String uploader) {
this.total = total;
this.document = document;
this.uploader = uploader;
}

public Long getId() {
Expand Down Expand Up @@ -82,12 +106,36 @@ public void setTransactionTime(Instant transactionTime) {
this.transactionTime = transactionTime;
}

public Address getAddress() {
return address;
public Address getSender() {
return sender;
}

public void setSender(Address sender) {
this.sender = sender;
}

public boolean isPrivatelyPaid() {
return privatelyPaid;
}

public void setPrivatelyPaid(boolean privatelyPaid) {
this.privatelyPaid = privatelyPaid;
}

public DocumentType getDocument() {
return document;
}

public void setDocument(DocumentType document) {
this.document = document;
}

public Address getRecipient() {
return recipient;
}

public void setAddress(Address address) {
this.address = address;
public void setRecipient(Address recipient) {
this.recipient = recipient;
}

public String getName() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
create sequence trade_party_sequence start with 1 increment by 1;

create table trade_party
(
id bigint not null,
city varchar(255),
country varchar(255),
state varchar(255),
street varchar(255),
streetNumber varchar(255),
zipCode varchar(255),
primary key (id)
);

alter table TransactionRecord
add column privately_paid bool default false,
add column document smallint default 0 not null,
add column recipient_id bigint,
add column sender_id bigint,
add column uploader varchar(255),

drop column if exists city,
drop column if exists country,
drop column if exists state,
drop column if exists street,
drop column if exists streetNumber,
drop column if exists zipCode,

add constraint UKlu9j69deh9wh75pnlfeaxcvjf unique (recipient_id),
add constraint UKsvol64wdyce1cgdy4dfpbapa6 unique (sender_id),
add constraint FKc9y0wdh9ohw1q55y03og58o3w foreign key (recipient_id) references trade_party,
add constraint FK7yhrp9af6kbv73vcry7p4ot98 foreign key (sender_id) references trade_party
;
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package app.hopps.fin;

import app.hopps.commons.Address;
import app.hopps.commons.DocumentType;
import app.hopps.commons.InvoiceData;
import app.hopps.commons.ReceiptData;
import app.hopps.fin.jpa.TransactionRecordRepository;
Expand All @@ -24,7 +25,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;

@QuarkusTest
@TestSecurity(authorizationEnabled = false)
@TestSecurity(user = "alice")
class DataHandlerTest {

private static final Address address = new Address("Country", "ZipCode", "State", "City", "Street", "StreetNumber");
Expand All @@ -46,7 +47,7 @@ void setUp() {
// although this test does not persist to db, other test might…
repository.deleteAll();

TransactionRecord transactionRecord = new TransactionRecord(BigDecimal.TEN);
TransactionRecord transactionRecord = new TransactionRecord(BigDecimal.TEN, DocumentType.INVOICE, "alice");
transactionRecord.setDocumentKey("randomKey");
repository.persist(transactionRecord);
referenceKey = transactionRecord.getId();
Expand Down Expand Up @@ -98,7 +99,7 @@ void shouldWriteFullInvoiceData() {
TransactionRecord transactionRecord = transactionRecords.getFirst();
assertEquals("CustomerName", transactionRecord.getName());
assertEquals(dueDate.atStartOfDay(ZoneId.systemDefault()).toInstant(), transactionRecord.getDueDate());
assertEquals("State", transactionRecord.getAddress().getState());
assertEquals("State", transactionRecord.getSender().getState());
}

@Test
Expand Down Expand Up @@ -137,7 +138,7 @@ void shouldWriteFullReceiptData() {

TransactionRecord transactionRecord = transactionRecords.getFirst();
assertEquals("StoreName", transactionRecord.getName());
assertEquals("City", transactionRecord.getAddress().getCity());
assertEquals("City", transactionRecord.getSender().getCity());
assertEquals(transactionTime.atOffset(ZoneOffset.UTC).toInstant(), transactionRecord.getTransactionTime());
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package app.hopps.fin.endpoint;

import app.hopps.commons.DocumentType;
import app.hopps.fin.jpa.TransactionRecordRepository;
import app.hopps.fin.jpa.entities.TransactionRecord;
import com.github.tomakehurst.wiremock.client.WireMock;
Expand Down Expand Up @@ -38,12 +39,12 @@ class TransactionRecordResourceTest {
void setup() {
repository.deleteAll();

TransactionRecord withBommel = new TransactionRecord(BigDecimal.valueOf(50));
TransactionRecord withBommel = new TransactionRecord(BigDecimal.valueOf(50), DocumentType.INVOICE, "alice");
withBommel.setDocumentKey("randomKey");
withBommel.setBommelId(1L);
repository.persist(withBommel);

TransactionRecord noBommel = new TransactionRecord(BigDecimal.valueOf(20));
TransactionRecord noBommel = new TransactionRecord(BigDecimal.valueOf(20), DocumentType.RECEIPT, "alice");
noBommel.setDocumentKey("randomKey");
repository.persist(noBommel);
}
Expand Down

0 comments on commit b0de5f8

Please sign in to comment.