Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FINERACT-1849: Fix to use notes in Savings Accounts #2857

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public static String getResourceCondition(final NoteType noteType, List<Object>
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 = ? ";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -40,28 +41,32 @@
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) {
Expand Down Expand Up @@ -151,26 +156,23 @@ private CommandProcessingResult createLoanTransactionNote(final JsonCommand comm
.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) {
Expand All @@ -192,9 +194,9 @@ public CommandProcessingResult createNote(final JsonCommand command) {
case LOAN_TRANSACTION: {
return createLoanTransactionNote(command);
}
// case SAVING_ACCOUNT: {
// return createSavingAccountNote(command);
// }
case SAVING_ACCOUNT: {
return createSavingAccountNote(command);
}
default:
throw new NoteResourceNotSupportedException(resourceUrl);
}
Expand Down Expand Up @@ -333,41 +335,30 @@ private CommandProcessingResult updateLoanTransactionNote(final JsonCommand comm
.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) {
Expand All @@ -390,9 +381,9 @@ public CommandProcessingResult updateNote(final JsonCommand command) {
case LOAN_TRANSACTION: {
return updateLoanTransactionNote(command);
}
// case SAVING_ACCOUNT: {
// return updateSavingAccountNote(command);
// }
case SAVING_ACCOUNT: {
return updateSavingAccountNote(command);
}
default:
throw new NoteResourceNotSupportedException(resourceUrl);
}
Expand Down Expand Up @@ -444,19 +435,19 @@ private Note getNoteForDelete(final JsonCommand command) {
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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
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;
Expand All @@ -46,8 +47,8 @@ public NoteReadPlatformService noteReadPlatformService(JdbcTemplate jdbcTemplate
@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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
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;
Expand All @@ -36,6 +38,8 @@
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;
Expand All @@ -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() {
Expand All @@ -56,6 +62,8 @@ public void setup() {
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
Expand Down Expand Up @@ -190,6 +198,33 @@ public void testCreateLoanNote() {

}

@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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {

}
Expand Down Expand Up @@ -134,4 +140,20 @@ public static void deleteLoanTransactionNote(RequestSpecification requestSpec, R
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);
}

}