You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by vi...@apache.org on 2023/01/06 20:17:42 UTC

[fineract] branch develop updated: Fix to use notes in Savings Accounts (#2857)

This is an automated email from the ASF dual-hosted git repository.

victorromero pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new a25acf0ab Fix to use notes in Savings Accounts (#2857)
a25acf0ab is described below

commit a25acf0abdd47c8e134710cbee258cd666784ae4
Author: José Alberto Hernández <44...@users.noreply.github.com>
AuthorDate: Fri Jan 6 14:17:35 2023 -0600

    Fix to use notes in Savings Accounts (#2857)
    
    Co-authored-by: Jose Alberto Hernandez <al...@MacBook-Pro.local>
---
 .../portfolio/note/api/NotesApiResource.java       |   4 +-
 .../portfolio/note/domain/NoteRepository.java      |   2 +-
 .../note/service/NoteReadPlatformServiceImpl.java  |   2 +-
 .../NoteWritePlatformServiceJpaRepositoryImpl.java | 139 ++++++++++-----------
 .../note/starter/NoteAutoConfiguration.java        |   5 +-
 .../fineract/integrationtests/NotesTest.java       |  35 ++++++
 .../integrationtests/common/NotesHelper.java       |  22 ++++
 7 files changed, 129 insertions(+), 80 deletions(-)

diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/api/NotesApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/api/NotesApiResource.java
index c66c8ee1e..10d7aa8fc 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/api/NotesApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/api/NotesApiResource.java
@@ -71,8 +71,8 @@ public class NotesApiResource {
     public static final String GROUPNOTE = "GROUPNOTE";
     public static final String INVALIDNOTE = "INVALIDNOTE";
     private static final Set<String> NOTE_DATA_PARAMETERS = new HashSet<>(
-            Arrays.asList("id", "clientId", "groupId", "loanId", "loanTransactionId", "depositAccountId", "savingAccountId", "noteType",
-                    "note", "createdById", "createdByUsername", "createdOn", "updatedById", "updatedByUsername", "updatedOn"));
+            Arrays.asList("id", "resourceId", "clientId", "groupId", "loanId", "loanTransactionId", "depositAccountId", "savingAccountId",
+                    "noteType", "note", "createdById", "createdByUsername", "createdOn", "updatedById", "updatedByUsername", "updatedOn"));
     private final PlatformSecurityContext context;
     private final NoteReadPlatformService readPlatformService;
     private final DefaultToApiJsonSerializer<NoteData> toApiJsonSerializer;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/domain/NoteRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/domain/NoteRepository.java
index 94f89770e..f609eeae0 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/domain/NoteRepository.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/domain/NoteRepository.java
@@ -45,5 +45,5 @@ public interface NoteRepository extends JpaRepository<Note, Long>, JpaSpecificat
 
     List<Note> findBySavingsAccount(SavingsAccount savingAccount);
 
-    // Note findBySavingsAccountIdAndId(Long savingAccountId, Long id);
+    Note findBySavingsAccountAndId(SavingsAccount savingAccount, Long id);
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteReadPlatformServiceImpl.java
index 2722cb5cc..29bc14226 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteReadPlatformServiceImpl.java
@@ -132,7 +132,7 @@ public class NoteReadPlatformServiceImpl implements NoteReadPlatformService {
             case SAVING_ACCOUNT:
                 paramList.add(NoteType.SAVING_ACCOUNT.getValue());
                 paramList.add(NoteType.SAVINGS_TRANSACTION.getValue());
-                conditionSql = " n.saving_account_id = ? and ( n.note_type_enum = ? or n.note_type_enum = ? ) ";
+                conditionSql = " n.savings_account_id = ? and ( n.note_type_enum = ? or n.note_type_enum = ? ) ";
             break;
             case SAVINGS_TRANSACTION:
                 conditionSql = " n.savings_account_transaction_id = ? ";
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java
index 980335611..c3513d60c 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java
@@ -19,6 +19,7 @@
 package org.apache.fineract.portfolio.note.service;
 
 import java.util.Map;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
 import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
@@ -40,28 +41,32 @@ import org.apache.fineract.portfolio.note.domain.NoteType;
 import org.apache.fineract.portfolio.note.exception.NoteNotFoundException;
 import org.apache.fineract.portfolio.note.exception.NoteResourceNotSupportedException;
 import org.apache.fineract.portfolio.note.serialization.NoteCommandFromApiJsonDeserializer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
+import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepository;
+import org.apache.fineract.portfolio.savings.exception.SavingsAccountNotFoundException;
 
+@Slf4j
 public class NoteWritePlatformServiceJpaRepositoryImpl implements NoteWritePlatformService {
 
-    private static final Logger LOG = LoggerFactory.getLogger(NoteWritePlatformServiceJpaRepositoryImpl.class);
     private final NoteRepository noteRepository;
     private final ClientRepositoryWrapper clientRepository;
     private final GroupRepository groupRepository;
     private final LoanRepositoryWrapper loanRepository;
     private final LoanTransactionRepository loanTransactionRepository;
     private final NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer;
+    private final SavingsAccountRepository savingsAccountRepository;
 
     public NoteWritePlatformServiceJpaRepositoryImpl(final NoteRepository noteRepository, final ClientRepositoryWrapper clientRepository,
             final GroupRepository groupRepository, final LoanRepositoryWrapper loanRepository,
-            final LoanTransactionRepository loanTransactionRepository, final NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer) {
+            final LoanTransactionRepository loanTransactionRepository, final NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer,
+            final SavingsAccountRepository savingsAccountRepository) {
         this.noteRepository = noteRepository;
         this.clientRepository = clientRepository;
         this.groupRepository = groupRepository;
         this.loanRepository = loanRepository;
         this.loanTransactionRepository = loanTransactionRepository;
         this.fromApiJsonDeserializer = fromApiJsonDeserializer;
+        this.savingsAccountRepository = savingsAccountRepository;
     }
 
     private CommandProcessingResult createClientNote(final JsonCommand command) {
@@ -151,26 +156,23 @@ public class NoteWritePlatformServiceJpaRepositoryImpl implements NoteWritePlatf
                 .build();
     }
 
-    // private CommandProcessingResult createSavingAccountNote(final JsonCommand
-    // command) {
-    //
-    // final Long resourceId = command.getSupportedEntityId();
-    //
-    // final SavingAccount savingAccount =
-    // this.savingAccountRepository.findOne(resourceId);
-    // if (savingAccount == null) { throw new
-    // SavingAccountNotFoundException(resourceId); }
-    //
-    // final String note = command.stringValueOfParameterNamed("note");
-    // final Note newNote = Note.savingNote(savingAccount, note);
-    //
-    // this.noteRepository.save(newNote);
-    //
-    // return new CommandProcessingResultBuilder() //
-    // .withCommandId(command.commandId()) //
-    // .withEntityId(newNote.getId()) //
-    // .withClientId(savingAccount.getClient().getId()).withOfficeId(savingAccount.getClient().getOffice().getId()).build();
-    // }
+    private CommandProcessingResult createSavingAccountNote(final JsonCommand command) {
+        final Long resourceId = command.getSavingsId();
+        final SavingsAccount savingAccount = this.savingsAccountRepository.findById(resourceId)
+                .orElseThrow(() -> new SavingsAccountNotFoundException(resourceId));
+
+        final String note = command.stringValueOfParameterNamed("note");
+        final Note newNote = Note.savingNote(savingAccount, note);
+
+        this.noteRepository.saveAndFlush(newNote);
+
+        return new CommandProcessingResultBuilder() //
+                .withCommandId(command.commandId()) //
+                .withEntityId(newNote.getId()) //
+                .withOfficeId(savingAccount.getClient().getOffice().getId()) //
+                .withSavingsId(savingAccount.getId()) //
+                .build();
+    }
 
     @Override
     public CommandProcessingResult createNote(final JsonCommand command) {
@@ -192,9 +194,9 @@ public class NoteWritePlatformServiceJpaRepositoryImpl implements NoteWritePlatf
             case LOAN_TRANSACTION: {
                 return createLoanTransactionNote(command);
             }
-            // case SAVING_ACCOUNT: {
-            // return createSavingAccountNote(command);
-            // }
+            case SAVING_ACCOUNT: {
+                return createSavingAccountNote(command);
+            }
             default:
                 throw new NoteResourceNotSupportedException(resourceUrl);
         }
@@ -333,41 +335,30 @@ public class NoteWritePlatformServiceJpaRepositoryImpl implements NoteWritePlatf
                 .withLoanId(loan.getId()).withOfficeId(loan.getOfficeId()).with(changes).build();
     }
 
-    // private CommandProcessingResult updateSavingAccountNote(final JsonCommand
-    // command) {
-    //
-    // final Long resourceId = command.getSupportedEntityId();
-    // final Long noteId = command.entityId();
-    // final String resourceUrl = command.getSupportedEntityType();
-    //
-    // final NoteType type = NoteType.fromApiUrl(resourceUrl);
-    //
-    // final SavingAccount savingAccount =
-    // this.savingAccountRepository.findOne(resourceId);
-    // if (savingAccount == null) { throw new
-    // SavingAccountNotFoundException(resourceId); }
-    //
-    // final Note noteForUpdate =
-    // this.noteRepository.findBySavingAccountIdAndId(resourceId, noteId);
-    //
-    // if (noteForUpdate == null) { throw new NoteNotFoundException(noteId,
-    // resourceId, type.name().toLowerCase()); }
-    //
-    // final Map<String, Object> changes = noteForUpdate.update(command);
-    //
-    // if (!changes.isEmpty()) {
-    // this.noteRepository.saveAndFlush(noteForUpdate);
-    // }
-    //
-    // return new CommandProcessingResultBuilder()
-    // //
-    // .withCommandId(command.commandId())
-    // //
-    // .withEntityId(noteForUpdate.getId())
-    // //
-    // .withClientId(savingAccount.getClient().getId()).withOfficeId(savingAccount.getClient().getOffice().getId()).with(changes)
-    // .build();
-    // }
+    private CommandProcessingResult updateSavingAccountNote(final JsonCommand command) {
+        final Long resourceId = command.getSavingsId();
+        final Long noteId = command.entityId();
+        final NoteType type = NoteType.SAVING_ACCOUNT;
+        final SavingsAccount savingAccount = this.savingsAccountRepository.findById(resourceId)
+                .orElseThrow(() -> new SavingsAccountNotFoundException(resourceId));
+
+        final Note noteForUpdate = this.noteRepository.findBySavingsAccountAndId(savingAccount, noteId);
+        if (noteForUpdate == null) {
+            throw new NoteNotFoundException(noteId, resourceId, type.name().toLowerCase());
+        }
+        final Map<String, Object> changes = noteForUpdate.update(command);
+        if (!changes.isEmpty()) {
+            this.noteRepository.saveAndFlush(noteForUpdate);
+        }
+
+        return new CommandProcessingResultBuilder() //
+                .withCommandId(command.commandId()) //
+                .withEntityId(noteForUpdate.getId()) //
+                .withOfficeId(savingAccount.getClient().getOffice().getId()) //
+                .withSavingsId(savingAccount.getId()) //
+                .with(changes) //
+                .build();
+    }
 
     @Override
     public CommandProcessingResult updateNote(final JsonCommand command) {
@@ -390,9 +381,9 @@ public class NoteWritePlatformServiceJpaRepositoryImpl implements NoteWritePlatf
             case LOAN_TRANSACTION: {
                 return updateLoanTransactionNote(command);
             }
-            // case SAVING_ACCOUNT: {
-            // return updateSavingAccountNote(command);
-            // }
+            case SAVING_ACCOUNT: {
+                return updateSavingAccountNote(command);
+            }
             default:
                 throw new NoteResourceNotSupportedException(resourceUrl);
         }
@@ -444,19 +435,19 @@ public class NoteWritePlatformServiceJpaRepositoryImpl implements NoteWritePlatf
                 noteForUpdate = this.noteRepository.findByLoanTransactionAndId(loanTransaction, noteId);
             }
             break;
-            // case SAVING_ACCOUNT: {
-            // noteForUpdate =
-            // this.noteRepository.findBySavingAccountIdAndId(resourceId,
-            // noteId);
-            // }
-            // break;
-            case SAVING_ACCOUNT:
+            case SAVING_ACCOUNT: {
+                final Long savinsAccountId = command.getSavingsId();
+                final SavingsAccount savingAccount = this.savingsAccountRepository.findById(savinsAccountId)
+                        .orElseThrow(() -> new SavingsAccountNotFoundException(savinsAccountId));
+
+                noteForUpdate = this.noteRepository.findBySavingsAccountAndId(savingAccount, noteId);
+            }
             break;
             case SHARE_ACCOUNT:
-                LOG.error("TODO Implement getNoteForDelete for SHARE_ACCOUNT");
+                log.error("TODO Implement getNoteForDelete for SHARE_ACCOUNT");
             break;
             case SAVINGS_TRANSACTION:
-                LOG.error("TODO Implement getNoteForDelete for SAVINGS_TRANSACTION");
+                log.error("TODO Implement getNoteForDelete for SAVINGS_TRANSACTION");
             break;
         }
         if (noteForUpdate == null) {
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/starter/NoteAutoConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/starter/NoteAutoConfiguration.java
index 2da1c9d24..8fab6f156 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/starter/NoteAutoConfiguration.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/starter/NoteAutoConfiguration.java
@@ -28,6 +28,7 @@ import org.apache.fineract.portfolio.note.service.NoteReadPlatformService;
 import org.apache.fineract.portfolio.note.service.NoteReadPlatformServiceImpl;
 import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
 import org.apache.fineract.portfolio.note.service.NoteWritePlatformServiceJpaRepositoryImpl;
+import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepository;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -46,8 +47,8 @@ public class NoteAutoConfiguration {
     @ConditionalOnMissingBean
     public NoteWritePlatformService noteWritePlatformService(NoteRepository noteRepository, ClientRepositoryWrapper clientRepository,
             GroupRepository groupRepository, LoanRepositoryWrapper loanRepository, LoanTransactionRepository loanTransactionRepository,
-            NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer) {
+            NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer, SavingsAccountRepository savingsAccountRepository) {
         return new NoteWritePlatformServiceJpaRepositoryImpl(noteRepository, clientRepository, groupRepository, loanRepository,
-                loanTransactionRepository, fromApiJsonDeserializer);
+                loanTransactionRepository, fromApiJsonDeserializer, savingsAccountRepository);
     }
 }
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/NotesTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/NotesTest.java
index 3b4d4f1af..99f0fa077 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/NotesTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/NotesTest.java
@@ -28,6 +28,8 @@ import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import org.apache.fineract.client.models.GetResourceTypeResourceIdNotesNoteIdResponse;
+import org.apache.fineract.client.models.PostResourceTypeResourceIdNotesResponse;
 import org.apache.fineract.integrationtests.common.ClientHelper;
 import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
 import org.apache.fineract.integrationtests.common.GroupHelper;
@@ -36,6 +38,8 @@ import org.apache.fineract.integrationtests.common.Utils;
 import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
 import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
 import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
+import org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper;
+import org.apache.fineract.integrationtests.common.savings.SavingsProductHelper;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -47,6 +51,8 @@ public class NotesTest {
     private RequestSpecification requestSpec;
     private ResponseSpecification responseSpec404;
     private LoanTransactionHelper loanTransactionHelper;
+    private SavingsProductHelper savingsProductHelper;
+    private SavingsAccountHelper savingsAccountHelper;
 
     @BeforeEach
     public void setup() {
@@ -56,6 +62,8 @@ public class NotesTest {
         this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
         this.responseSpec404 = new ResponseSpecBuilder().expectStatusCode(404).build();
         this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
+        this.savingsProductHelper = new SavingsProductHelper();
+        this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
     }
 
     @Test
@@ -190,6 +198,33 @@ public class NotesTest {
 
     }
 
+    @Test
+    public void testCreateSavingsNote() {
+        final String noteText = "this is a test Savings note";
+        final String testDate = "01 January 2012";
+
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, testDate);
+        // Savings Account
+        final String savingsProductJSON = this.savingsProductHelper.withInterestCompoundingPeriodTypeAsDaily()
+                .withInterestPostingPeriodTypeAsDaily().withInterestCalculationPeriodTypeAsDailyBalance().build();
+        final Integer savingsProductId = SavingsProductHelper.createSavingsProduct(savingsProductJSON, requestSpec, responseSpec);
+        final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplicationOnDate(clientID, savingsProductId, "INDIVIDUAL",
+                testDate);
+        Assertions.assertNotNull(savingsId);
+
+        // Notes
+        final String payload = "{\"note\": \"" + noteText + "\"}";
+        final PostResourceTypeResourceIdNotesResponse postNoteResponse = NotesHelper.createSavingsNote(requestSpec, responseSpec, savingsId,
+                payload);
+        Assertions.assertNotNull(postNoteResponse);
+        Assertions.assertNotNull(postNoteResponse.getResourceId());
+
+        final GetResourceTypeResourceIdNotesNoteIdResponse getNoteResponse = NotesHelper.getSavingsNote(requestSpec, responseSpec,
+                savingsId, postNoteResponse.getResourceId());
+        Assertions.assertNotNull(getNoteResponse);
+        Assertions.assertEquals(noteText, getNoteResponse.getNote());
+    }
+
     private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID) {
         List<HashMap> collaterals = new ArrayList<>();
         final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/NotesHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/NotesHelper.java
index 25c0fb9d3..e333f3fa1 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/NotesHelper.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/NotesHelper.java
@@ -18,12 +18,18 @@
  */
 package org.apache.fineract.integrationtests.common;
 
+import com.google.gson.Gson;
 import io.restassured.specification.RequestSpecification;
 import io.restassured.specification.ResponseSpecification;
+import org.apache.fineract.client.models.GetResourceTypeResourceIdNotesNoteIdResponse;
+import org.apache.fineract.client.models.PostResourceTypeResourceIdNotesResponse;
+import org.apache.fineract.client.util.JSON;
 
 @SuppressWarnings({ "rawtypes", "unchecked" })
 public final class NotesHelper {
 
+    private static final Gson GSON = new JSON().getGson();
+
     private NotesHelper() {
 
     }
@@ -134,4 +140,20 @@ public final class NotesHelper {
         Utils.performServerDelete(requestSpec, responseSpec, deleteLoanTransactionNoteURL, "");
     }
 
+    private static final String SAVINGS_URL = "/fineract-provider/api/v1/savings";
+
+    public static PostResourceTypeResourceIdNotesResponse createSavingsNote(RequestSpecification requestSpec,
+            ResponseSpecification responseSpec, Integer savingsId, String request) {
+        final String noteURL = SAVINGS_URL + "/" + savingsId + "/notes?" + Utils.TENANT_IDENTIFIER;
+        final String response = Utils.performServerPost(requestSpec, responseSpec, noteURL, request);
+        return GSON.fromJson(response, PostResourceTypeResourceIdNotesResponse.class);
+    }
+
+    public static GetResourceTypeResourceIdNotesNoteIdResponse getSavingsNote(RequestSpecification requestSpec,
+            ResponseSpecification responseSpec, Integer savingsId, Integer noteId) {
+        final String noteURL = SAVINGS_URL + "/" + savingsId + "/notes/" + noteId + "?" + Utils.TENANT_IDENTIFIER;
+        final String response = Utils.performServerGet(requestSpec, responseSpec, noteURL);
+        return GSON.fromJson(response, GetResourceTypeResourceIdNotesNoteIdResponse.class);
+    }
+
 }