From d15106498189e6ee7ee3c6016005a93771b47c16 Mon Sep 17 00:00:00 2001 From: Kammerlo Date: Fri, 28 Feb 2025 14:21:39 +0100 Subject: [PATCH 01/11] feat: first implementation --- .../domain/core/TransactionItem.java | 4 + .../domain/entity/TransactionItemEntity.java | 17 ++- ...AccountingCorePresentationViewService.java | 8 +- ...ournalAccountCreditEnrichmentTaskItem.java | 24 ++-- .../internal/AccountingCoreEventHandler.java | 30 ++-- .../internal/TransactionConverter.java | 17 +-- ...lob_service_app_accounting_core_module.sql | 6 + .../entity/TransactionItemEntityTest.java | 40 ------ ...countingCorePresentationConverterTest.java | 1 + ...alAccountCreditEnrichmentTaskItemTest.java | 65 +++++---- .../ExtractionParametersFilteringService.java | 18 +-- .../internal/NetSuiteExtractionService.java | 92 +++++++------ .../internal/TransactionConverter.java | 129 ++++++++++-------- 13 files changed, 231 insertions(+), 220 deletions(-) delete mode 100644 accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/domain/entity/TransactionItemEntityTest.java diff --git a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/domain/core/TransactionItem.java b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/domain/core/TransactionItem.java index 40e64031..706389e4 100644 --- a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/domain/core/TransactionItem.java +++ b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/domain/core/TransactionItem.java @@ -48,6 +48,10 @@ public class TransactionItem { @Builder.Default private Optional document = Optional.empty(); // initially we allow empty but later as part of business rules we check if document is present + @NotNull + @LOBVersionSourceRelevant + private OperationType operationType; + @NotNull @PositiveOrZero @LOBVersionSourceRelevant diff --git a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/domain/entity/TransactionItemEntity.java b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/domain/entity/TransactionItemEntity.java index 5b5b7cbd..b4777715 100644 --- a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/domain/entity/TransactionItemEntity.java +++ b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/domain/entity/TransactionItemEntity.java @@ -129,7 +129,7 @@ public String getId() { @AttributeOverride(name = "counterparty.type", column = @Column(name = "document_counterparty_type")), @AttributeOverride(name = "counterparty.name", column = @Column(name = "document_counterparty_name")), }) - @Nullable + private Document document; @Column(name = "status", nullable = false) @@ -139,6 +139,13 @@ public String getId() { @JdbcType(PostgreSQLEnumJdbcType.class) private TxItemValidationStatus status = TxItemValidationStatus.OK; + @Getter + @Setter + @Enumerated(EnumType.STRING) + @Column(name = "operation_type", nullable = false) + @JdbcType(PostgreSQLEnumJdbcType.class) + private OperationType operationType; + public void clearAccountCodeCredit() { this.accountCredit = null; } @@ -204,14 +211,6 @@ public void setRejection(Optional rejection) { this.rejection = rejection.orElse(null); } - public Optional getOperationType() { - val amountLcy = this.amountLcy; - - if (amountLcy.compareTo(BigDecimal.ZERO) == 0) return Optional.empty(); - - return amountLcy.compareTo(BigDecimal.ZERO) < 0 ? Optional.of(OperationType.CREDIT) : Optional.of(OperationType.DEBIT); - } - @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/resource/presentation_layer_service/AccountingCorePresentationViewService.java b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/resource/presentation_layer_service/AccountingCorePresentationViewService.java index 8d6a22b4..e0fc7d35 100644 --- a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/resource/presentation_layer_service/AccountingCorePresentationViewService.java +++ b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/resource/presentation_layer_service/AccountingCorePresentationViewService.java @@ -290,7 +290,7 @@ private TransactionReconciliationTransactionsView getTransactionReconciliationVi Optional.of(transactionEntity.getAutomatedValidationStatus()), transactionEntity.getTransactionApproved(), transactionEntity.getLedgerDispatchApproved(), - getAmountLcyTotalForAllItems(transactionEntity), + getAmountLcyTotalForAllDebitItems(transactionEntity), false, transactionEntity.getReconcilation().flatMap(reconcilation -> reconcilation.getSource().map(TransactionReconciliationTransactionsView.ReconciliationCodeView::of)) .orElse(TransactionReconciliationTransactionsView.ReconciliationCodeView.NEVER), @@ -373,7 +373,7 @@ private TransactionView getTransactionView(TransactionEntity transactionEntity) transactionEntity.getAutomatedValidationStatus(), transactionEntity.getTransactionApproved(), transactionEntity.getLedgerDispatchApproved(), - getAmountLcyTotalForAllItems(transactionEntity), + getAmountLcyTotalForAllDebitItems(transactionEntity), transactionEntity.hasAnyRejection(), transactionEntity.getReconcilation().flatMap(reconcilation -> reconcilation.getSource().map(TransactionView.ReconciliationCodeView::of)) .orElse(TransactionView.ReconciliationCodeView.NEVER), @@ -512,11 +512,11 @@ private TransactionReconciliationTransactionsView getReconciliationTransactionsS return getTransactionReconciliationViolationView(); } - public BigDecimal getAmountLcyTotalForAllItems(TransactionEntity tx) { + public BigDecimal getAmountLcyTotalForAllDebitItems(TransactionEntity tx) { Set items = tx.getItems(); if (tx.getTransactionType().equals(TransactionType.Journal)) { - items = tx.getItems().stream().filter(txItems -> txItems.getOperationType().equals(Optional.of(OperationType.DEBIT))).collect(toSet()); + items = tx.getItems().stream().filter(txItems -> txItems.getOperationType().equals(OperationType.DEBIT)).collect(toSet()); } return items.stream() diff --git a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountCreditEnrichmentTaskItem.java b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountCreditEnrichmentTaskItem.java index 8dc791ea..837ab0fa 100644 --- a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountCreditEnrichmentTaskItem.java +++ b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountCreditEnrichmentTaskItem.java @@ -11,9 +11,11 @@ import lombok.extern.slf4j.Slf4j; import lombok.val; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.OperationType; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.TransactionViolationCode; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.Account; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionEntity; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionItemEntity; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionViolation; import org.cardanofoundation.lob.app.organisation.OrganisationPublicApiIF; import org.cardanofoundation.lob.app.organisation.domain.entity.Organisation; @@ -32,12 +34,12 @@ public void run(TransactionEntity tx) { return; } - val dummyAccountM = organisationPublicApiIF.findByOrganisationId(tx.getOrganisation().getId()) + Optional dummyAccountM = organisationPublicApiIF.findByOrganisationId(tx.getOrganisation().getId()) .flatMap(Organisation::getDummyAccount); if (!shouldTriggerNormalisation(tx, dummyAccountM)) { if (dummyAccountM.isEmpty()) { - val v = TransactionViolation.builder() + TransactionViolation v = TransactionViolation.builder() .code(TransactionViolationCode.JOURNAL_DUMMY_ACCOUNT_MISSING) .processorModule(this.getClass().getSimpleName()) .source(LOB) @@ -52,22 +54,12 @@ public void run(TransactionEntity tx) { log.info("Normalising journal transaction with id: {}", tx.getId()); // at this point we can assume we have it, it is mandatory - val dummyAccount = dummyAccountM.orElseThrow(); - for (val txItem : tx.getItems()) { - val operationTypeM = txItem.getOperationType(); - - if (operationTypeM.isEmpty()) { - txItem.setAccountCredit(Optional.of(Account.builder() - .code(dummyAccount) - .name(DUMMY_ACCOUNT) - .build())); - continue; - } - - val operationType = operationTypeM.orElseThrow(); + String dummyAccount = dummyAccountM.orElseThrow(); + for (TransactionItemEntity txItem : tx.getItems()) { + OperationType operationType = txItem.getOperationType(); if (txItem.getAccountCredit().isEmpty() && operationType == CREDIT) { - val accountDebit = txItem.getAccountDebit().orElseThrow(); + Account accountDebit = txItem.getAccountDebit().orElseThrow(); txItem.setAccountCredit(Optional.of(accountDebit)); txItem.clearAccountCodeDebit(); diff --git a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/AccountingCoreEventHandler.java b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/AccountingCoreEventHandler.java index d5f2ae6c..35b62e6c 100644 --- a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/AccountingCoreEventHandler.java +++ b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/AccountingCoreEventHandler.java @@ -1,11 +1,19 @@ package org.cardanofoundation.lob.app.accounting_reporting_core.service.internal; +import java.time.LocalDate; +import java.util.Map; import java.util.Optional; +import java.util.Set; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import lombok.val; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.FatalError; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.ReportStatusUpdate; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.Transaction; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.TxStatusUpdate; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionEntity; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; @@ -37,7 +45,7 @@ public class AccountingCoreEventHandler { public void handleLedgerUpdatedEvent(TxsLedgerUpdatedEvent event) { log.info("Received handleLedgerUpdatedEvent event, event: {}", event.getStatusUpdates()); - val txStatusUpdatesMap = event.statusUpdatesMap(); + Map txStatusUpdatesMap = event.statusUpdatesMap(); ledgerService.updateTransactionsWithNewStatuses(txStatusUpdatesMap); transactionBatchService.updateBatchesPerTransactions(txStatusUpdatesMap); @@ -49,7 +57,7 @@ public void handleLedgerUpdatedEvent(TxsLedgerUpdatedEvent event) { public void handleReportsLedgerUpdated(ReportsLedgerUpdatedEvent event) { log.info("Received handleReportsLedgerUpdated, event: {}", event); - val reportStatusUpdatesMap = event.statusUpdatesMap(); + Map reportStatusUpdatesMap = event.statusUpdatesMap(); ledgerService.updateReportsWithNewStatuses(reportStatusUpdatesMap); @@ -60,7 +68,7 @@ public void handleReportsLedgerUpdated(ReportsLedgerUpdatedEvent event) { public void handleTransactionBatchFailedEvent(TransactionBatchFailedEvent event) { log.info("Received handleTransactionBatchFailedEvent event, event: {}", event); - val error = event.getError(); + FatalError error = event.getError(); transactionBatchService.failTransactionBatch( event.getBatchId(), @@ -92,8 +100,8 @@ public void handleTransactionBatchChunkEvent(TransactionBatchChunkEvent transact log.info("Received handleTransactionBatchChunkEvent event...., event, batch_id: {}, chunk_size:{}", batchId, transactionBatchChunkEvent.getTransactions().size()); - val txs = transactionBatchChunkEvent.getTransactions(); - val detachedDbTxs = transactionConverter.convertToDbDetached(txs); + Set txs = transactionBatchChunkEvent.getTransactions(); + Set detachedDbTxs = transactionConverter.convertToDbDetached(txs); erpIncomingDataProcessor.continueIngestion( transactionBatchChunkEvent.getOrganisationId(), @@ -134,12 +142,12 @@ public void handleReconcilationStartedEvent(ReconcilationStartedEvent event) { public void handleReconcilationChunkEvent(ReconcilationChunkEvent event) { log.info("Received handleReconcilationChunkEvent, event: {}", event); - val reconcilationId = event.getReconciliationId(); - val organisationId = event.getOrganisationId(); - val fromDate = event.getFrom(); - val toDate = event.getTo(); - val transactions = event.getTransactions(); - val chunkDetachedTxEntities = transactionConverter.convertToDbDetached(transactions); + String reconcilationId = event.getReconciliationId(); + String organisationId = event.getOrganisationId(); + LocalDate fromDate = event.getFrom(); + LocalDate toDate = event.getTo(); + Set transactions = event.getTransactions(); + Set chunkDetachedTxEntities = transactionConverter.convertToDbDetached(transactions); erpIncomingDataProcessor.continueReconcilation( reconcilationId, diff --git a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionConverter.java b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionConverter.java index 1f614daf..4bbc0645 100644 --- a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionConverter.java +++ b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionConverter.java @@ -72,10 +72,10 @@ public Set convertFromDb(Set transactionEntities } private TransactionEntity convertToDbDetached(Transaction transaction) { - val violations = transaction.getViolations() + Set violations = transaction.getViolations() .stream() .map(violation -> { - val violationEntity = new TransactionViolation(); + TransactionViolation violationEntity = new TransactionViolation(); violationEntity.setCode(violation.code()); violationEntity.setTxItemId(violation.txItemId()); violationEntity.setSeverity(violation.severity()); @@ -87,12 +87,12 @@ private TransactionEntity convertToDbDetached(Transaction transaction) { }) .collect(Collectors.toSet()); - val txItems = transaction.getItems() + Set txItems = transaction.getItems() .stream() .map(txItem -> { - val doc = convertToDbDetached(txItem.getDocument()); + Optional doc = convertToDbDetached(txItem.getDocument()); - val txItemEntity = new TransactionItemEntity(); + TransactionItemEntity txItemEntity = new TransactionItemEntity(); txItemEntity.setId(txItem.getId()); txItemEntity.setDocument(doc); txItemEntity.setAmountLcy(txItem.getAmountLcy()); @@ -100,6 +100,7 @@ private TransactionEntity convertToDbDetached(Transaction transaction) { txItemEntity.setCostCenter(convertCostCenter(txItem.getCostCenter())); txItemEntity.setProject(convertProject(txItem.getProject())); txItemEntity.setFxRate(txItem.getFxRate()); + txItemEntity.setOperationType(txItem.getOperationType()); txItem.getAccountCredit().ifPresent(creditAccount -> { txItemEntity.setAccountCredit(Optional.of(Account.builder() .code(creditAccount.getCode()) @@ -127,7 +128,7 @@ private TransactionEntity convertToDbDetached(Transaction transaction) { }) .collect(Collectors.toSet()); - val txEntity = new TransactionEntity(); + TransactionEntity txEntity = new TransactionEntity(); txEntity.setId(transaction.getId()); txEntity.setBatchId(transaction.getBatchId()); txEntity.setTransactionInternalNumber(transaction.getInternalTransactionNumber()); @@ -188,7 +189,7 @@ private Optional violations = transactionEntity.getViolations() .stream() .map(violationEntity -> { return new org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.Violation( @@ -202,7 +203,7 @@ private Transaction convertToDbDetached(TransactionEntity transactionEntity) { }) .collect(Collectors.toSet()); - val items = transactionEntity.getItems() + Set items = transactionEntity.getItems() .stream() .map(txItemEntity -> TransactionItem.builder() .id(txItemEntity.getId()) diff --git a/accounting_reporting_core/src/main/resources/db/migration/postgresql/common/V1.0_100_6__lob_service_app_accounting_core_module.sql b/accounting_reporting_core/src/main/resources/db/migration/postgresql/common/V1.0_100_6__lob_service_app_accounting_core_module.sql index a8b4f6e7..825d82d8 100644 --- a/accounting_reporting_core/src/main/resources/db/migration/postgresql/common/V1.0_100_6__lob_service_app_accounting_core_module.sql +++ b/accounting_reporting_core/src/main/resources/db/migration/postgresql/common/V1.0_100_6__lob_service_app_accounting_core_module.sql @@ -104,6 +104,11 @@ CREATE TYPE accounting_core_tx_item_validation_status_type AS ENUM ( 'ERASED_ZERO_BALANCE' ); +CREATE TYPE accounting_core_tx_item_operation_type AS ENUM ( + 'DEBIT', + 'CREDIT' +); + CREATE TYPE accounting_core_report_type AS ENUM ( 'BALANCE_SHEET', 'INCOME_STATEMENT' @@ -474,6 +479,7 @@ CREATE TABLE IF NOT EXISTS accounting_core_transaction_item ( cost_center_name VARCHAR(255), status accounting_core_tx_item_validation_status_type NOT NULL, + operation_type accounting_core_tx_item_operation_type NOT NULL, created_by VARCHAR(255), updated_by VARCHAR(255), diff --git a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/domain/entity/TransactionItemEntityTest.java b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/domain/entity/TransactionItemEntityTest.java deleted file mode 100644 index 09afcb9f..00000000 --- a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/domain/entity/TransactionItemEntityTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.OperationType.CREDIT; -import static org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.OperationType.DEBIT; - -import java.math.BigDecimal; -import java.util.Optional; - -import lombok.val; - -import org.junit.jupiter.api.Test; - -class TransactionItemEntityTest { - - @Test - void checkOperationTypeWorksProperly() { - val item1 = new TransactionItemEntity(); - item1.setId("1"); - item1.setAmountLcy(BigDecimal.valueOf(0.06)); // positive implies debit - - val item2 = new TransactionItemEntity(); - item2.setId("2"); - item2.setAmountLcy(BigDecimal.valueOf(-0.99)); // negative implies credit - - val item3 = new TransactionItemEntity(); - item3.setId("3"); - item3.setAmountLcy(BigDecimal.valueOf(0.93)); // positive implies debit - - val item4 = new TransactionItemEntity(); - item4.setId("4"); - item4.setAmountLcy(BigDecimal.valueOf(0)); - - assertThat(item1.getOperationType()).isEqualTo(Optional.of(DEBIT)); - assertThat(item2.getOperationType()).isEqualTo(Optional.of(CREDIT)); - assertThat(item3.getOperationType()).isEqualTo(Optional.of(DEBIT)); - assertThat(item4.getOperationType()).isEqualTo(Optional.empty()); - } - -} diff --git a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/resource/model/AccountingCorePresentationConverterTest.java b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/resource/model/AccountingCorePresentationConverterTest.java index 37bcf983..f57601cb 100644 --- a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/resource/model/AccountingCorePresentationConverterTest.java +++ b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/resource/model/AccountingCorePresentationConverterTest.java @@ -180,6 +180,7 @@ void testBatchDetail() { transactionItem.setId("txItemId"); transactionItem.setAmountLcy(BigDecimal.valueOf(100)); transactionItem.setAmountFcy(BigDecimal.valueOf(100)); + transactionItem.setOperationType(OperationType.DEBIT); TransactionViolation transactionViolation = new TransactionViolation(); transactionViolation.setTxItemId(Optional.of("txItemId")); LocalDate from = LocalDate.now(); diff --git a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountCreditEnrichmentTaskItemTest.java b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountCreditEnrichmentTaskItemTest.java index c5860bbd..25a0daa5 100644 --- a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountCreditEnrichmentTaskItemTest.java +++ b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountCreditEnrichmentTaskItemTest.java @@ -12,6 +12,7 @@ import lombok.val; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.OperationType; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -42,9 +43,9 @@ public class JournalAccountCreditEnrichmentTaskItemTest { @Test void should_Not_Run_Because_It_Is_Not_A_Journal_Transaction() { - val organisationId = "org1"; + String organisationId = "org1"; - val items = new LinkedHashSet(); + LinkedHashSet items = new LinkedHashSet(); transaction = new TransactionEntity(); transaction.setOrganisation(org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.Organisation.builder() .id(organisationId) @@ -52,7 +53,7 @@ void should_Not_Run_Because_It_Is_Not_A_Journal_Transaction() { ); transaction.setTransactionType(FxRevaluation); - val txItem1 = new TransactionItemEntity(); + TransactionItemEntity txItem1 = new TransactionItemEntity(); txItem1.setId("1"); txItem1.clearAccountCodeCredit(); items.add(txItem1); @@ -67,9 +68,9 @@ void should_Not_Run_Because_It_Is_Not_A_Journal_Transaction() { @Test void should_Not_Run_Because_Dummy_Account_Is_Missing() { - val organisationId = "org1"; + String organisationId = "org1"; - val items = new LinkedHashSet(); + LinkedHashSet items = new LinkedHashSet(); transaction = new TransactionEntity(); transaction.setOrganisation(org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.Organisation.builder() .id(organisationId) @@ -77,7 +78,7 @@ void should_Not_Run_Because_Dummy_Account_Is_Missing() { ); transaction.setTransactionType(Journal); - val txItem1 = new TransactionItemEntity(); + TransactionItemEntity txItem1 = new TransactionItemEntity(); txItem1.setId("1"); txItem1.clearAccountCodeCredit(); items.add(txItem1); @@ -95,9 +96,9 @@ void should_Not_Run_Because_Dummy_Account_Is_Missing() { @Test void should_Not_Run_Because_Not_All_Credit_Accounts_Are_Missing() { - val organisationId = "org1"; + String organisationId = "org1"; - val items = new LinkedHashSet(); + LinkedHashSet items = new LinkedHashSet(); transaction = new TransactionEntity(); transaction.setOrganisation(org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.Organisation.builder() .id(organisationId) @@ -105,12 +106,12 @@ void should_Not_Run_Because_Not_All_Credit_Accounts_Are_Missing() { ); transaction.setTransactionType(Journal); - val txItem1 = new TransactionItemEntity(); + TransactionItemEntity txItem1 = new TransactionItemEntity(); txItem1.setId("1"); txItem1.clearAccountCodeCredit(); items.add(txItem1); - val txItem2 = new TransactionItemEntity(); + TransactionItemEntity txItem2 = new TransactionItemEntity(); txItem2.setId("2"); txItem2.setAccountCredit(Optional.of(Account.builder() .code("1234567890") @@ -132,7 +133,7 @@ void should_Not_Run_Because_Not_All_Credit_Accounts_Are_Missing() { @Test void should_Set_Credit_From_Debit_If_Conditions_Met() { - val items = new LinkedHashSet(); + LinkedHashSet items = new LinkedHashSet<>(); transaction = new TransactionEntity(); transaction.setOrganisation(org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.Organisation.builder() .id("org1") @@ -140,7 +141,7 @@ void should_Set_Credit_From_Debit_If_Conditions_Met() { ); transaction.setTransactionType(Journal); - val item1 = new TransactionItemEntity(); + TransactionItemEntity item1 = new TransactionItemEntity(); item1.setId("1"); item1.setAccountDebit(Optional.of(Account.builder() @@ -148,10 +149,11 @@ void should_Set_Credit_From_Debit_If_Conditions_Met() { .build()) ); - item1.setAmountLcy(BigDecimal.valueOf(988.86)); // positive implies debit + item1.setAmountLcy(BigDecimal.valueOf(988.86)); + item1.setOperationType(OperationType.DEBIT); items.add(item1); - val item2 = new TransactionItemEntity(); + TransactionItemEntity item2 = new TransactionItemEntity(); item2.setId("2"); item2.setAccountDebit(Optional.of(Account.builder() .code("4102120100") @@ -159,10 +161,12 @@ void should_Set_Credit_From_Debit_If_Conditions_Met() { ) ); - item2.setAmountLcy(BigDecimal.valueOf(-188.50)); // negative implies credit + + item2.setAmountLcy(BigDecimal.valueOf(188.50)); + item2.setOperationType(OperationType.CREDIT); items.add(item2); - val item3 = new TransactionItemEntity(); + TransactionItemEntity item3 = new TransactionItemEntity(); item3.setId("3"); item3.setAccountDebit(Optional.of(Account.builder() .code("4102140100") @@ -170,9 +174,10 @@ void should_Set_Credit_From_Debit_If_Conditions_Met() { ); item3.setAmountLcy(BigDecimal.valueOf(148.64)); + item3.setOperationType(OperationType.DEBIT); items.add(item3); - val item4 = new TransactionItemEntity(); + TransactionItemEntity item4 = new TransactionItemEntity(); item4.setId("4"); item4.setAccountDebit(Optional.of(Account.builder() @@ -180,10 +185,11 @@ void should_Set_Credit_From_Debit_If_Conditions_Met() { .build()) ); - item4.setAmountLcy(BigDecimal.valueOf(-949.00)); + item4.setAmountLcy(BigDecimal.valueOf(949.00)); + item4.setOperationType(OperationType.CREDIT); items.add(item4); - val item5 = new TransactionItemEntity(); + TransactionItemEntity item5 = new TransactionItemEntity(); item5.setId("5"); item5.setAccountDebit(Optional.of(Account.builder() @@ -191,10 +197,11 @@ void should_Set_Credit_From_Debit_If_Conditions_Met() { .build()) ); - item5.setAmountLcy(BigDecimal.valueOf(-528.5)); + item5.setAmountLcy(BigDecimal.valueOf(528.5)); + item5.setOperationType(OperationType.CREDIT); items.add(item5); - val item6 = new TransactionItemEntity(); + TransactionItemEntity item6 = new TransactionItemEntity(); item6.setId("6"); item6.setAccountDebit(Optional.of(Account.builder() @@ -202,10 +209,11 @@ void should_Set_Credit_From_Debit_If_Conditions_Met() { .build()) ); - item6.setAmountLcy(BigDecimal.valueOf(-147.30)); + item6.setAmountLcy(BigDecimal.valueOf(147.30)); + item6.setOperationType(OperationType.CREDIT); items.add(item6); - val item7 = new TransactionItemEntity(); + TransactionItemEntity item7 = new TransactionItemEntity(); item7.setId("7"); item7.setAccountDebit(Optional.of(Account.builder() @@ -214,9 +222,10 @@ void should_Set_Credit_From_Debit_If_Conditions_Met() { ); item7.setAmountLcy(BigDecimal.valueOf(675.80)); + item7.setOperationType(OperationType.DEBIT); items.add(item7); - val item8 = new TransactionItemEntity(); + TransactionItemEntity item8 = new TransactionItemEntity(); item8.setId("8"); item8.setAccountDebit(Optional.of(Account.builder() @@ -224,10 +233,11 @@ void should_Set_Credit_From_Debit_If_Conditions_Met() { .build() )); - item8.setAmountLcy(BigDecimal.valueOf(-925.40)); + item8.setAmountLcy(BigDecimal.valueOf(925.40)); + item8.setOperationType(OperationType.CREDIT); items.add(item8); - val item9 = new TransactionItemEntity(); + TransactionItemEntity item9 = new TransactionItemEntity(); item9.setId("9"); item9.setAccountDebit(Optional.of(Account.builder() @@ -236,9 +246,10 @@ void should_Set_Credit_From_Debit_If_Conditions_Met() { )); item9.setAmountLcy(BigDecimal.valueOf(925.40)); + item9.setOperationType(OperationType.DEBIT); items.add(item9); - val item10 = new TransactionItemEntity(); + TransactionItemEntity item10 = new TransactionItemEntity(); item10.setId("10"); item10.setAccountDebit(Optional.of(Account.builder() diff --git a/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/ExtractionParametersFilteringService.java b/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/ExtractionParametersFilteringService.java index 8f477a8c..0c5eaba4 100644 --- a/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/ExtractionParametersFilteringService.java +++ b/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/ExtractionParametersFilteringService.java @@ -1,15 +1,17 @@ package org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.service.internal; import java.time.LocalDate; +import java.time.YearMonth; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import lombok.val; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.SystemExtractionParameters; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.Transaction; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.TransactionType; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.UserExtractionParameters; @Slf4j @@ -22,9 +24,9 @@ public Set applyExtractionParameters(Set txs, return txs.stream() // this is for sanity reasons since actually we should be filtering out the transactions in the adapter layer and more specifically while making an HTTP call via NetSuiteClient .filter(tx -> { - val txAccountingPeriod = tx.getAccountingPeriod(); // e.g. 2023-01 - val txAccountPeriodBeginning = txAccountingPeriod.atDay(1); // e.g. 2023-01-01 - val txAccountPeriodEnd = txAccountingPeriod.atEndOfMonth(); // e.g. 2023-01-31 + YearMonth txAccountingPeriod = tx.getAccountingPeriod(); // e.g. 2023-01 + LocalDate txAccountPeriodBeginning = txAccountingPeriod.atDay(1); // e.g. 2023-01-01 + LocalDate txAccountPeriodEnd = txAccountingPeriod.atEndOfMonth(); // e.g. 2023-01-31 return (txAccountPeriodBeginning.equals(systemExtractionParameters.getAccountPeriodFrom()) || txAccountPeriodBeginning.isAfter(systemExtractionParameters.getAccountPeriodFrom())) && @@ -33,23 +35,23 @@ public Set applyExtractionParameters(Set txs, .filter(tx -> userExtractionParameters.getOrganisationId().equals(tx.getOrganisation().getId())) // this is for sanity reasons since actually we should be filtering out the transactions in the adapter layer and more specifically while making an HTTP call via NetSuiteClient .filter(tx -> { - val from = userExtractionParameters.getFrom(); + LocalDate from = userExtractionParameters.getFrom(); return tx.getEntryDate().isEqual(from) || tx.getEntryDate().isAfter(from); }) // this is for sanity reasons since actually we should be filtering out the transactions in the adapter layer and more specifically while making an HTTP call via NetSuiteClient .filter(tx -> { - val to = userExtractionParameters.getTo(); + LocalDate to = userExtractionParameters.getTo(); return tx.getEntryDate().isEqual(to) || tx.getEntryDate().isBefore(to); }) .filter(tx -> { - val txTypes = userExtractionParameters.getTransactionTypes(); + List txTypes = userExtractionParameters.getTransactionTypes(); return txTypes.isEmpty() || txTypes.contains(tx.getTransactionType()); }) .filter(tx -> { - val transactionNumbers = userExtractionParameters.getTransactionNumbers(); + List transactionNumbers = userExtractionParameters.getTransactionNumbers(); return transactionNumbers.isEmpty() || transactionNumbers.contains(tx.getInternalTransactionNumber()); }) diff --git a/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/NetSuiteExtractionService.java b/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/NetSuiteExtractionService.java index 5d1e5393..5a490fa6 100644 --- a/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/NetSuiteExtractionService.java +++ b/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/NetSuiteExtractionService.java @@ -7,25 +7,33 @@ import static org.cardanofoundation.lob.app.support.crypto.MD5Hashing.md5; import static org.cardanofoundation.lob.app.support.crypto.SHA3.digestAsHex; +import java.time.LocalDate; +import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.UUID; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import lombok.val; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; import org.springframework.transaction.annotation.Transactional; +import io.vavr.control.Either; +import org.zalando.problem.Problem; + import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.FatalError; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.SystemExtractionParameters; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.Transaction; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.UserExtractionParameters; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.event.extraction.TransactionBatchChunkEvent; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.event.extraction.TransactionBatchFailedEvent; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.event.extraction.TransactionBatchStartedEvent; import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.client.NetSuiteClient; +import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.Transactions; +import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.TxLine; import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.entity.NetSuiteIngestionEntity; import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.repository.IngestionRepository; import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.util.MoreCompress; @@ -54,29 +62,29 @@ public class NetSuiteExtractionService { public void startNewERPExtraction(String organisationId, String user, UserExtractionParameters userExtractionParameters) { - val batchId = digestAsHex(UUID.randomUUID().toString()); + String batchId = digestAsHex(UUID.randomUUID().toString()); try { log.info("Running ingestion..."); - val fromExtractionDate = userExtractionParameters.getFrom(); - val toExtractionDate = userExtractionParameters.getTo(); + LocalDate fromExtractionDate = userExtractionParameters.getFrom(); + LocalDate toExtractionDate = userExtractionParameters.getTo(); - val netSuiteJsonE = netSuiteClient.retrieveLatestNetsuiteTransactionLines(fromExtractionDate, toExtractionDate); + Either> netSuiteJsonE = netSuiteClient.retrieveLatestNetsuiteTransactionLines(fromExtractionDate, toExtractionDate); if (netSuiteJsonE.isLeft()) { log.error("Error retrieving data from NetSuite API: {}", netSuiteJsonE.getLeft().getDetail()); - val problem = netSuiteJsonE.getLeft(); + Problem problem = netSuiteJsonE.getLeft(); - val bag = Map.of( + Map bag = Map.of( "adapterInstanceId", netsuiteInstanceId, "netsuiteUrl", netSuiteClient.getBaseUrl(), "technicalErrorTitle", problem.getTitle(), "technicalErrorDetail", problem.getDetail() ); - val batchFailedEvent = TransactionBatchFailedEvent.builder() + TransactionBatchFailedEvent batchFailedEvent = TransactionBatchFailedEvent.builder() .metadata(EventMetadata.create(TransactionBatchFailedEvent.VERSION, user)) .batchId(batchId) .organisationId(organisationId) @@ -88,20 +96,20 @@ public void startNewERPExtraction(String organisationId, return; } - val bodyM = netSuiteJsonE.get(); + Optional bodyM = netSuiteJsonE.get(); if (bodyM.isEmpty()) { log.warn("No data to read from NetSuite API..., bailing out!"); - val problem = netSuiteJsonE.getLeft(); + Problem problem = netSuiteJsonE.getLeft(); - val bag = Map.of( + Map bag = Map.of( "adapterInstanceId", netsuiteInstanceId, "netsuiteUrl", netSuiteClient.getBaseUrl(), "technicalErrorTitle", problem.getTitle(), "technicalErrorDetail", problem.getDetail() ); - val batchFailedEvent = TransactionBatchFailedEvent.builder() + TransactionBatchFailedEvent batchFailedEvent = TransactionBatchFailedEvent.builder() .metadata(EventMetadata.create(TransactionBatchFailedEvent.VERSION, user)) .batchId(batchId) .organisationId(organisationId) @@ -113,12 +121,12 @@ public void startNewERPExtraction(String organisationId, return; } - val netsuiteTransactionLinesJson = bodyM.get(); - val ingestionBodyChecksum = md5(netsuiteTransactionLinesJson); - val netSuiteIngestion = new NetSuiteIngestionEntity(); + String netsuiteTransactionLinesJson = bodyM.get(); + String ingestionBodyChecksum = md5(netsuiteTransactionLinesJson); + NetSuiteIngestionEntity netSuiteIngestion = new NetSuiteIngestionEntity(); netSuiteIngestion.setId(batchId); - val compressedBody = MoreCompress.compress(netsuiteTransactionLinesJson); + String compressedBody = MoreCompress.compress(netsuiteTransactionLinesJson); log.info("Before compression: {}, compressed: {}", netsuiteTransactionLinesJson.length(), compressedBody.length()); netSuiteIngestion.setIngestionBody(compressedBody); @@ -128,19 +136,19 @@ public void startNewERPExtraction(String organisationId, netSuiteIngestion.setAdapterInstanceId(netsuiteInstanceId); netSuiteIngestion.setIngestionBodyChecksum(ingestionBodyChecksum); - val storedNetsuiteIngestion = ingestionRepository.saveAndFlush(netSuiteIngestion); + NetSuiteIngestionEntity storedNetsuiteIngestion = ingestionRepository.saveAndFlush(netSuiteIngestion); - val systemExtractionParametersE = systemExtractionParametersFactory.createSystemExtractionParameters(organisationId); + Either systemExtractionParametersE = systemExtractionParametersFactory.createSystemExtractionParameters(organisationId); if (systemExtractionParametersE.isLeft()) { - val problem = systemExtractionParametersE.getLeft(); + Problem problem = systemExtractionParametersE.getLeft(); - val bag = Map.of( + Map bag = Map.of( "adapterInstanceId", netsuiteInstanceId, "technicalErrorTitle", problem.getTitle(), "technicalErrorDetail", problem.getDetail() ); - val batchFailedEvent = TransactionBatchFailedEvent.builder() + TransactionBatchFailedEvent batchFailedEvent = TransactionBatchFailedEvent.builder() .metadata(EventMetadata.create(TransactionBatchFailedEvent.VERSION, user)) .batchId(batchId) .organisationId(organisationId) @@ -152,7 +160,7 @@ public void startNewERPExtraction(String organisationId, return; } - val systemExtractionParameters = systemExtractionParametersE.get(); + SystemExtractionParameters systemExtractionParameters = systemExtractionParametersE.get(); applicationEventPublisher.publishEvent(TransactionBatchStartedEvent.builder() .metadata(EventMetadata.create(TransactionBatchStartedEvent.VERSION, user)) @@ -165,12 +173,12 @@ public void startNewERPExtraction(String organisationId, log.info("NetSuite ingestion started."); } catch (Exception e) { - val bag = Map.of( + Map bag = Map.of( "adapterInstanceId", netsuiteInstanceId, "technicalErrorMessage", e.getMessage() ); - val batchFailedEvent = TransactionBatchFailedEvent.builder() + TransactionBatchFailedEvent batchFailedEvent = TransactionBatchFailedEvent.builder() .metadata(EventMetadata.create(TransactionBatchFailedEvent.VERSION, user)) .batchId(batchId) .organisationId(organisationId) @@ -191,15 +199,15 @@ public void continueERPExtraction(String batchId, try { log.info("Continuing ERP extraction..., batchId: {}, organisationId: {}", batchId, organisationId); - val netsuiteIngestionM = ingestionRepository.findById(batchId); + Optional netsuiteIngestionM = ingestionRepository.findById(batchId); if (netsuiteIngestionM.isEmpty()) { log.error("NetSuite ingestion not found, batchId: {}", batchId); - val bag = Map.of( + Map bag = Map.of( "batchId", batchId, "organisationId", organisationId); - val batchFailedEvent = TransactionBatchFailedEvent.builder() + TransactionBatchFailedEvent batchFailedEvent = TransactionBatchFailedEvent.builder() .metadata(EventMetadata.create(TransactionBatchFailedEvent.VERSION)) .batchId(batchId) .organisationId(organisationId) @@ -213,12 +221,12 @@ public void continueERPExtraction(String batchId, } if (!userExtractionParameters.getOrganisationId().equals(systemExtractionParameters.getOrganisationId())) { - val bag = Map.of( + Map bag = Map.of( "batchId", batchId, "organisationId", organisationId ); - val batchFailedEvent = TransactionBatchFailedEvent.builder() + TransactionBatchFailedEvent batchFailedEvent = TransactionBatchFailedEvent.builder() .metadata(EventMetadata.create(TransactionBatchFailedEvent.VERSION)) .batchId(batchId) .organisationId(organisationId) @@ -230,20 +238,20 @@ public void continueERPExtraction(String batchId, applicationEventPublisher.publishEvent(batchFailedEvent); return; } - val netsuiteIngestion = netsuiteIngestionM.orElseThrow(); + NetSuiteIngestionEntity netsuiteIngestion = netsuiteIngestionM.orElseThrow(); - val transactionDataSearchResultE = netSuiteParser.parseSearchResults(requireNonNull(decompress(netsuiteIngestion.getIngestionBody()))); + Either> transactionDataSearchResultE = netSuiteParser.parseSearchResults(requireNonNull(decompress(netsuiteIngestion.getIngestionBody()))); if (transactionDataSearchResultE.isEmpty()) { - val problem = transactionDataSearchResultE.getLeft(); + Problem problem = transactionDataSearchResultE.getLeft(); - val bag = Map.of( + Map bag = Map.of( "batchId", batchId, "organisationId", organisationId, "technicalErrorTitle", problem.getTitle(), "technicalErrorDetail", problem.getDetail() ); - val batchFailedEvent = TransactionBatchFailedEvent.builder() + TransactionBatchFailedEvent batchFailedEvent = TransactionBatchFailedEvent.builder() .metadata(EventMetadata.create(TransactionBatchFailedEvent.VERSION)) .batchId(batchId) .organisationId(organisationId) @@ -256,11 +264,11 @@ public void continueERPExtraction(String batchId, return; } - val transactionDataSearchResult = transactionDataSearchResultE.get(); - val transactionsE = transactionConverter.convert(organisationId, batchId, transactionDataSearchResult); + List transactionDataSearchResult = transactionDataSearchResultE.get(); + Either transactionsE = transactionConverter.convert(organisationId, batchId, transactionDataSearchResult); if (transactionsE.isLeft()) { - val batchFailedEvent = TransactionBatchFailedEvent.builder() + TransactionBatchFailedEvent batchFailedEvent = TransactionBatchFailedEvent.builder() .metadata(EventMetadata.create(TransactionBatchFailedEvent.VERSION)) .batchId(batchId) .organisationId(organisationId) @@ -273,13 +281,13 @@ public void continueERPExtraction(String batchId, return; } - val transactions = transactionsE.get(); + Transactions transactions = transactionsE.get(); - val transactionsWithExtractionParametersApplied = extractionParametersFilteringService + Set transactionsWithExtractionParametersApplied = extractionParametersFilteringService .applyExtractionParameters(transactions.transactions(), userExtractionParameters, systemExtractionParameters); Partitions.partition(transactionsWithExtractionParametersApplied, sendBatchSize).forEach(txPartition -> { - val batchChunkEventBuilder = TransactionBatchChunkEvent.builder() + TransactionBatchChunkEvent.TransactionBatchChunkEventBuilder batchChunkEventBuilder = TransactionBatchChunkEvent.builder() .metadata(EventMetadata.create(TransactionBatchChunkEvent.VERSION)) .batchId(netsuiteIngestion.getId()) .organisationId(organisationId) @@ -301,12 +309,12 @@ public void continueERPExtraction(String batchId, } catch (Exception e) { log.error("Fatal error while processing NetSuite ingestion", e); - val bag = Map.of( + Map bag = Map.of( "adapterInstanceId", netsuiteInstanceId, "technicalErrorMessage", e.getMessage() ); - val batchFailedEvent = TransactionBatchFailedEvent.builder() + TransactionBatchFailedEvent batchFailedEvent = TransactionBatchFailedEvent.builder() .metadata(EventMetadata.create(TransactionBatchFailedEvent.VERSION)) .batchId(batchId) .organisationId(organisationId) diff --git a/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverter.java b/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverter.java index 35bbeec8..092eb748 100644 --- a/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverter.java +++ b/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverter.java @@ -7,6 +7,8 @@ import static org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.entity.CodeMappingType.ORGANISATION; import static org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.util.MoreString.normaliseString; +import java.math.BigDecimal; +import java.time.LocalDate; import java.time.YearMonth; import java.util.*; @@ -15,9 +17,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import lombok.val; import io.vavr.control.Either; +import org.zalando.problem.Problem; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.*; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.Currency; @@ -42,30 +44,30 @@ public class TransactionConverter { public Either convert(String organisationId, String batchId, List txLines) { - val searchResultsByOrganisation = new ArrayList(); - val transactions = new LinkedHashSet(); + ArrayList searchResultsByOrganisation = new ArrayList<>(); + LinkedHashSet transactions = new LinkedHashSet<>(); - for (val txLine : txLines) { - val localOrgIdE = organisationId(txLine); + for (TxLine txLine : txLines) { + Either localOrgIdE = organisationId(txLine); if (localOrgIdE.isEmpty()) { return Either.left(localOrgIdE.getLeft()); } - val localOrgId = localOrgIdE.get(); + String localOrgId = localOrgIdE.get(); if (localOrgId.equals(organisationId)) { searchResultsByOrganisation.add(txLine); } } - val searchResultItemsPerTransactionNumber = searchResultsByOrganisation + Map> searchResultItemsPerTransactionNumber = searchResultsByOrganisation .stream() .collect(groupingBy(TxLine::transactionNumber)); - for (val entry : searchResultItemsPerTransactionNumber.entrySet()) { - val transactionLevelTxLines = entry.getValue(); - val transactionE = createTransactionFromSearchResultItems(organisationId, batchId, transactionLevelTxLines); + for (Map.Entry> entry : searchResultItemsPerTransactionNumber.entrySet()) { + List transactionLevelTxLines = entry.getValue(); + Either> transactionE = createTransactionFromSearchResultItems(organisationId, batchId, transactionLevelTxLines); if (transactionE.isEmpty()) { return Either.left(transactionE.getLeft()); @@ -85,28 +87,27 @@ private Either> createTransactionFromSearchRes return Either.right(Optional.empty()); } - val firstTxLine = txLines.getFirst(); - val txId = Transaction.id(organisationId, firstTxLine.transactionNumber()); + TxLine firstTxLine = txLines.getFirst(); + String txId = Transaction.id(organisationId, firstTxLine.transactionNumber()); - val transTypeE = transactionType(organisationId, txId, firstTxLine); + Either transTypeE = transactionType(organisationId, txId, firstTxLine); if (transTypeE.isEmpty()) { return Either.left(transTypeE.getLeft()); } - val transactionType = transTypeE.get(); + TransactionType transactionType = transTypeE.get(); - val txDate = firstTxLine.date(); - val internalTransactionNumber = firstTxLine.transactionNumber(); - val fxRate = firstTxLine.exchangeRate(); - val accountingPeriod = financialPeriod(firstTxLine); + LocalDate txDate = firstTxLine.date(); + String internalTransactionNumber = firstTxLine.transactionNumber(); + BigDecimal fxRate = firstTxLine.exchangeRate(); + YearMonth accountingPeriod = financialPeriod(firstTxLine); - val txItems = new LinkedHashSet(); - - for (val txLine : txLines) { - val validationIssues = validator.validate(txLine); - val isValid = validationIssues.isEmpty(); + LinkedHashSet txItems = new LinkedHashSet<>(); + for (TxLine txLine : txLines) { + Set> validationIssues = validator.validate(txLine); + boolean isValid = validationIssues.isEmpty(); if (!isValid) { - val bag = Map.of( + Map bag = Map.of( "organisationId", organisationId, "txId", txId, "internalTransactionNumber", txLine.transactionNumber(), @@ -118,17 +119,35 @@ private Either> createTransactionFromSearchRes return Either.left(new FatalError(ADAPTER_ERROR, "TRANSACTIONS_VALIDATION_ERROR", bag)); } - val accountCreditCodeM = accountCreditCode(organisationId, txLine.accountMain()); - - val amountLcy = MoreBigDecimal.substractNullFriendly(txLine.amountDebit(), txLine.amountCredit()); - val amountFcy = MoreBigDecimal.substractNullFriendly(txLine.amountDebitForeignCurrency(), txLine.amountCreditForeignCurrency()); + Optional accountCreditCodeM = accountCreditCode(organisationId, txLine.accountMain()); + + OperationType operationType; + BigDecimal amountLcy; + BigDecimal amountFcy; + BigDecimal debitAmount = MoreBigDecimal.zeroForNull(txLine.amountDebit()); + BigDecimal creditAmount = MoreBigDecimal.zeroForNull(txLine.amountCredit()); + if(debitAmount.signum() > 0 && creditAmount.signum() > 0) { + // Error when both amounts are non-zero + return Either.left(new FatalError(ADAPTER_ERROR, "TRANSACTIONS_VALIDATION_ERROR", Map.of())); + } else if(debitAmount.signum() > 0) { + operationType = OperationType.DEBIT; + amountLcy = txLine.amountDebit(); + amountFcy = txLine.amountDebitForeignCurrency(); + } else if(creditAmount.signum() > 0) { + operationType = OperationType.CREDIT; + amountLcy = txLine.amountCredit(); + amountFcy = txLine.amountCreditForeignCurrency(); + } else { + // skipping when both amounts are zero + continue; + } - val costCenterM = costCenterCode(organisationId, txLine); - val projectCodeM = projectCode(organisationId, txLine); + Optional costCenterM = costCenterCode(organisationId, txLine); + Optional projectCodeM = projectCode(organisationId, txLine); - val documentM = convertDocument(organisationId, txLine); + Optional documentM = convertDocument(organisationId, txLine); - val txItem = TransactionItem.builder() + TransactionItem txItem = TransactionItem.builder() .id(TransactionItem.id(txId, txLine.lineID().toString())) .accountDebit(Optionals.zip(normaliseString(txLine.name()), normaliseString(txLine.number()), (accountDebitName, accountDebitCode) -> { return Account.builder() @@ -154,7 +173,7 @@ private Either> createTransactionFromSearchRes .fxRate(fxRate) .amountLcy(amountLcy) .amountFcy(amountFcy) - + .operationType(operationType) .build(); txItems.add(txItem); @@ -191,7 +210,7 @@ private YearMonth financialPeriod(TxLine txLine) { return switch (financialPeriodSource) { case IMPLICIT -> YearMonth.from(txLine.date()); case EXPLICIT -> { - val endDate = txLine.endDate(); + LocalDate endDate = txLine.endDate(); yield YearMonth.from(endDate); } @@ -201,10 +220,10 @@ private YearMonth financialPeriod(TxLine txLine) { private Either transactionType(String organisationId, String txId, TxLine txLine) { - val transactionTypeM = transactionTypeMapper.apply(txLine.type()); + Optional transactionTypeM = transactionTypeMapper.apply(txLine.type()); if (transactionTypeM.isEmpty()) { - val bag = Map.of( + Map bag = Map.of( "organisationId", organisationId, "internalTransactionNumber", txLine.transactionNumber(), "txId", txId, @@ -218,17 +237,17 @@ private Either transactionType(String organisationI } private Optional convertDocument(String organisationId, TxLine txLine) { - val documentNumberM = normaliseString(txLine.documentNumber()); + Optional documentNumberM = normaliseString(txLine.documentNumber()); if (documentNumberM.isPresent()) { - val documentNumber = documentNumberM.orElseThrow(); + String documentNumber = documentNumberM.orElseThrow(); - val taxItemM = normaliseString(txLine.taxItem()) + Optional taxItemM = normaliseString(txLine.taxItem()) .map(String::trim); - var vatCodeM = Optional.empty(); + Optional vatCodeM = Optional.empty(); if (taxItemM.isPresent()) { - val vatCodeE = preprocessorService.preProcess(taxItemM.orElseThrow(), VAT); + Either vatCodeE = preprocessorService.preProcess(taxItemM.orElseThrow(), VAT); if (vatCodeE.isEmpty()) { log.warn("Conversion failed for vatCode: {} in organisation: {}", taxItemM.orElseThrow(), organisationId); @@ -265,12 +284,12 @@ private static Optional convertCounterparty(TxLine txLine) { private Optional accountCreditCode(String organisationId, String accountMain) { - val accountCodeCreditM = normaliseString(accountMain); + Optional accountCodeCreditM = normaliseString(accountMain); if (accountCodeCreditM.isPresent()) { - val accountCodeCreditText = accountCodeCreditM.orElseThrow(); + String accountCodeCreditText = accountCodeCreditM.orElseThrow(); - val accountCreditCodeE = preprocessorService.preProcess(accountCodeCreditM.orElseThrow(), CHART_OF_ACCOUNT); + Either accountCreditCodeE = preprocessorService.preProcess(accountCodeCreditM.orElseThrow(), CHART_OF_ACCOUNT); if (accountCreditCodeE.isEmpty()) { log.warn("Conversion failed for accountCodeCredit: {} in organisation: {}", accountCodeCreditText, organisationId); @@ -278,7 +297,7 @@ private Optional accountCreditCode(String organisationId, return Optional.of(accountCodeCreditText); } - val accountCreditCode = accountCreditCodeE.get(); + String accountCreditCode = accountCreditCodeE.get(); return Optional.of(accountCreditCode); } @@ -288,19 +307,19 @@ private Optional accountCreditCode(String organisationId, private Optional costCenterCode(String organisationId, TxLine txLine) { - val costCenterM = MoreString.normaliseString(txLine.costCenter()); + Optional costCenterM = MoreString.normaliseString(txLine.costCenter()); if (costCenterM.isPresent()) { - val costCenterText = costCenterM.orElseThrow(); + String costCenterText = costCenterM.orElseThrow(); - val costCenterE = preprocessorService.preProcess(costCenterText, COST_CENTER); + Either costCenterE = preprocessorService.preProcess(costCenterText, COST_CENTER); if (costCenterE.isEmpty()) { log.warn("Conversion failed for costCenter: {} in organisation: {}", costCenterText, organisationId); return Optional.of(costCenterText); } - val costCenter = costCenterE.get(); + String costCenter = costCenterE.get(); return Optional.of(costCenter); } @@ -309,10 +328,10 @@ private Optional costCenterCode(String organisationId, } private Either organisationId(TxLine txLine) { - val organisationIdM = codesMappingService.getCodeMapping(netsuiteInstanceId, txLine.subsidiary(), ORGANISATION); + Optional organisationIdM = codesMappingService.getCodeMapping(netsuiteInstanceId, txLine.subsidiary(), ORGANISATION); if (organisationIdM.isEmpty()) { - val bag = Map.of( + Map bag = Map.of( "netsuiteInstanceId", netsuiteInstanceId, "subsidiary", txLine.subsidiary() ); @@ -325,12 +344,12 @@ private Either organisationId(TxLine txLine) { private Optional projectCode(String organisationId, TxLine txLine) { - val projectM = normaliseString(txLine.project()); + Optional projectM = normaliseString(txLine.project()); if (projectM.isPresent()) { - val projectText = projectM.orElseThrow(); + String projectText = projectM.orElseThrow(); - val projectCodeE = preprocessorService.preProcess(projectM.orElseThrow(), PROJECT); + Either projectCodeE = preprocessorService.preProcess(projectM.orElseThrow(), PROJECT); if (projectCodeE.isEmpty()) { log.warn("Conversion failed for projectCode: {} in organisation: {}", projectText, organisationId); @@ -338,7 +357,7 @@ private Optional projectCode(String organisationId, return Optional.of(projectText); } - val projectCode = projectCodeE.get(); + String projectCode = projectCodeE.get(); return Optional.of(projectCode); } From 2647970ea1f761e69872a540787302e06ec73811 Mon Sep 17 00:00:00 2001 From: Kammerlo Date: Fri, 28 Feb 2025 14:25:04 +0100 Subject: [PATCH 02/11] chore: spotless --- .../items/JournalAccountCreditEnrichmentTaskItem.java | 1 - .../service/internal/AccountingCoreEventHandler.java | 9 ++++----- .../service/internal/TransactionConverter.java | 1 - .../JournalAccountCreditEnrichmentTaskItemTest.java | 4 +--- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountCreditEnrichmentTaskItem.java b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountCreditEnrichmentTaskItem.java index 837ab0fa..3ba84cd5 100644 --- a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountCreditEnrichmentTaskItem.java +++ b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountCreditEnrichmentTaskItem.java @@ -9,7 +9,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import lombok.val; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.OperationType; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.TransactionViolationCode; diff --git a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/AccountingCoreEventHandler.java b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/AccountingCoreEventHandler.java index 35b62e6c..1a9a81ae 100644 --- a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/AccountingCoreEventHandler.java +++ b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/AccountingCoreEventHandler.java @@ -7,17 +7,16 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import lombok.val; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Service; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.FatalError; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.ReportStatusUpdate; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.Transaction; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.TxStatusUpdate; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionEntity; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.event.EventListener; -import org.springframework.stereotype.Service; - import org.cardanofoundation.lob.app.accounting_reporting_core.domain.event.extraction.TransactionBatchChunkEvent; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.event.extraction.TransactionBatchFailedEvent; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.event.extraction.TransactionBatchStartedEvent; diff --git a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionConverter.java b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionConverter.java index 4bbc0645..3ac630e8 100644 --- a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionConverter.java +++ b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionConverter.java @@ -6,7 +6,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import lombok.val; import org.springframework.stereotype.Service; diff --git a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountCreditEnrichmentTaskItemTest.java b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountCreditEnrichmentTaskItemTest.java index 25a0daa5..52d1a298 100644 --- a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountCreditEnrichmentTaskItemTest.java +++ b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountCreditEnrichmentTaskItemTest.java @@ -10,9 +10,6 @@ import java.util.LinkedHashSet; import java.util.Optional; -import lombok.val; - -import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.OperationType; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -20,6 +17,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.OperationType; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.Account; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionEntity; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionItemEntity; From 49942d5191084655c68dd2b7522b0081e0cb2f36 Mon Sep 17 00:00:00 2001 From: Kammerlo Date: Mon, 3 Mar 2025 11:16:55 +0100 Subject: [PATCH 03/11] chore: adjusting taskitems --- ...AmountFcyBalanceZerosOutCheckTaskItem.java | 21 +++++++++++++------ ...AmountLcyBalanceZerosOutCheckTaskItem.java | 19 +++++++++++------ ...lob_service_app_accounting_core_module.sql | 1 + ...ractionParametersFilteringServiceTest.java | 3 +-- .../domain/entity/Organisation.java | 2 +- 5 files changed, 31 insertions(+), 15 deletions(-) rename netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/{ => internal}/ExtractionParametersFilteringServiceTest.java (98%) diff --git a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountFcyBalanceZerosOutCheckTaskItem.java b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountFcyBalanceZerosOutCheckTaskItem.java index 435646b2..212137cf 100644 --- a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountFcyBalanceZerosOutCheckTaskItem.java +++ b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountFcyBalanceZerosOutCheckTaskItem.java @@ -7,10 +7,11 @@ import java.math.BigDecimal; import java.util.Map; +import java.util.Set; import lombok.RequiredArgsConstructor; -import lombok.val; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.OperationType; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionEntity; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionItemEntity; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionViolation; @@ -20,14 +21,14 @@ public class AmountFcyBalanceZerosOutCheckTaskItem implements PipelineTaskItem { @Override public void run(TransactionEntity tx) { - val txItems = tx.getItems(); + Set txItems = tx.getItems(); - val fcySum = txItems.stream() - .map(TransactionItemEntity::getAmountFcy) - .reduce(ZERO, BigDecimal::add); + BigDecimal fcySumDebit = getSumOfFcy(txItems, OperationType.DEBIT); + BigDecimal fcySumCredit = getSumOfFcy(txItems, OperationType.CREDIT); + BigDecimal fcySum = fcySumDebit.subtract(fcySumCredit); if (fcySum.signum() != 0) { - val v = TransactionViolation.builder() + TransactionViolation v = TransactionViolation.builder() .code(FCY_BALANCE_MUST_BE_ZERO) .severity(ERROR) .source(ERP) @@ -43,4 +44,12 @@ public void run(TransactionEntity tx) { } } + private static BigDecimal getSumOfFcy(Set txItems, OperationType credit) { + return txItems.stream() + .filter(transactionItemEntity -> transactionItemEntity.getOperationType().equals(credit)) + .map(TransactionItemEntity::getAmountFcy) + .reduce(ZERO, BigDecimal::add); + } + + } diff --git a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountLcyBalanceZerosOutCheckTaskItem.java b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountLcyBalanceZerosOutCheckTaskItem.java index ef65a4a6..2ead43c7 100644 --- a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountLcyBalanceZerosOutCheckTaskItem.java +++ b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountLcyBalanceZerosOutCheckTaskItem.java @@ -8,10 +8,11 @@ import java.math.BigDecimal; import java.util.Map; +import java.util.Set; import lombok.RequiredArgsConstructor; -import lombok.val; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.OperationType; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionEntity; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionItemEntity; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionViolation; @@ -21,14 +22,14 @@ public class AmountLcyBalanceZerosOutCheckTaskItem implements PipelineTaskItem { @Override public void run(TransactionEntity tx) { - val txItems = tx.getItems(); + Set txItems = tx.getItems(); - val lcySum = txItems.stream() - .map(TransactionItemEntity::getAmountLcy) - .reduce(ZERO, BigDecimal::add); + BigDecimal lcySumDebit = getSumOfOperationType(txItems, OperationType.DEBIT); + BigDecimal lcySumCredit = getSumOfOperationType(txItems, OperationType.CREDIT); + BigDecimal lcySum = lcySumDebit.subtract(lcySumCredit); if (lcySum.signum() != 0) { - val v = TransactionViolation.builder() + TransactionViolation v = TransactionViolation.builder() .code(LCY_BALANCE_MUST_BE_ZERO) .severity(ERROR) .source(ERP) @@ -44,4 +45,10 @@ public void run(TransactionEntity tx) { } } + private static BigDecimal getSumOfOperationType(Set txItems, OperationType credit) { + return txItems.stream() + .filter(transactionItemEntity -> transactionItemEntity.getOperationType().equals(credit)) + .map(TransactionItemEntity::getAmountLcy) + .reduce(ZERO, BigDecimal::add); + } } diff --git a/accounting_reporting_core/src/main/resources/db/migration/postgresql/common/V1.0_100_6__lob_service_app_accounting_core_module.sql b/accounting_reporting_core/src/main/resources/db/migration/postgresql/common/V1.0_100_6__lob_service_app_accounting_core_module.sql index 825d82d8..63445627 100644 --- a/accounting_reporting_core/src/main/resources/db/migration/postgresql/common/V1.0_100_6__lob_service_app_accounting_core_module.sql +++ b/accounting_reporting_core/src/main/resources/db/migration/postgresql/common/V1.0_100_6__lob_service_app_accounting_core_module.sql @@ -533,6 +533,7 @@ CREATE TABLE IF NOT EXISTS accounting_core_transaction_item_aud ( cost_center_external_customer_code VARCHAR(255), cost_center_name VARCHAR(255), status accounting_core_tx_item_validation_status_type, + operation_type accounting_core_tx_item_operation_type NOT NULL, created_by VARCHAR(255), updated_by VARCHAR(255), diff --git a/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/ExtractionParametersFilteringServiceTest.java b/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/ExtractionParametersFilteringServiceTest.java similarity index 98% rename from netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/ExtractionParametersFilteringServiceTest.java rename to netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/ExtractionParametersFilteringServiceTest.java index 130183be..8f802408 100644 --- a/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/ExtractionParametersFilteringServiceTest.java +++ b/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/ExtractionParametersFilteringServiceTest.java @@ -1,4 +1,4 @@ -package org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.service; +package org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.service.internal; import static org.assertj.core.api.Assertions.assertThat; import static org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.TransactionType.CardCharge; @@ -17,7 +17,6 @@ import org.junit.jupiter.api.Test; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.*; -import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.service.internal.ExtractionParametersFilteringService; class ExtractionParametersFilteringServiceTest { diff --git a/organisation/src/main/java/org/cardanofoundation/lob/app/organisation/domain/entity/Organisation.java b/organisation/src/main/java/org/cardanofoundation/lob/app/organisation/domain/entity/Organisation.java index 711cc255..8c3505d8 100644 --- a/organisation/src/main/java/org/cardanofoundation/lob/app/organisation/domain/entity/Organisation.java +++ b/organisation/src/main/java/org/cardanofoundation/lob/app/organisation/domain/entity/Organisation.java @@ -46,7 +46,7 @@ public class Organisation extends CommonEntity implements Persistable { @Column(name = "province", nullable = false) private String province; - @Column(name = "country", nullable = false) + @Column(name = "country") private String country; @Column(name = "address", nullable = false) From 0eb1e14e8d95340b6008819879f79201480afa9e Mon Sep 17 00:00:00 2001 From: Kammerlo Date: Mon, 3 Mar 2025 15:27:05 +0100 Subject: [PATCH 04/11] chore: adding tests --- .../internal/TransactionConverter.java | 10 +- .../NetSuiteExtractionServiceTest.java | 221 ++++++++++++++++++ 2 files changed, 226 insertions(+), 5 deletions(-) create mode 100644 netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/NetSuiteExtractionServiceTest.java diff --git a/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverter.java b/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverter.java index 092eb748..414dbea7 100644 --- a/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverter.java +++ b/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverter.java @@ -124,20 +124,20 @@ private Either> createTransactionFromSearchRes OperationType operationType; BigDecimal amountLcy; BigDecimal amountFcy; - BigDecimal debitAmount = MoreBigDecimal.zeroForNull(txLine.amountDebit()); - BigDecimal creditAmount = MoreBigDecimal.zeroForNull(txLine.amountCredit()); - if(debitAmount.signum() > 0 && creditAmount.signum() > 0) { + if(txLine.amountDebit() != null && txLine.amountCredit() != null) { // Error when both amounts are non-zero + log.error("Both debit and credit amounts are non-zero for transaction: {}", txId); return Either.left(new FatalError(ADAPTER_ERROR, "TRANSACTIONS_VALIDATION_ERROR", Map.of())); - } else if(debitAmount.signum() > 0) { + } else if(txLine.amountDebit() != null) { operationType = OperationType.DEBIT; amountLcy = txLine.amountDebit(); amountFcy = txLine.amountDebitForeignCurrency(); - } else if(creditAmount.signum() > 0) { + } else if(txLine.amountCredit() != null) { operationType = OperationType.CREDIT; amountLcy = txLine.amountCredit(); amountFcy = txLine.amountCreditForeignCurrency(); } else { + log.info("Skipping transaction line with zero amounts for transaction: {}", txId); // skipping when both amounts are zero continue; } diff --git a/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/NetSuiteExtractionServiceTest.java b/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/NetSuiteExtractionServiceTest.java new file mode 100644 index 00000000..e2650e9e --- /dev/null +++ b/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/NetSuiteExtractionServiceTest.java @@ -0,0 +1,221 @@ +package org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.service.internal; + +import static java.util.Objects.requireNonNull; +import static org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.util.MoreCompress.decompress; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import java.time.LocalDate; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.FatalError; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.SystemExtractionParameters; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.Transaction; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.event.extraction.TransactionBatchChunkEvent; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.event.extraction.TransactionBatchFailedEvent; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.event.extraction.TransactionBatchStartedEvent; +import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.Transactions; +import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.TxLine; +import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.entity.NetSuiteIngestionEntity; +import org.springframework.context.ApplicationEventPublisher; + +import io.vavr.control.Either; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.zalando.problem.Problem; +import org.zalando.problem.Status; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.UserExtractionParameters; +import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.client.NetSuiteClient; +import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.repository.IngestionRepository; + +@ExtendWith(MockitoExtension.class) +public class NetSuiteExtractionServiceTest { + + private final String INGESTION_BODY = "1f8b08000000000000ffed55c18ed33010bdef57583937959d2d42f4062b16b442805838210e537bd25a9bd8d1d8e9365af5df99a4dd264d5b71022144955aedcc7bf6ccf33ce5e94a88a4f484c95ce450049cb481c23a0c1cf9ce7f8478ea560e877a11acb1408df32b8b04a4570dc3d4e419119baadd29b9f33539289243c240444dc8ab69f399cc5ea4324b3329d4cb393f52f6d802422cbdb1b945d3f27e4988046e009ca52a4baf959072de3d3d10dd61c36376001dad77ae2e17485d039fbe7df9f8fa43c69f41612c0b27e511d5760dddbd4da594aac7aef92c4f5374d1c6668739496a5f56e01a07e5a8248315502c997c2cf400a259a570311b61a3bd19ed0a5afbdac569dfe54c49a5f83bd4e880da57f5d54728c43bf22108ebb8641439f952042850f85c2cbd3741f0058880b4b61a83988bfb7d7210fa4c7e6d038b1c44ee49205009f48046e475ac09056e2a7481c76e5c4909d68d7aaf89d0e9aee7fb47cb85ddf245e81e70b3074c43532e7cd1e26ededf0ee660a357e0962cdd6e18d474a880c1858df906caf6f4d1c984e638a7e429f732f398d767cbba88b6b7570b18941b22c43a10e66d1caa8a95641b9ddc9875115bd7eda64d5dcfb2a4836c27ff6d7cc6c6eadfb271f6676cfca6b68511556fe654f0783e58b714848f40e66f34f0c8a4a72ebe68e0b3cc73bcdfe1e0997ab57730af3fba37f31a8a1a5758540cd8193a697fb580edd5f62767da246cce070000"; + + @Mock + private IngestionRepository ingestionRepository; + @Mock + private NetSuiteClient netSuiteClient; + @Mock + private TransactionConverter transactionConverter; + @Mock + private ApplicationEventPublisher applicationEventPublisher; + @Mock + private SystemExtractionParametersFactory systemExtractionParametersFactory; + @Mock + private ExtractionParametersFilteringService extractionParametersFilteringService; + @Mock + private NetSuiteParser netSuiteParser; + + private NetSuiteExtractionService netSuiteExtractionService; + + @BeforeEach + void setUp() { + netSuiteExtractionService = new NetSuiteExtractionService(ingestionRepository, netSuiteClient, transactionConverter, applicationEventPublisher, systemExtractionParametersFactory, extractionParametersFilteringService, netSuiteParser, 1, "",true ); + } + + @Test + void testStartNewERPExtraction_errorJson() { + when(netSuiteClient.retrieveLatestNetsuiteTransactionLines(any(LocalDate.class), any(LocalDate.class))).thenReturn(Either.left(Problem.builder() + .withStatus(Status.BAD_REQUEST) + .withTitle("testTitle") + .withDetail("testDetail") + .build())); + when(netSuiteClient.getBaseUrl()).thenReturn("testBaseUrl"); + + netSuiteExtractionService.startNewERPExtraction("orgId", "userId", UserExtractionParameters.builder().from(LocalDate.now()).to(LocalDate.now()).build()); + + // verifying that the event was published + verify(applicationEventPublisher).publishEvent(any(TransactionBatchFailedEvent.class)); + verify(netSuiteClient).retrieveLatestNetsuiteTransactionLines(any(LocalDate.class), any(LocalDate.class)); + verify(netSuiteClient).getBaseUrl(); + verifyNoMoreInteractions(applicationEventPublisher, netSuiteClient); + + } + + @Test + void testStartNewERPExtraction_emptyBody() { + when(netSuiteClient.retrieveLatestNetsuiteTransactionLines(any(LocalDate.class), any(LocalDate.class))).thenReturn(Either.right(Optional.empty())); + netSuiteExtractionService.startNewERPExtraction("orgId", "userId", UserExtractionParameters.builder().from(LocalDate.now()).to(LocalDate.now()).build()); + + // verifying that the event was published + verify(applicationEventPublisher).publishEvent(any(TransactionBatchFailedEvent.class)); + verify(netSuiteClient).retrieveLatestNetsuiteTransactionLines(any(LocalDate.class), any(LocalDate.class)); + verifyNoMoreInteractions(applicationEventPublisher, netSuiteClient); + } + + @Test + void testStartNewERPExtraction_errorCreatingExtractionParams() { + when(netSuiteClient.retrieveLatestNetsuiteTransactionLines(any(LocalDate.class), any(LocalDate.class))).thenReturn(Either.right(Optional.of("TestBody"))); + when(systemExtractionParametersFactory.createSystemExtractionParameters("orgId")).thenReturn(Either.left(Problem.builder() + .withStatus(Status.BAD_REQUEST) + .withTitle("testTitle") + .withDetail("testDetail") + .build())); + + netSuiteExtractionService.startNewERPExtraction("orgId", "userId", UserExtractionParameters.builder().from(LocalDate.now()).to(LocalDate.now()).build()); + + verify(applicationEventPublisher).publishEvent(any(TransactionBatchFailedEvent.class)); + verify(netSuiteClient).retrieveLatestNetsuiteTransactionLines(any(LocalDate.class), any(LocalDate.class)); + verify(systemExtractionParametersFactory).createSystemExtractionParameters("orgId"); + verifyNoMoreInteractions(applicationEventPublisher, netSuiteClient, systemExtractionParametersFactory); + } + + @Test + void testStartNewERPExtraction_successfull() { + when(netSuiteClient.retrieveLatestNetsuiteTransactionLines(any(LocalDate.class), any(LocalDate.class))).thenReturn(Either.right(Optional.of("TestBody"))); + when(systemExtractionParametersFactory.createSystemExtractionParameters("orgId")).thenReturn(Either.right(SystemExtractionParameters.builder().build())); + when(ingestionRepository.saveAndFlush(any())).thenReturn(new NetSuiteIngestionEntity("id", "adapterInstanceId", "ingestionBody","ingestionBodyDebug", "ingestionChecksum")); + netSuiteExtractionService.startNewERPExtraction("orgId", "userId", UserExtractionParameters.builder().from(LocalDate.now()).to(LocalDate.now()).build()); + + verify(netSuiteClient).retrieveLatestNetsuiteTransactionLines(any(LocalDate.class), any(LocalDate.class)); + verify(systemExtractionParametersFactory).createSystemExtractionParameters("orgId"); + verify(applicationEventPublisher).publishEvent(any(TransactionBatchStartedEvent.class)); + verify(ingestionRepository).saveAndFlush(any()); + verifyNoMoreInteractions(netSuiteClient, systemExtractionParametersFactory, applicationEventPublisher, ingestionRepository); + } + + @Test + void testStartNewERPExtraction_exceptionHandling() { + when(netSuiteClient.retrieveLatestNetsuiteTransactionLines(any(LocalDate.class), any(LocalDate.class))).thenThrow(new RuntimeException("TestException")); + + netSuiteExtractionService.startNewERPExtraction("orgId", "userId", UserExtractionParameters.builder().from(LocalDate.now()).to(LocalDate.now()).build()); + + verify(applicationEventPublisher).publishEvent(any(TransactionBatchFailedEvent.class)); + verify(netSuiteClient).retrieveLatestNetsuiteTransactionLines(any(LocalDate.class), any(LocalDate.class)); + verifyNoMoreInteractions(applicationEventPublisher, netSuiteClient); + } + + @Test + void testContinueERPExtraction_NotFound() { + when(ingestionRepository.findById("id")).thenReturn(Optional.empty()); + netSuiteExtractionService.continueERPExtraction("id", "orgId", UserExtractionParameters.builder().from(LocalDate.now()).to(LocalDate.now()).build(), SystemExtractionParameters.builder().build()); + + verify(applicationEventPublisher).publishEvent(any(TransactionBatchFailedEvent.class)); + verify(ingestionRepository).findById("id"); + verifyNoMoreInteractions(applicationEventPublisher, ingestionRepository); + } + + @Test + void testContinueERPExtraction_orgIdMismatch() { + when(ingestionRepository.findById("id")).thenReturn(Optional.of(new NetSuiteIngestionEntity("id", "adapterInstanceId", "ingestionBody","ingestionBodyDebug", "ingestionChecksum"))); + netSuiteExtractionService.continueERPExtraction("id", "orgId", UserExtractionParameters.builder().organisationId("org1").from(LocalDate.now()).to(LocalDate.now()).build(), SystemExtractionParameters.builder().organisationId("orgId2").build()); + + verify(applicationEventPublisher).publishEvent(any(TransactionBatchFailedEvent.class)); + verify(ingestionRepository).findById("id"); + verifyNoMoreInteractions(applicationEventPublisher, ingestionRepository); + } + + @Test + void testContinueERPExtraction_parseSearchFailed() { + when(ingestionRepository.findById("id")).thenReturn(Optional.of(new NetSuiteIngestionEntity("id", "adapterInstanceId", INGESTION_BODY,"ingestionBodyDebug", "ingestionChecksum"))); + when(netSuiteParser.parseSearchResults(requireNonNull(decompress(INGESTION_BODY)))).thenReturn(Either.left(Problem.builder() + .withStatus(Status.BAD_REQUEST) + .withTitle("testTitle") + .withDetail("testDetail") + .build())); + + netSuiteExtractionService.continueERPExtraction("id", "orgId", UserExtractionParameters.builder().organisationId("org").from(LocalDate.now()).to(LocalDate.now()).build(), SystemExtractionParameters.builder().organisationId("org").build()); + + verify(applicationEventPublisher).publishEvent(any(TransactionBatchFailedEvent.class)); + verify(ingestionRepository).findById("id"); + verify(netSuiteParser).parseSearchResults(requireNonNull(decompress(INGESTION_BODY))); + verifyNoMoreInteractions(applicationEventPublisher, ingestionRepository, netSuiteParser); + } + + @Test + void testContinueERPExtraction_transactionConvertFailed() { + when(ingestionRepository.findById("id")).thenReturn(Optional.of(new NetSuiteIngestionEntity("id", "adapterInstanceId", INGESTION_BODY,"ingestionBodyDebug", "ingestionChecksum"))); + when(netSuiteParser.parseSearchResults(requireNonNull(decompress(INGESTION_BODY)))).thenReturn(Either.right(List.of())); + when(transactionConverter.convert("org", "id", List.of())).thenReturn(Either.left(new FatalError(FatalError.Code.ADAPTER_ERROR, "test", Map.of()))); + netSuiteExtractionService.continueERPExtraction("id", "orgId", UserExtractionParameters.builder().organisationId("org").from(LocalDate.now()).to(LocalDate.now()).build(), SystemExtractionParameters.builder().organisationId("org").build()); + + verify(applicationEventPublisher).publishEvent(any(TransactionBatchFailedEvent.class)); + verify(ingestionRepository).findById("id"); + verify(netSuiteParser).parseSearchResults(requireNonNull(decompress(INGESTION_BODY))); + verifyNoMoreInteractions(applicationEventPublisher, ingestionRepository, netSuiteParser); + } + + @Test + void testContinueERPExtraction_transactionConvertSuccess() { + TxLine mockTxLine = mock(TxLine.class); + when(ingestionRepository.findById("id")).thenReturn(Optional.of(new NetSuiteIngestionEntity("id", "adapterInstanceId", INGESTION_BODY,"ingestionBodyDebug", "ingestionChecksum"))); + when(netSuiteParser.parseSearchResults(requireNonNull(decompress(INGESTION_BODY)))).thenReturn(Either.right(List.of(mockTxLine))); + when(transactionConverter.convert("orgId", "id", List.of(mockTxLine))).thenReturn(Either.right(new Transactions("org", Set.of()))); + when(extractionParametersFilteringService.applyExtractionParameters(any(), any(), any())).thenReturn(Set.of(Transaction.builder().id("id1").build(), Transaction.builder().id("id2").build(), Transaction.builder().id("id3").build())); + + netSuiteExtractionService.continueERPExtraction("id", "orgId", UserExtractionParameters.builder().organisationId("org").from(LocalDate.now()).to(LocalDate.now()).build(), SystemExtractionParameters.builder().organisationId("org").build()); + + verify(applicationEventPublisher, times(3)).publishEvent(any(TransactionBatchChunkEvent.class)); + verify(ingestionRepository).findById("id"); + verify(netSuiteParser).parseSearchResults(requireNonNull(decompress(INGESTION_BODY))); + verify(transactionConverter).convert("orgId", "id", List.of(mockTxLine)); + verifyNoMoreInteractions(applicationEventPublisher, ingestionRepository, netSuiteParser, transactionConverter); + } + + @Test + void testConintueERPExtraction_exceptionHandling() { + when(ingestionRepository.findById("id")).thenThrow(new RuntimeException("TestException")); + + netSuiteExtractionService.continueERPExtraction("id", "orgId", UserExtractionParameters.builder().from(LocalDate.now()).to(LocalDate.now()).build(), SystemExtractionParameters.builder().build()); + + verify(applicationEventPublisher).publishEvent(any(TransactionBatchFailedEvent.class)); + verify(ingestionRepository).findById("id"); + verifyNoMoreInteractions(applicationEventPublisher, ingestionRepository); + } + +} From 1ce266441565b24cce4e6c65bb915d625a2089d8 Mon Sep 17 00:00:00 2001 From: Kammerlo Date: Mon, 3 Mar 2025 15:33:25 +0100 Subject: [PATCH 05/11] chore: adding tests --- ...ntFcyBalanceZerosOutCheckTaskItemTest.java | 43 +++++++------ ...ntLcyBalanceZerosOutCheckTaskItemTest.java | 60 +++++++++++-------- 2 files changed, 58 insertions(+), 45 deletions(-) diff --git a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountFcyBalanceZerosOutCheckTaskItemTest.java b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountFcyBalanceZerosOutCheckTaskItemTest.java index 7fe7f027..4cd2dcd1 100644 --- a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountFcyBalanceZerosOutCheckTaskItemTest.java +++ b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountFcyBalanceZerosOutCheckTaskItemTest.java @@ -9,6 +9,7 @@ import lombok.val; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.OperationType; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -24,24 +25,26 @@ class AmountFcyBalanceZerosOutCheckTaskItemTest { private PipelineTaskItem taskItem; @BeforeEach - public void setup() { + void setup() { this.taskItem = new AmountFcyBalanceZerosOutCheckTaskItem(); } @Test - public void whenFcyBalanceZerosOut_thenNoViolations() { - val txId = Transaction.id("1", "1"); - val organisationId = "1"; + void whenFcyBalanceZerosOut_thenNoViolations() { + String txId = Transaction.id("1", "1"); + String organisationId = "1"; - val txItem1 = new TransactionItemEntity(); + TransactionItemEntity txItem1 = new TransactionItemEntity(); txItem1.setId(TransactionItem.id(txId, "0")); txItem1.setAmountFcy(new BigDecimal("100")); + txItem1.setOperationType(OperationType.DEBIT); - val txItem2 = new TransactionItemEntity(); + TransactionItemEntity txItem2 = new TransactionItemEntity(); txItem2.setId(TransactionItem.id(txId, "1")); - txItem2.setAmountFcy(new BigDecimal("-100")); + txItem2.setAmountFcy(new BigDecimal("100")); + txItem2.setOperationType(OperationType.CREDIT); - val tx = new TransactionEntity(); + TransactionEntity tx = new TransactionEntity(); tx.setId(txId); tx.setTransactionInternalNumber("1"); tx.setOrganisation(Organisation.builder().id(organisationId).build()); @@ -54,19 +57,21 @@ public void whenFcyBalanceZerosOut_thenNoViolations() { } @Test - public void whenFcyBalanceDoesNotZeroOut_thenViolationGenerated() { - val txId = Transaction.id("2", "1"); - val organisationId = "1"; + void whenFcyBalanceDoesNotZeroOut_thenViolationGenerated() { + String txId = Transaction.id("2", "1"); + String organisationId = "1"; - val txItem1 = new TransactionItemEntity(); + TransactionItemEntity txItem1 = new TransactionItemEntity(); txItem1.setId(TransactionItem.id(txId, "0")); txItem1.setAmountFcy(new BigDecimal("100")); + txItem1.setOperationType(OperationType.DEBIT); - val txItem2 = new TransactionItemEntity(); + TransactionItemEntity txItem2 = new TransactionItemEntity(); txItem2.setId(TransactionItem.id(txId, "1")); - txItem2.setAmountFcy(new BigDecimal("-90")); + txItem2.setAmountFcy(new BigDecimal("90")); + txItem2.setOperationType(OperationType.CREDIT); - val tx = new TransactionEntity(); + TransactionEntity tx = new TransactionEntity(); tx.setId(txId); tx.setTransactionInternalNumber("2"); tx.setOrganisation(Organisation.builder().id(organisationId).build()); @@ -81,11 +86,11 @@ public void whenFcyBalanceDoesNotZeroOut_thenViolationGenerated() { } @Test - public void whenNoTransactionItems_thenNoViolations() { - val txId = Transaction.id("3", "1"); - val organisationId = "1"; + void whenNoTransactionItems_thenNoViolations() { + String txId = Transaction.id("3", "1"); + String organisationId = "1"; - val tx = new TransactionEntity(); + TransactionEntity tx = new TransactionEntity(); tx.setId(txId); tx.setTransactionInternalNumber("3"); tx.setOrganisation(Organisation.builder().id(organisationId).build()); diff --git a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountLcyBalanceZerosOutCheckTaskItemTest.java b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountLcyBalanceZerosOutCheckTaskItemTest.java index 4b13969f..db789e30 100644 --- a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountLcyBalanceZerosOutCheckTaskItemTest.java +++ b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountLcyBalanceZerosOutCheckTaskItemTest.java @@ -9,6 +9,7 @@ import lombok.val; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.OperationType; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -30,18 +31,20 @@ public void setup() { @Test void whenLcyBalanceZerosOut_thenNoViolations() { - val txId = Transaction.id("1", "1"); - val organisationId = "1"; + String txId = Transaction.id("1", "1"); + String organisationId = "1"; - val txItem1 = new TransactionItemEntity(); + TransactionItemEntity txItem1 = new TransactionItemEntity(); txItem1.setId(TransactionItem.id(txId, "0")); txItem1.setAmountLcy(new BigDecimal("100")); + txItem1.setOperationType(OperationType.DEBIT); - val txItem2 = new TransactionItemEntity(); + TransactionItemEntity txItem2 = new TransactionItemEntity(); txItem2.setId(TransactionItem.id(txId, "1")); - txItem2.setAmountLcy(new BigDecimal("-100")); + txItem2.setAmountLcy(new BigDecimal("100")); + txItem2.setOperationType(OperationType.CREDIT); - val tx = new TransactionEntity(); + TransactionEntity tx = new TransactionEntity(); tx.setId(txId); tx.setTransactionInternalNumber("1"); tx.setOrganisation(Organisation.builder().id(organisationId).build()); @@ -55,14 +58,15 @@ void whenLcyBalanceZerosOut_thenNoViolations() { @Test void whenLcyBalanceDoesNotZeroOut_thenViolationGenerated() { - val txId = Transaction.id("2", "1"); - val organisationId = "1"; + String txId = Transaction.id("2", "1"); + String organisationId = "1"; - val txItem1 = new TransactionItemEntity(); + TransactionItemEntity txItem1 = new TransactionItemEntity(); txItem1.setId(TransactionItem.id(txId, "1")); - txItem1.setAmountLcy(new BigDecimal("-99")); + txItem1.setAmountLcy(new BigDecimal("99")); + txItem1.setOperationType(OperationType.CREDIT); - val tx = new TransactionEntity(); + TransactionEntity tx = new TransactionEntity(); tx.setId(txId); tx.setTransactionInternalNumber("2"); tx.setOrganisation(Organisation.builder().id(organisationId).build()); @@ -73,16 +77,16 @@ void whenLcyBalanceDoesNotZeroOut_thenViolationGenerated() { assertThat(tx.getAutomatedValidationStatus()).isEqualTo(FAILED); assertThat(tx.getViolations()).isNotEmpty(); - assertThat(tx.getViolations().size()).isEqualTo(1); + assertThat(tx.getViolations()).hasSize(1); assertThat(tx.getViolations().iterator().next().getCode()).isEqualTo(LCY_BALANCE_MUST_BE_ZERO); } @Test void whenNoTransactionItems_thenNoViolations() { - val txId = Transaction.id("3", "1"); - val organisationId = "1"; + String txId = Transaction.id("3", "1"); + String organisationId = "1"; - val tx = new TransactionEntity(); + TransactionEntity tx = new TransactionEntity(); tx.setId(txId); tx.setTransactionInternalNumber("3"); tx.setOrganisation(Organisation.builder().id(organisationId).build()); @@ -96,14 +100,15 @@ void whenNoTransactionItems_thenNoViolations() { @Test void whenOnlyOneSideOfTransaction_thenViolationGenerated() { - val txId = Transaction.id("4", "1"); - val organisationId = "1"; + String txId = Transaction.id("4", "1"); + String organisationId = "1"; - val txItem1 = new TransactionItemEntity(); + TransactionItemEntity txItem1 = new TransactionItemEntity(); txItem1.setId(TransactionItem.id(txId, "2")); txItem1.setAmountLcy(new BigDecimal("100")); + txItem1.setOperationType(OperationType.DEBIT); - val tx = new TransactionEntity(); + TransactionEntity tx = new TransactionEntity(); tx.setId(txId); tx.setTransactionInternalNumber("4"); tx.setOrganisation(Organisation.builder().id(organisationId).build()); @@ -119,22 +124,25 @@ void whenOnlyOneSideOfTransaction_thenViolationGenerated() { @Test void whenLcyBalanceZerosOutWithMultipleItems_thenNoViolations() { - val txId = Transaction.id("5", "1"); - val organisationId = "1"; + String txId = Transaction.id("5", "1"); + String organisationId = "1"; - val txItem1 = new TransactionItemEntity(); + TransactionItemEntity txItem1 = new TransactionItemEntity(); txItem1.setId(TransactionItem.id(txId, "3")); txItem1.setAmountLcy(new BigDecimal("50")); + txItem1.setOperationType(OperationType.DEBIT); - val txItem2 = new TransactionItemEntity(); + TransactionItemEntity txItem2 = new TransactionItemEntity(); txItem2.setId(TransactionItem.id(txId, "4")); txItem2.setAmountLcy(new BigDecimal("30")); + txItem2.setOperationType(OperationType.DEBIT); - val txItem3 = new TransactionItemEntity(); + TransactionItemEntity txItem3 = new TransactionItemEntity(); txItem3.setId(TransactionItem.id(txId, "5")); - txItem3.setAmountLcy(new BigDecimal("-80")); + txItem3.setAmountLcy(new BigDecimal("80")); + txItem3.setOperationType(OperationType.CREDIT); - val tx = new TransactionEntity(); + TransactionEntity tx = new TransactionEntity(); tx.setId(txId); tx.setTransactionInternalNumber("5"); tx.setOrganisation(Organisation.builder().id(organisationId).build()); From 995cde39f594c45cd4b635563bdcaab52db7635d Mon Sep 17 00:00:00 2001 From: Kammerlo Date: Mon, 3 Mar 2025 15:35:05 +0100 Subject: [PATCH 06/11] chore: spotless --- ...ntFcyBalanceZerosOutCheckTaskItemTest.java | 4 +- ...ntLcyBalanceZerosOutCheckTaskItemTest.java | 4 +- .../internal/TransactionConverter.java | 1 - .../NetSuiteExtractionServiceTest.java | 41 +++++++++---------- 4 files changed, 22 insertions(+), 28 deletions(-) diff --git a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountFcyBalanceZerosOutCheckTaskItemTest.java b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountFcyBalanceZerosOutCheckTaskItemTest.java index 4cd2dcd1..4a7dddc3 100644 --- a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountFcyBalanceZerosOutCheckTaskItemTest.java +++ b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountFcyBalanceZerosOutCheckTaskItemTest.java @@ -7,12 +7,10 @@ import java.math.BigDecimal; import java.util.Set; -import lombok.val; - -import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.OperationType; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.OperationType; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.Transaction; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.TransactionItem; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.TransactionType; diff --git a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountLcyBalanceZerosOutCheckTaskItemTest.java b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountLcyBalanceZerosOutCheckTaskItemTest.java index db789e30..a835087a 100644 --- a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountLcyBalanceZerosOutCheckTaskItemTest.java +++ b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/AmountLcyBalanceZerosOutCheckTaskItemTest.java @@ -7,12 +7,10 @@ import java.math.BigDecimal; import java.util.Set; -import lombok.val; - -import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.OperationType; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.OperationType; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.Transaction; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.TransactionItem; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.TransactionType; diff --git a/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverter.java b/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverter.java index 414dbea7..385b6bc0 100644 --- a/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverter.java +++ b/netsuite_altavia_erp_adapter/src/main/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverter.java @@ -26,7 +26,6 @@ import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.FinancialPeriodSource; import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.Transactions; import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.TxLine; -import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.util.MoreBigDecimal; import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.util.MoreString; import org.cardanofoundation.lob.app.support.collections.Optionals; diff --git a/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/NetSuiteExtractionServiceTest.java b/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/NetSuiteExtractionServiceTest.java index e2650e9e..454461d3 100644 --- a/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/NetSuiteExtractionServiceTest.java +++ b/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/NetSuiteExtractionServiceTest.java @@ -3,7 +3,6 @@ import static java.util.Objects.requireNonNull; import static org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.util.MoreCompress.decompress; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -16,15 +15,6 @@ import java.util.Optional; import java.util.Set; -import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.FatalError; -import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.SystemExtractionParameters; -import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.Transaction; -import org.cardanofoundation.lob.app.accounting_reporting_core.domain.event.extraction.TransactionBatchChunkEvent; -import org.cardanofoundation.lob.app.accounting_reporting_core.domain.event.extraction.TransactionBatchFailedEvent; -import org.cardanofoundation.lob.app.accounting_reporting_core.domain.event.extraction.TransactionBatchStartedEvent; -import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.Transactions; -import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.TxLine; -import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.entity.NetSuiteIngestionEntity; import org.springframework.context.ApplicationEventPublisher; import io.vavr.control.Either; @@ -37,14 +27,23 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.FatalError; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.SystemExtractionParameters; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.Transaction; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.UserExtractionParameters; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.event.extraction.TransactionBatchChunkEvent; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.event.extraction.TransactionBatchFailedEvent; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.event.extraction.TransactionBatchStartedEvent; import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.client.NetSuiteClient; +import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.Transactions; +import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.TxLine; +import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.entity.NetSuiteIngestionEntity; import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.repository.IngestionRepository; @ExtendWith(MockitoExtension.class) -public class NetSuiteExtractionServiceTest { +class NetSuiteExtractionServiceTest { - private final String INGESTION_BODY = "1f8b08000000000000ffed55c18ed33010bdef57583937959d2d42f4062b16b442805838210e537bd25a9bd8d1d8e9365af5df99a4dd264d5b71022144955aedcc7bf6ccf33ce5e94a88a4f484c95ce450049cb481c23a0c1cf9ce7f8478ea560e877a11acb1408df32b8b04a4570dc3d4e419119baadd29b9f33539289243c240444dc8ab69f399cc5ea4324b3329d4cb393f52f6d802422cbdb1b945d3f27e4988046e009ca52a4baf959072de3d3d10dd61c36376001dad77ae2e17485d039fbe7df9f8fa43c69f41612c0b27e511d5760dddbd4da594aac7aef92c4f5374d1c6668739496a5f56e01a07e5a8248315502c997c2cf400a259a570311b61a3bd19ed0a5afbdac569dfe54c49a5f83bd4e880da57f5d54728c43bf22108ebb8641439f952042850f85c2cbd3741f0058880b4b61a83988bfb7d7210fa4c7e6d038b1c44ee49205009f48046e475ac09056e2a7481c76e5c4909d68d7aaf89d0e9aee7fb47cb85ddf245e81e70b3074c43532e7cd1e26ededf0ee660a357e0962cdd6e18d474a880c1858df906caf6f4d1c984e638a7e429f732f398d767cbba88b6b7570b18941b22c43a10e66d1caa8a95641b9ddc9875115bd7eda64d5dcfb2a4836c27ff6d7cc6c6eadfb271f6676cfca6b68511556fe654f0783e58b714848f40e66f34f0c8a4a72ebe68e0b3cc73bcdfe1e0997ab57730af3fba37f31a8a1a5758540cd8193a697fb580edd5f62767da246cce070000"; + private final String ingestionBody = "1f8b08000000000000ffed55c18ed33010bdef57583937959d2d42f4062b16b442805838210e537bd25a9bd8d1d8e9365af5df99a4dd264d5b71022144955aedcc7bf6ccf33ce5e94a88a4f484c95ce450049cb481c23a0c1cf9ce7f8478ea560e877a11acb1408df32b8b04a4570dc3d4e419119baadd29b9f33539289243c240444dc8ab69f399cc5ea4324b3329d4cb393f52f6d802422cbdb1b945d3f27e4988046e009ca52a4baf959072de3d3d10dd61c36376001dad77ae2e17485d039fbe7df9f8fa43c69f41612c0b27e511d5760dddbd4da594aac7aef92c4f5374d1c6668739496a5f56e01a07e5a8248315502c997c2cf400a259a570311b61a3bd19ed0a5afbdac569dfe54c49a5f83bd4e880da57f5d54728c43bf22108ebb8641439f952042850f85c2cbd3741f0058880b4b61a83988bfb7d7210fa4c7e6d038b1c44ee49205009f48046e475ac09056e2a7481c76e5c4909d68d7aaf89d0e9aee7fb47cb85ddf245e81e70b3074c43532e7cd1e26ededf0ee660a357e0962cdd6e18d474a880c1858df906caf6f4d1c984e638a7e429f732f398d767cbba88b6b7570b18941b22c43a10e66d1caa8a95641b9ddc9875115bd7eda64d5dcfb2a4836c27ff6d7cc6c6eadfb271f6676cfca6b68511556fe654f0783e58b714848f40e66f34f0c8a4a72ebe68e0b3cc73bcdfe1e0997ab57730af3fba37f31a8a1a5758540cd8193a697fb580edd5f62767da246cce070000"; @Mock private IngestionRepository ingestionRepository; @@ -162,8 +161,8 @@ void testContinueERPExtraction_orgIdMismatch() { @Test void testContinueERPExtraction_parseSearchFailed() { - when(ingestionRepository.findById("id")).thenReturn(Optional.of(new NetSuiteIngestionEntity("id", "adapterInstanceId", INGESTION_BODY,"ingestionBodyDebug", "ingestionChecksum"))); - when(netSuiteParser.parseSearchResults(requireNonNull(decompress(INGESTION_BODY)))).thenReturn(Either.left(Problem.builder() + when(ingestionRepository.findById("id")).thenReturn(Optional.of(new NetSuiteIngestionEntity("id", "adapterInstanceId", ingestionBody,"ingestionBodyDebug", "ingestionChecksum"))); + when(netSuiteParser.parseSearchResults(requireNonNull(decompress(ingestionBody)))).thenReturn(Either.left(Problem.builder() .withStatus(Status.BAD_REQUEST) .withTitle("testTitle") .withDetail("testDetail") @@ -173,28 +172,28 @@ void testContinueERPExtraction_parseSearchFailed() { verify(applicationEventPublisher).publishEvent(any(TransactionBatchFailedEvent.class)); verify(ingestionRepository).findById("id"); - verify(netSuiteParser).parseSearchResults(requireNonNull(decompress(INGESTION_BODY))); + verify(netSuiteParser).parseSearchResults(requireNonNull(decompress(ingestionBody))); verifyNoMoreInteractions(applicationEventPublisher, ingestionRepository, netSuiteParser); } @Test void testContinueERPExtraction_transactionConvertFailed() { - when(ingestionRepository.findById("id")).thenReturn(Optional.of(new NetSuiteIngestionEntity("id", "adapterInstanceId", INGESTION_BODY,"ingestionBodyDebug", "ingestionChecksum"))); - when(netSuiteParser.parseSearchResults(requireNonNull(decompress(INGESTION_BODY)))).thenReturn(Either.right(List.of())); + when(ingestionRepository.findById("id")).thenReturn(Optional.of(new NetSuiteIngestionEntity("id", "adapterInstanceId", ingestionBody,"ingestionBodyDebug", "ingestionChecksum"))); + when(netSuiteParser.parseSearchResults(requireNonNull(decompress(ingestionBody)))).thenReturn(Either.right(List.of())); when(transactionConverter.convert("org", "id", List.of())).thenReturn(Either.left(new FatalError(FatalError.Code.ADAPTER_ERROR, "test", Map.of()))); netSuiteExtractionService.continueERPExtraction("id", "orgId", UserExtractionParameters.builder().organisationId("org").from(LocalDate.now()).to(LocalDate.now()).build(), SystemExtractionParameters.builder().organisationId("org").build()); verify(applicationEventPublisher).publishEvent(any(TransactionBatchFailedEvent.class)); verify(ingestionRepository).findById("id"); - verify(netSuiteParser).parseSearchResults(requireNonNull(decompress(INGESTION_BODY))); + verify(netSuiteParser).parseSearchResults(requireNonNull(decompress(ingestionBody))); verifyNoMoreInteractions(applicationEventPublisher, ingestionRepository, netSuiteParser); } @Test void testContinueERPExtraction_transactionConvertSuccess() { TxLine mockTxLine = mock(TxLine.class); - when(ingestionRepository.findById("id")).thenReturn(Optional.of(new NetSuiteIngestionEntity("id", "adapterInstanceId", INGESTION_BODY,"ingestionBodyDebug", "ingestionChecksum"))); - when(netSuiteParser.parseSearchResults(requireNonNull(decompress(INGESTION_BODY)))).thenReturn(Either.right(List.of(mockTxLine))); + when(ingestionRepository.findById("id")).thenReturn(Optional.of(new NetSuiteIngestionEntity("id", "adapterInstanceId", ingestionBody,"ingestionBodyDebug", "ingestionChecksum"))); + when(netSuiteParser.parseSearchResults(requireNonNull(decompress(ingestionBody)))).thenReturn(Either.right(List.of(mockTxLine))); when(transactionConverter.convert("orgId", "id", List.of(mockTxLine))).thenReturn(Either.right(new Transactions("org", Set.of()))); when(extractionParametersFilteringService.applyExtractionParameters(any(), any(), any())).thenReturn(Set.of(Transaction.builder().id("id1").build(), Transaction.builder().id("id2").build(), Transaction.builder().id("id3").build())); @@ -202,7 +201,7 @@ void testContinueERPExtraction_transactionConvertSuccess() { verify(applicationEventPublisher, times(3)).publishEvent(any(TransactionBatchChunkEvent.class)); verify(ingestionRepository).findById("id"); - verify(netSuiteParser).parseSearchResults(requireNonNull(decompress(INGESTION_BODY))); + verify(netSuiteParser).parseSearchResults(requireNonNull(decompress(ingestionBody))); verify(transactionConverter).convert("orgId", "id", List.of(mockTxLine)); verifyNoMoreInteractions(applicationEventPublisher, ingestionRepository, netSuiteParser, transactionConverter); } From de655df6696c0746490bbafc4bf222b9b857bf20 Mon Sep 17 00:00:00 2001 From: Kammerlo Date: Mon, 3 Mar 2025 15:53:26 +0100 Subject: [PATCH 07/11] removed abs from blockchain publisher --- .../service/API1MetadataSerialiser.java | 2 +- .../internal/TransactionConverterTest.java | 62 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverterTest.java diff --git a/blockchain_publisher/src/main/java/org/cardanofoundation/lob/app/blockchain_publisher/service/API1MetadataSerialiser.java b/blockchain_publisher/src/main/java/org/cardanofoundation/lob/app/blockchain_publisher/service/API1MetadataSerialiser.java index b6da6688..9afc1493 100644 --- a/blockchain_publisher/src/main/java/org/cardanofoundation/lob/app/blockchain_publisher/service/API1MetadataSerialiser.java +++ b/blockchain_publisher/src/main/java/org/cardanofoundation/lob/app/blockchain_publisher/service/API1MetadataSerialiser.java @@ -152,7 +152,7 @@ private static MetadataMap serialise(TransactionItemEntity transactionItemEntity val metadataMap = MetadataBuilder.createMap(); metadataMap.put("id", transactionItemEntity.getId()); - metadataMap.put("amount", BigDecimals.normaliseEngineeringString(transactionItemEntity.getAmountFcy().abs())); // TODO ABS function here is not a mistake but we need to revisit journals properly + metadataMap.put("amount", BigDecimals.normaliseEngineeringString(transactionItemEntity.getAmountFcy())); transactionItemEntity.getAccountEvent().ifPresent(accountEvent -> metadataMap.put("event", serialise(accountEvent))); transactionItemEntity.getProject().ifPresent(project -> metadataMap.put("project", serialise(project))); diff --git a/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverterTest.java b/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverterTest.java new file mode 100644 index 00000000..527912b6 --- /dev/null +++ b/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverterTest.java @@ -0,0 +1,62 @@ +package org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.service.internal; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.Optional; + +import jakarta.validation.Validator; + +import io.vavr.control.Either; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.FatalError; +import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.FinancialPeriodSource; +import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.Transactions; +import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.TxLine; +import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.entity.CodeMappingType; + +@ExtendWith(MockitoExtension.class) +class TransactionConverterTest { + + @Mock + private Validator validator; + @Mock + private CodesMappingService codesMappingService; + @Mock + private PreprocessorService preprocessorService; + @Mock + private TransactionTypeMapper transactionTypeMapper; + @Mock + private FinancialPeriodSource financialPeriodSource; + private final String netsuiteInstanceId = "netsuiteInstanceId"; + + private TransactionConverter transactionConverter; + + @BeforeEach + void setUp() { + transactionConverter = new TransactionConverter(validator, codesMappingService, preprocessorService, transactionTypeMapper, netsuiteInstanceId, financialPeriodSource); + } + + @Test + void testConvert_OrganisationIdFailed() { + TxLine mockTxLine = mock(TxLine.class); + when(codesMappingService.getCodeMapping(netsuiteInstanceId, 10L, CodeMappingType.ORGANISATION)).thenReturn(Optional.empty()); + when(mockTxLine.subsidiary()).thenReturn(10L); + + Either org = transactionConverter.convert("org", "10", List.of(mockTxLine)); + + assertThat(org.isLeft()).isTrue(); + } + + + + +} From 259779c6e518b737be2500e0671c5025d5700a1a Mon Sep 17 00:00:00 2001 From: Kammerlo Date: Mon, 3 Mar 2025 16:49:54 +0100 Subject: [PATCH 08/11] chore: extend tests --- .../internal/TransactionConverterTest.java | 159 +++++++++++++++++- 1 file changed, 156 insertions(+), 3 deletions(-) diff --git a/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverterTest.java b/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverterTest.java index 527912b6..abbd4549 100644 --- a/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverterTest.java +++ b/netsuite_altavia_erp_adapter/src/test/java/org/cardanofoundation/lob/app/netsuite_altavia_erp_adapter/service/internal/TransactionConverterTest.java @@ -4,20 +4,31 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.math.BigDecimal; +import java.time.LocalDate; import java.util.List; import java.util.Optional; +import java.util.Set; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Path; import jakarta.validation.Validator; import io.vavr.control.Either; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.FatalError; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.OperationType; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.Transaction; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.TransactionItem; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.TransactionType; +import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.FieldType; import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.FinancialPeriodSource; import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.Transactions; import org.cardanofoundation.lob.app.netsuite_altavia_erp_adapter.domain.core.TxLine; @@ -34,9 +45,8 @@ class TransactionConverterTest { private PreprocessorService preprocessorService; @Mock private TransactionTypeMapper transactionTypeMapper; - @Mock - private FinancialPeriodSource financialPeriodSource; - private final String netsuiteInstanceId = "netsuiteInstanceId"; + private final FinancialPeriodSource financialPeriodSource = FinancialPeriodSource.IMPLICIT; + private final String netsuiteInstanceId = "test-instance"; private TransactionConverter transactionConverter; @@ -56,7 +66,150 @@ void testConvert_OrganisationIdFailed() { assertThat(org.isLeft()).isTrue(); } + @Test + void testConvert_emptyType() { + TxLine mockTxLine = mock(TxLine.class); + when(codesMappingService.getCodeMapping(netsuiteInstanceId, 10L, CodeMappingType.ORGANISATION)).thenReturn(Optional.of("orgID")); + when(mockTxLine.subsidiary()).thenReturn(10L); + when(mockTxLine.transactionNumber()).thenReturn("transactionID"); + when(mockTxLine.type()).thenReturn("type"); + when(transactionTypeMapper.apply("type")).thenReturn(Optional.empty()); + + Either org = transactionConverter.convert("orgID", "10", List.of(mockTxLine)); + + assertThat(org.isLeft()).isTrue(); + + } + + @Test + void testConvert_validationError() { + TxLine mockTxLine = mock(TxLine.class); + ConstraintViolation mockViolation = mock(ConstraintViolation.class); + Path mockPath = mock(Path.class); + when(mockPath.toString()).thenReturn("path"); + when(mockViolation.getRootBean()).thenReturn(mockTxLine); + when(mockViolation.getMessage()).thenReturn("Message"); + when(mockViolation.getPropertyPath()).thenReturn(mockPath); + when(mockViolation.getInvalidValue()).thenReturn("invalidaValue"); + when(codesMappingService.getCodeMapping(netsuiteInstanceId, 10L, CodeMappingType.ORGANISATION)).thenReturn(Optional.of("orgID")); + when(mockTxLine.subsidiary()).thenReturn(10L); + when(mockTxLine.transactionNumber()).thenReturn("transactionID"); + when(mockTxLine.type()).thenReturn("type"); + when(mockTxLine.date()).thenReturn(LocalDate.now()); + when(mockTxLine.exchangeRate()).thenReturn(BigDecimal.ONE); + when(validator.validate(mockTxLine)).thenReturn(Set.of(mockViolation)); + when(transactionTypeMapper.apply("type")).thenReturn(Optional.of(TransactionType.Transfer)); + + Either org = transactionConverter.convert("orgID", "10", List.of(mockTxLine)); + + assertThat(org.isLeft()).isTrue(); + } + + @Test + void testConvert_SuccesNoEntries() { + TxLine mockTxLine = mock(TxLine.class); + when(codesMappingService.getCodeMapping(netsuiteInstanceId, 10L, CodeMappingType.ORGANISATION)).thenReturn(Optional.of("orgID")); + when(mockTxLine.subsidiary()).thenReturn(10L); + when(mockTxLine.transactionNumber()).thenReturn("transactionID"); + when(mockTxLine.type()).thenReturn("type"); + when(mockTxLine.date()).thenReturn(LocalDate.now()); + when(mockTxLine.exchangeRate()).thenReturn(BigDecimal.ONE); + when(mockTxLine.accountMain()).thenReturn("accountMain"); + when(validator.validate(mockTxLine)).thenReturn(Set.of()); + when(transactionTypeMapper.apply("type")).thenReturn(Optional.of(TransactionType.Transfer)); + when(preprocessorService.preProcess("accountMain", FieldType.CHART_OF_ACCOUNT)).thenReturn(Either.right("Success")); + + Either org = transactionConverter.convert("orgID", "10", List.of(mockTxLine)); + + assertThat(org.isRight()).isTrue(); + Transactions transactions = org.get(); + Assertions.assertEquals(1, transactions.transactions().size()); + Transaction next = transactions.transactions().stream().iterator().next(); + Assertions.assertEquals("transactionID", next.getInternalTransactionNumber()); + Assertions.assertEquals("orgID", next.getOrganisation().getId()); + Assertions.assertEquals(TransactionType.Transfer, next.getTransactionType()); + Assertions.assertEquals(LocalDate.now(), next.getEntryDate()); + Assertions.assertEquals(0, next.getItems().size()); + } + @Test + void testConvert_ErrorCreditAndDebitSet() { + TxLine mockTxLine = mock(TxLine.class); + when(codesMappingService.getCodeMapping(netsuiteInstanceId, 10L, CodeMappingType.ORGANISATION)).thenReturn(Optional.of("orgID")); + when(mockTxLine.subsidiary()).thenReturn(10L); + when(mockTxLine.transactionNumber()).thenReturn("transactionID"); + when(mockTxLine.type()).thenReturn("type"); + when(mockTxLine.date()).thenReturn(LocalDate.now()); + when(mockTxLine.exchangeRate()).thenReturn(BigDecimal.ONE); + when(mockTxLine.accountMain()).thenReturn("accountMain"); + when(mockTxLine.amountCredit()).thenReturn(BigDecimal.ONE); + when(mockTxLine.amountDebit()).thenReturn(BigDecimal.ONE); + when(validator.validate(mockTxLine)).thenReturn(Set.of()); + when(transactionTypeMapper.apply("type")).thenReturn(Optional.of(TransactionType.Transfer)); + when(preprocessorService.preProcess("accountMain", FieldType.CHART_OF_ACCOUNT)).thenReturn(Either.right("Success")); + + Either org = transactionConverter.convert("orgID", "10", List.of(mockTxLine)); + + assertThat(org.isLeft()).isTrue(); + } + @Test + void testConvert_SuccesCreditAndDebitEntry() { + TxLine mockTxLine = mock(TxLine.class); + when(codesMappingService.getCodeMapping(netsuiteInstanceId, 10L, CodeMappingType.ORGANISATION)).thenReturn(Optional.of("orgID")); + when(mockTxLine.subsidiary()).thenReturn(10L); + when(mockTxLine.transactionNumber()).thenReturn("transactionID"); + when(mockTxLine.type()).thenReturn("type"); + when(mockTxLine.date()).thenReturn(LocalDate.now()); + when(mockTxLine.exchangeRate()).thenReturn(BigDecimal.ONE); + when(mockTxLine.accountMain()).thenReturn("accountMain"); + when(mockTxLine.amountCredit()).thenReturn(BigDecimal.ONE); + when(validator.validate(mockTxLine)).thenReturn(Set.of()); + when(transactionTypeMapper.apply("type")).thenReturn(Optional.of(TransactionType.Transfer)); + when(preprocessorService.preProcess("accountMain", FieldType.CHART_OF_ACCOUNT)).thenReturn(Either.right("Success")); + + Either org = transactionConverter.convert("orgID", "10", List.of(mockTxLine)); + + assertThat(org.isRight()).isTrue(); + Transactions transactions = org.get(); + Assertions.assertEquals(1, transactions.transactions().size()); + Transaction next = transactions.transactions().stream().iterator().next(); + Assertions.assertEquals("transactionID", next.getInternalTransactionNumber()); + Assertions.assertEquals("orgID", next.getOrganisation().getId()); + Assertions.assertEquals(TransactionType.Transfer, next.getTransactionType()); + Assertions.assertEquals(LocalDate.now(), next.getEntryDate()); + Assertions.assertEquals(1, next.getItems().size()); + TransactionItem txItem = next.getItems().stream().iterator().next(); + Assertions.assertEquals(OperationType.CREDIT, txItem.getOperationType()); + } + @Test + void testConvert_SuccesDebitEntry() { + TxLine mockTxLine = mock(TxLine.class); + when(codesMappingService.getCodeMapping(netsuiteInstanceId, 10L, CodeMappingType.ORGANISATION)).thenReturn(Optional.of("orgID")); + when(mockTxLine.subsidiary()).thenReturn(10L); + when(mockTxLine.transactionNumber()).thenReturn("transactionID"); + when(mockTxLine.type()).thenReturn("type"); + when(mockTxLine.date()).thenReturn(LocalDate.now()); + when(mockTxLine.exchangeRate()).thenReturn(BigDecimal.ONE); + when(mockTxLine.accountMain()).thenReturn("accountMain"); + when(mockTxLine.amountDebit()).thenReturn(BigDecimal.ONE); + when(validator.validate(mockTxLine)).thenReturn(Set.of()); + when(transactionTypeMapper.apply("type")).thenReturn(Optional.of(TransactionType.Transfer)); + when(preprocessorService.preProcess("accountMain", FieldType.CHART_OF_ACCOUNT)).thenReturn(Either.right("Success")); + + Either org = transactionConverter.convert("orgID", "10", List.of(mockTxLine)); + + assertThat(org.isRight()).isTrue(); + Transactions transactions = org.get(); + Assertions.assertEquals(1, transactions.transactions().size()); + Transaction next = transactions.transactions().stream().iterator().next(); + Assertions.assertEquals("transactionID", next.getInternalTransactionNumber()); + Assertions.assertEquals("orgID", next.getOrganisation().getId()); + Assertions.assertEquals(TransactionType.Transfer, next.getTransactionType()); + Assertions.assertEquals(LocalDate.now(), next.getEntryDate()); + Assertions.assertEquals(1, next.getItems().size()); + TransactionItem txItem = next.getItems().stream().iterator().next(); + Assertions.assertEquals(OperationType.DEBIT, txItem.getOperationType()); + } } From 46e30d93fbfd8fc2b9b2dae690a1cd6081bb3894 Mon Sep 17 00:00:00 2001 From: Kammerlo Date: Mon, 3 Mar 2025 17:02:16 +0100 Subject: [PATCH 09/11] chore: adding tests --- .../internal/TransactionConverterTest.java | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionConverterTest.java diff --git a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionConverterTest.java b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionConverterTest.java new file mode 100644 index 00000000..1b5cce4d --- /dev/null +++ b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionConverterTest.java @@ -0,0 +1,99 @@ +package org.cardanofoundation.lob.app.accounting_reporting_core.service.internal; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Optional; +import java.util.Set; + +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.SystemExtractionParameters; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.Transaction; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.TransactionType; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.UserExtractionParameters; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.FilteringParameters; +import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionEntity; + +@ExtendWith(MockitoExtension.class) +class TransactionConverterTest { + + @Mock + private CoreCurrencyService coreCurrencyService; + @Mock + OrganisationConverter organisationConverter; + + @InjectMocks + private TransactionConverter transactionConverter; + + private UserExtractionParameters userParams; + private SystemExtractionParameters systemParams; + private Transaction transaction; + private TransactionEntity transactionEntity; + + @BeforeEach + void setUp() { + userParams = mock(UserExtractionParameters.class); + systemParams = mock(SystemExtractionParameters.class); + transaction = mock(Transaction.class); + transactionEntity = mock(TransactionEntity.class); + } + + @Test + void testConvertToDbDetached_WithSystemAndUserParams() { + when(userParams.getOrganisationId()).thenReturn("org123"); + FilteringParameters result = transactionConverter.convertToDbDetached(systemParams, userParams); + Assertions.assertNotNull(result); + Assertions.assertEquals("org123", result.getOrganisationId()); + } + + @Test + void testConvertToDbDetached_WithOptionalSystemParams() { + when(userParams.getOrganisationId()).thenReturn("org123"); + Optional optionalParams = Optional.of(systemParams); + FilteringParameters result = transactionConverter.convertToDbDetached(userParams, optionalParams); + Assertions.assertNotNull(result); + Assertions.assertEquals("org123", result.getOrganisationId()); + } + + @Test + void testConvertToDbDetached_UserParamsOnly() { + when(userParams.getOrganisationId()).thenReturn("org123"); + FilteringParameters result = transactionConverter.convertToDbDetached(userParams); + Assertions.assertNotNull(result); + Assertions.assertEquals("org123", result.getOrganisationId()); + } + + @Test + void testConvertToDbDetached_SetOfTransactions() { + Set transactions = Set.of(transaction); + Set result = transactionConverter.convertToDbDetached(transactions); + Assertions.assertNotNull(result); + Assertions.assertEquals(1, result.size()); + } + + @Test + void testConvertFromDb_SetOfTransactionEntities() { + Set transactionEntities = Set.of(transactionEntity); + Set result = transactionConverter.convertFromDb(transactionEntities); + Assertions.assertNotNull(result); + Assertions.assertEquals(1, result.size()); + } + + @Test + void testCopyFields() { + TransactionEntity attached = new TransactionEntity(); + TransactionEntity detached = new TransactionEntity(); + detached.setTransactionType(TransactionType.BillCredit); + + transactionConverter.copyFields(attached, detached); + Assertions.assertEquals(TransactionType.BillCredit, attached.getTransactionType()); + } +} From f06d6e680487a58284d7de0c47b7196a4143ded1 Mon Sep 17 00:00:00 2001 From: Kammerlo Date: Mon, 3 Mar 2025 17:08:48 +0100 Subject: [PATCH 10/11] removing unused JournalTask --- .../config/BusinessRulesConfig.java | 1 - ...urnalAccountAmountsEnrichmentTaskItem.java | 25 ------- ...lAccountAmountsEnrichmentTaskItemTest.java | 71 ------------------- .../internal/TransactionConverterTest.java | 8 --- 4 files changed, 105 deletions(-) delete mode 100644 accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountAmountsEnrichmentTaskItem.java delete mode 100644 accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountAmountsEnrichmentTaskItemTest.java diff --git a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/config/BusinessRulesConfig.java b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/config/BusinessRulesConfig.java index b947288a..1c0dd62d 100644 --- a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/config/BusinessRulesConfig.java +++ b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/config/BusinessRulesConfig.java @@ -70,7 +70,6 @@ private PipelineTask preCleansingPipelineTask() { return new DefaultPipelineTask(List.of( new DiscardZeroBalanceTxItemsTaskItem(), new JournalAccountCreditEnrichmentTaskItem(organisationPublicApi) - //new JournalAccountAmountsEnrichmentTaskItem() // this must be after JournalAccountCreditEnrichmentTaskItem )); } diff --git a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountAmountsEnrichmentTaskItem.java b/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountAmountsEnrichmentTaskItem.java deleted file mode 100644 index 4b852b70..00000000 --- a/accounting_reporting_core/src/main/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountAmountsEnrichmentTaskItem.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cardanofoundation.lob.app.accounting_reporting_core.service.business_rules.items; - -import static org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.TransactionType.Journal; - -import lombok.extern.slf4j.Slf4j; -import lombok.val; - -import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionEntity; - -@Slf4j -public class JournalAccountAmountsEnrichmentTaskItem implements PipelineTaskItem { - - @Override - public void run(TransactionEntity tx) { - if (tx.getTransactionType() != Journal) { - return; - } - - for (val txItem : tx.getItems()) { - txItem.setAmountFcy(txItem.getAmountFcy().abs()); - txItem.setAmountLcy(txItem.getAmountLcy().abs()); - } - } - -} diff --git a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountAmountsEnrichmentTaskItemTest.java b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountAmountsEnrichmentTaskItemTest.java deleted file mode 100644 index 0444d6b9..00000000 --- a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/business_rules/items/JournalAccountAmountsEnrichmentTaskItemTest.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.cardanofoundation.lob.app.accounting_reporting_core.service.business_rules.items; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.TransactionType.Journal; -import static org.mockito.Mockito.*; - -import java.math.BigDecimal; -import java.util.Set; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import org.cardanofoundation.lob.app.accounting_reporting_core.domain.core.TransactionType; -import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionEntity; -import org.cardanofoundation.lob.app.accounting_reporting_core.domain.entity.TransactionItemEntity; - -class JournalAccountAmountsEnrichmentTaskItemTest { - - private JournalAccountAmountsEnrichmentTaskItem taskItem; - - @BeforeEach - void setUp() { - taskItem = new JournalAccountAmountsEnrichmentTaskItem(); - } - - @Test - void shouldNotProcessNonJournalTransaction() { - // Given - TransactionEntity transaction = mock(TransactionEntity.class); - when(transaction.getTransactionType()).thenReturn(TransactionType.FxRevaluation); // A type other than Journal - - // When - taskItem.run(transaction); - - // Then - verify(transaction, times(1)).getTransactionType(); - verifyNoMoreInteractions(transaction); - } - - @Test - void shouldProcessJournalTransaction() { - // Given - TransactionItemEntity item1 = new TransactionItemEntity(); - item1.setId("1"); - item1.setAmountFcy(new BigDecimal("-100.00")); - item1.setAmountLcy(new BigDecimal("-200.00")); - - TransactionItemEntity item2 = new TransactionItemEntity(); - item2.setId("2"); - item2.setAmountFcy(new BigDecimal("300.00")); - item2.setAmountLcy(new BigDecimal("400.00")); - - TransactionEntity transaction = mock(TransactionEntity.class); - when(transaction.getTransactionType()).thenReturn(Journal); - when(transaction.getItems()).thenReturn(Set.of(item1, item2)); - - // When - taskItem.run(transaction); - - // Then - assertThat(item1.getAmountFcy()).isEqualByComparingTo("100.00"); - assertThat(item1.getAmountLcy()).isEqualByComparingTo("200.00"); - assertThat(item2.getAmountFcy()).isEqualByComparingTo("300.00"); - assertThat(item2.getAmountLcy()).isEqualByComparingTo("400.00"); - - verify(transaction, times(1)).getTransactionType(); - verify(transaction, times(1)).getItems(); - verifyNoMoreInteractions(transaction); - } - -} diff --git a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionConverterTest.java b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionConverterTest.java index 1b5cce4d..599c8400 100644 --- a/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionConverterTest.java +++ b/accounting_reporting_core/src/test/java/org/cardanofoundation/lob/app/accounting_reporting_core/service/internal/TransactionConverterTest.java @@ -79,14 +79,6 @@ void testConvertToDbDetached_SetOfTransactions() { Assertions.assertEquals(1, result.size()); } - @Test - void testConvertFromDb_SetOfTransactionEntities() { - Set transactionEntities = Set.of(transactionEntity); - Set result = transactionConverter.convertFromDb(transactionEntities); - Assertions.assertNotNull(result); - Assertions.assertEquals(1, result.size()); - } - @Test void testCopyFields() { TransactionEntity attached = new TransactionEntity(); From 810837023ae33fb513cda6da8edd4e484b795c4f Mon Sep 17 00:00:00 2001 From: Kammerlo Date: Wed, 5 Mar 2025 14:45:13 +0100 Subject: [PATCH 11/11] reverted nullable annotation --- .../domain/entity/txs/TransactionItemEntity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/blockchain_publisher/src/main/java/org/cardanofoundation/lob/app/blockchain_publisher/domain/entity/txs/TransactionItemEntity.java b/blockchain_publisher/src/main/java/org/cardanofoundation/lob/app/blockchain_publisher/domain/entity/txs/TransactionItemEntity.java index 8f5d2559..8792d9a1 100644 --- a/blockchain_publisher/src/main/java/org/cardanofoundation/lob/app/blockchain_publisher/domain/entity/txs/TransactionItemEntity.java +++ b/blockchain_publisher/src/main/java/org/cardanofoundation/lob/app/blockchain_publisher/domain/entity/txs/TransactionItemEntity.java @@ -76,6 +76,7 @@ public class TransactionItemEntity extends CommonDateOnlyEntity implements Persi @AttributeOverride(name = "counterparty.customerCode", column = @Column(name = "document_counterparty_customer_code")), @AttributeOverride(name = "counterparty.type", column = @Column(name = "document_counterparty_type")), }) + @Nullable private Document document; public Optional getAccountEvent() {