diff --git a/backend/app.hopps.az-document-ai/src/main/java/app/hopps/model/InvoiceDataHelper.java b/backend/app.hopps.az-document-ai/src/main/java/app/hopps/model/InvoiceDataHelper.java index 0d7406c..e9e5ff0 100644 --- a/backend/app.hopps.az-document-ai/src/main/java/app/hopps/model/InvoiceDataHelper.java +++ b/backend/app.hopps.az-document-ai/src/main/java/app/hopps/model/InvoiceDataHelper.java @@ -25,9 +25,6 @@ public static InvoiceData fromDocument(Long referenceKey, Document document) { .orElse("EUR"), Optional.ofNullable(fields.get("CustomerName")) .map(DocumentField::getValueString), - Optional.ofNullable(fields.get("BillingAddress")) - .map(DocumentField::getValueAddress) - .map(TradePartyHelper::fromAzure), Optional.ofNullable(fields.get("PurchaseOrder")) .map(DocumentField::getValueString), Optional.ofNullable(fields.get("InvoiceId")) @@ -37,7 +34,9 @@ public static InvoiceData fromDocument(Long referenceKey, Document document) { Optional.ofNullable(fields.get("AmountDue")) .map(DocumentField::getValueCurrency) .map(t -> BigDecimal.valueOf(t.getAmount())), - null, + Optional.ofNullable(fields.get("BillingAddress")) + .map(DocumentField::getValueAddress) + .map(TradePartyHelper::fromAzure), null); } } diff --git a/backend/app.hopps.az-document-ai/src/test/java/app/hopps/DocumentKafkaConnectorTest.java b/backend/app.hopps.az-document-ai/src/test/java/app/hopps/DocumentKafkaConnectorTest.java index 043b836..7fdd86e 100644 --- a/backend/app.hopps.az-document-ai/src/test/java/app/hopps/DocumentKafkaConnectorTest.java +++ b/backend/app.hopps.az-document-ai/src/test/java/app/hopps/DocumentKafkaConnectorTest.java @@ -1,9 +1,9 @@ package app.hopps; -import app.hopps.commons.TradeParty; import app.hopps.commons.DocumentData; import app.hopps.commons.InvoiceData; import app.hopps.commons.ReceiptData; +import app.hopps.commons.TradeParty; import io.quarkus.test.InjectMock; import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusTest; @@ -76,12 +76,11 @@ private static InvoiceData fakeInvoiceData() { LocalDate.now(), "EUR", Optional.of("Test customer"), - Optional.of(fakeAddress()), - Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), + Optional.of(fakeAddress()), Optional.empty()); } diff --git a/backend/app.hopps.commons/src/main/java/app/hopps/commons/InvoiceData.java b/backend/app.hopps.commons/src/main/java/app/hopps/commons/InvoiceData.java index f53e279..3455f01 100644 --- a/backend/app.hopps.commons/src/main/java/app/hopps/commons/InvoiceData.java +++ b/backend/app.hopps.commons/src/main/java/app/hopps/commons/InvoiceData.java @@ -10,7 +10,6 @@ public record InvoiceData( LocalDate invoiceDate, String currencyCode, Optional customerName, - Optional billingAddress, Optional purchaseOrderNumber, Optional invoiceId, Optional dueDate, @@ -19,7 +18,9 @@ public record InvoiceData( Optional receiver) implements Data { public InvoiceData(Long referenceKey, BigDecimal total, LocalDate invoiceDate, String currencyCode) { - this(referenceKey, total, invoiceDate, currencyCode, Optional.empty(), Optional.empty(), Optional.empty(), + this(referenceKey, total, invoiceDate, currencyCode, + Optional.empty(), + Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), diff --git a/backend/app.hopps.fin/src/main/java/app/hopps/fin/InvoiceDataHandler.java b/backend/app.hopps.fin/src/main/java/app/hopps/fin/InvoiceDataHandler.java index a4c83d2..d8192f0 100644 --- a/backend/app.hopps.fin/src/main/java/app/hopps/fin/InvoiceDataHandler.java +++ b/backend/app.hopps.fin/src/main/java/app/hopps/fin/InvoiceDataHandler.java @@ -27,7 +27,11 @@ private void handleInvoice(TransactionRecord transactionRecord, InvoiceData data // Optional data.customerName().ifPresent(transactionRecord::setName); - data.billingAddress().ifPresent(address -> transactionRecord.setSender(TradePartyHelper.convertToJpa(address))); + + data.sender().ifPresent(tradeParty -> transactionRecord.setSender(TradePartyHelper.convertToJpa(tradeParty))); + data.receiver() + .ifPresent(tradeParty -> transactionRecord.setRecipient(TradePartyHelper.convertToJpa(tradeParty))); + data.purchaseOrderNumber().ifPresent(transactionRecord::setOrderNumber); data.invoiceId().ifPresent(transactionRecord::setInvoiceId); data.dueDate() diff --git a/backend/app.hopps.fin/src/main/java/app/hopps/fin/endpoint/DocumentResource.java b/backend/app.hopps.fin/src/main/java/app/hopps/fin/endpoint/DocumentResource.java index 35d0f4a..6687e1a 100644 --- a/backend/app.hopps.fin/src/main/java/app/hopps/fin/endpoint/DocumentResource.java +++ b/backend/app.hopps.fin/src/main/java/app/hopps/fin/endpoint/DocumentResource.java @@ -71,9 +71,9 @@ public InputStream getDocumentByKey(@PathParam("documentKey") String documentKey @Produces(MediaType.APPLICATION_JSON) public Response uploadDocument( @RestForm("file") FileUpload file, - @RestForm @PartType(MediaType.TEXT_PLAIN) Optional bommelId, - @RestForm @PartType(MediaType.TEXT_PLAIN) boolean privatelyPaid, - @RestForm @PartType(MediaType.TEXT_PLAIN) DocumentType type) { + @RestForm("bommelId") @PartType(MediaType.TEXT_PLAIN) Optional bommelId, + @RestForm("privatelyPaid") @PartType(MediaType.TEXT_PLAIN) boolean privatelyPaid, + @RestForm("type") @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()); diff --git a/backend/app.hopps.fin/src/main/java/app/hopps/fin/jpa/entities/TransactionRecord.java b/backend/app.hopps.fin/src/main/java/app/hopps/fin/jpa/entities/TransactionRecord.java index 0f56107..badaa1c 100644 --- a/backend/app.hopps.fin/src/main/java/app/hopps/fin/jpa/entities/TransactionRecord.java +++ b/backend/app.hopps.fin/src/main/java/app/hopps/fin/jpa/entities/TransactionRecord.java @@ -1,6 +1,7 @@ package app.hopps.fin.jpa.entities; import app.hopps.commons.DocumentType; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -46,10 +47,10 @@ public class TransactionRecord { @Column(name = "transaction_time") private Instant transactionTime; - @OneToOne + @OneToOne(cascade = CascadeType.ALL) private TradeParty sender; - @OneToOne + @OneToOne(cascade = CascadeType.ALL) private TradeParty recipient; private String name; @@ -114,7 +115,9 @@ public void setSender(TradeParty address) { this.sender = address; } - public TradeParty getRecipient() {return recipient;} + public TradeParty getRecipient() { + return recipient; + } public void setRecipient(TradeParty address) { this.recipient = address; diff --git a/backend/app.hopps.fin/src/main/resources/db/migration/V1.0.1__update_record.sql b/backend/app.hopps.fin/src/main/resources/db/migration/V1.0.1__update_record.sql index e9384d0..418fef2 100644 --- a/backend/app.hopps.fin/src/main/resources/db/migration/V1.0.1__update_record.sql +++ b/backend/app.hopps.fin/src/main/resources/db/migration/V1.0.1__update_record.sql @@ -2,13 +2,17 @@ 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), + id bigint not null, + name varchar(255), + city varchar(255), + country varchar(255), + state varchar(255), + street varchar(255), + additionalAddress varchar(255), + zipCode varchar(255), + taxID varchar(255), + vatID varchar(255), + description varchar(255), primary key (id) ); diff --git a/backend/app.hopps.fin/src/test/java/app/hopps/fin/DataHandlerTest.java b/backend/app.hopps.fin/src/test/java/app/hopps/fin/DataHandlerTest.java index 6c2da00..4cd7034 100644 --- a/backend/app.hopps.fin/src/test/java/app/hopps/fin/DataHandlerTest.java +++ b/backend/app.hopps.fin/src/test/java/app/hopps/fin/DataHandlerTest.java @@ -1,9 +1,9 @@ package app.hopps.fin; -import app.hopps.commons.TradeParty; import app.hopps.commons.DocumentType; import app.hopps.commons.InvoiceData; import app.hopps.commons.ReceiptData; +import app.hopps.commons.TradeParty; import app.hopps.fin.jpa.TransactionRecordRepository; import app.hopps.fin.jpa.entities.TransactionRecord; import io.quarkus.test.TestTransaction; @@ -19,6 +19,7 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; import java.util.List; import java.util.Optional; @@ -28,7 +29,8 @@ @TestSecurity(user = "alice") class DataHandlerTest { - private static final TradeParty TRADE_PARTY = new TradeParty("Name","Country", "ZipCode", "State", "City", "Street", "AdditionalAddress", "TaxID", "VatID","Description"); + private static final TradeParty TRADE_PARTY = new TradeParty("Name", "Country", "ZipCode", "State", "City", + "Street", "AdditionalAddress", "TaxID", "VatID", "Description"); @Inject ReceiptDataHandler receiptDataHandler; @@ -72,7 +74,6 @@ void shouldWriteMinimalInvoiceData() { } @Test - @TestTransaction void shouldWriteFullInvoiceData() { // given @@ -83,13 +84,12 @@ void shouldWriteFullInvoiceData() { LocalDate.now(), "EUR", Optional.of("CustomerName"), - Optional.of(TRADE_PARTY), Optional.of("pruchaseOrderNumber"), Optional.of("invoiceId"), Optional.of(dueDate), Optional.of(BigDecimal.valueOf(150)), - null, - null); + Optional.of(TRADE_PARTY), + Optional.empty()); // when invoiceDataHandler.handleData(invoiceData); @@ -101,7 +101,7 @@ void shouldWriteFullInvoiceData() { TransactionRecord transactionRecord = transactionRecords.getFirst(); assertEquals("CustomerName", transactionRecord.getName()); assertEquals(dueDate.atStartOfDay(ZoneId.systemDefault()).toInstant(), transactionRecord.getDueDate()); - assertEquals("State", transactionRecord.getSender().getCountry()); + assertEquals("Country", transactionRecord.getSender().getCountry()); } @Test @@ -119,7 +119,6 @@ void shouldWriteMinimalReceiptData() { } @Test - @TestTransaction void shouldWriteFullReceiptData() { // given LocalDateTime transactionTime = LocalDateTime.now(); @@ -141,6 +140,7 @@ void shouldWriteFullReceiptData() { TransactionRecord transactionRecord = transactionRecords.getFirst(); assertEquals("StoreName", transactionRecord.getName()); assertEquals("City", transactionRecord.getSender().getCity()); - assertEquals(transactionTime.atOffset(ZoneOffset.UTC).toInstant(), transactionRecord.getTransactionTime()); + assertEquals(transactionTime.atOffset(ZoneOffset.UTC).toInstant().truncatedTo(ChronoUnit.SECONDS), + transactionRecord.getTransactionTime().truncatedTo(ChronoUnit.SECONDS)); } } diff --git a/backend/app.hopps.fin/src/test/java/app/hopps/fin/endpoint/DocumentResourceTest.java b/backend/app.hopps.fin/src/test/java/app/hopps/fin/endpoint/DocumentResourceTest.java index be90cf8..a42b681 100644 --- a/backend/app.hopps.fin/src/test/java/app/hopps/fin/endpoint/DocumentResourceTest.java +++ b/backend/app.hopps.fin/src/test/java/app/hopps/fin/endpoint/DocumentResourceTest.java @@ -1,5 +1,6 @@ package app.hopps.fin.endpoint; +import app.hopps.commons.DocumentType; import io.quarkus.test.common.http.TestHTTPEndpoint; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.security.TestSecurity; @@ -20,7 +21,7 @@ import static io.restassured.RestAssured.given; @QuarkusTest -@TestSecurity(authorizationEnabled = false) +@TestSecurity(user = "peter") @TestHTTPEndpoint(DocumentResource.class) class DocumentResourceTest { private static final String IMAGE_KEY = "imageKey"; @@ -77,6 +78,7 @@ void shouldUploadFile() { given() .contentType(MediaType.MULTIPART_FORM_DATA) .multiPart("file", "ZUGFeRD.pdf", zugferdInputStream) + .multiPart("type", DocumentType.INVOICE.toString()) .when() .post() .then() diff --git a/backend/app.hopps.zugferd/src/main/java/app/hopps/zugferd/ZugFerdService.java b/backend/app.hopps.zugferd/src/main/java/app/hopps/zugferd/ZugFerdService.java index c4a9f44..f343685 100644 --- a/backend/app.hopps.zugferd/src/main/java/app/hopps/zugferd/ZugFerdService.java +++ b/backend/app.hopps.zugferd/src/main/java/app/hopps/zugferd/ZugFerdService.java @@ -19,10 +19,4 @@ public InvoiceData scanInvoice(Long referenceKey, InputStream stream) Invoice invoice = zii.extractInvoice(); return InvoiceDataHandler.fromZugferd(referenceKey, invoice); } - - public Invoice getInvoice(Long referenceKey, InputStream stream) - throws XPathExpressionException, ParseException { - ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(stream); - return zii.extractInvoice(); - } } diff --git a/backend/app.hopps.zugferd/src/main/java/app/hopps/zugferd/model/InvoiceDataHandler.java b/backend/app.hopps.zugferd/src/main/java/app/hopps/zugferd/model/InvoiceDataHandler.java index a45b103..032bc7e 100644 --- a/backend/app.hopps.zugferd/src/main/java/app/hopps/zugferd/model/InvoiceDataHandler.java +++ b/backend/app.hopps.zugferd/src/main/java/app/hopps/zugferd/model/InvoiceDataHandler.java @@ -33,7 +33,6 @@ public static InvoiceData fromZugferd(Long referenceKey, Invoice invoice) { invoice.getIssueDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), invoice.getCurrency(), Optional.ofNullable(invoice.getRecipient().getName()), - Optional.of(TradePartyHelper.fromZugferd(invoice)), Optional.ofNullable(invoice.getReferenceNumber()), Optional.ofNullable(invoice.getNumber()), Optional.ofNullable(dueDate), Optional.of(amountDue), diff --git a/backend/app.hopps.zugferd/src/main/java/app/hopps/zugferd/model/TradePartyHelper.java b/backend/app.hopps.zugferd/src/main/java/app/hopps/zugferd/model/TradePartyHelper.java index 6cf82dc..6d75811 100644 --- a/backend/app.hopps.zugferd/src/main/java/app/hopps/zugferd/model/TradePartyHelper.java +++ b/backend/app.hopps.zugferd/src/main/java/app/hopps/zugferd/model/TradePartyHelper.java @@ -1,19 +1,16 @@ package app.hopps.zugferd.model; import app.hopps.commons.TradeParty; -import org.mustangproject.Invoice; public class TradePartyHelper { private TradePartyHelper() { - } - - public static TradeParty fromZugferd(Invoice invoice) { - return new TradeParty(invoice.getOwnOrganisationName(), invoice.getOwnCountry(), invoice.getOwnZIP(), null, invoice.getOwnLocation(), - invoice.getOwnStreet(), null, invoice.getOwnTaxID(), invoice.getOwnVATID(), invoice.getPaymentTermDescription()); + // use static method } public static TradeParty fromTradeParty(org.mustangproject.TradeParty tradeparty) { - return new TradeParty(tradeparty.getName(), tradeparty.getCountry(), tradeparty.getZIP(), null, tradeparty.getLocation(), - tradeparty.getStreet(), tradeparty.getAdditionalAddress(), tradeparty.getTaxID(), tradeparty.getVatID(), tradeparty.getDescription()); + return new TradeParty(tradeparty.getName(), tradeparty.getCountry(), tradeparty.getZIP(), null, + tradeparty.getLocation(), + tradeparty.getStreet(), tradeparty.getAdditionalAddress(), tradeparty.getTaxID(), tradeparty.getVatID(), + tradeparty.getDescription()); } }