Implemented Notes API

This commit is contained in:
ashok-conflux
2013-03-06 22:28:59 +05:30
parent 155339342a
commit a497aeec55
35 changed files with 998 additions and 551 deletions
@@ -0,0 +1,8 @@
ALTER TABLE `m_note`
ADD COLUMN `group_id` BIGINT(20) NULL AFTER `client_id`,
ADD CONSTRAINT `FK_m_note_m_group` FOREIGN KEY (`group_id`) REFERENCES `m_group` (`id`);
ALTER TABLE `m_note`
ALTER `client_id` DROP DEFAULT;
ALTER TABLE `m_note`
CHANGE COLUMN `client_id` `client_id` BIGINT(20) NULL AFTER `id`;
@@ -0,0 +1,36 @@
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
VALUES('portfolio', 'CREATE_LOANNOTE', 'LOANNOTE', 'CREATE', '0'),
('portfolio', 'READ_LOANNOTE', 'LOANNOTE', 'READ', '0'),
('portfolio', 'UPDATE_LOANNOTE', 'LOANNOTE', 'UPDATE', '0'),
('portfolio', 'DELETE_LOANNOTE', 'LOANNOTE', 'DELETE', '0'),
('portfolio', 'CREATE_LOANNOTE_CHECKER', 'LOANNOTE', 'CREATE', '0'),
('portfolio', 'UPDATE_LOANNOTE_CHECKER', 'LOANNOTE', 'UPDATE', '0'),
('portfolio', 'DELETE_LOANNOTE_CHECKER', 'LOANNOTE', 'DELETE', '0'),
('portfolio', 'CREATE_LOANTRANSACTIONNOTE', 'LOANTRANSACTIONNOTE', 'CREATE', '0'),
('portfolio', 'READ_LOANTRANSACTIONNOTE', 'LOANTRANSACTIONNOTE', 'READ', '0'),
('portfolio', 'UPDATE_LOANTRANSACTIONNOTE', 'LOANTRANSACTIONNOTE', 'UPDATE', '0'),
('portfolio', 'DELETE_LOANTRANSACTIONNOTE', 'LOANTRANSACTIONNOTE', 'DELETE', '0'),
('portfolio', 'CREATE_LOANTRANSACTIONNOTE_CHECKER', 'LOANTRANSACTIONNOTE', 'CREATE', '0'),
('portfolio', 'UPDATE_LOANTRANSACTIONNOTE_CHECKER', 'LOANTRANSACTIONNOTE', 'UPDATE', '0'),
('portfolio', 'DELETE_LOANTRANSACTIONNOTE_CHECKER', 'LOANTRANSACTIONNOTE', 'DELETE', '0'),
('portfolio', 'CREATE_DEPOSITNOTE', 'DEPOSITNOTE', 'CREATE', '0'),
('portfolio', 'READ_DEPOSITNOTE', 'DEPOSITNOTE', 'READ', '0'),
('portfolio', 'UPDATE_DEPOSITNOTE', 'DEPOSITNOTE', 'UPDATE', '0'),
('portfolio', 'DELETE_DEPOSITNOTE', 'DEPOSITNOTE', 'DELETE', '0'),
('portfolio', 'CREATE_DEPOSITNOTE_CHECKER', 'DEPOSITNOTE', 'CREATE', '0'),
('portfolio', 'UPDATE_DEPOSITNOTE_CHECKER', 'DEPOSITNOTE', 'UPDATE', '0'),
('portfolio', 'DELETE_DEPOSITNOTE_CHECKER', 'DEPOSITNOTE', 'DELETE', '0'),
('portfolio', 'CREATE_SAVINGNOTE', 'SAVINGNOTE', 'CREATE', '0'),
('portfolio', 'READ_SAVINGNOTE', 'SAVINGNOTE', 'READ', '0'),
('portfolio', 'UPDATE_SAVINGNOTE', 'SAVINGNOTE', 'UPDATE', '0'),
('portfolio', 'DELETE_SAVINGNOTE', 'SAVINGNOTE', 'DELETE', '0'),
('portfolio', 'CREATE_SAVINGNOTE_CHECKER', 'SAVINGNOTE', 'CREATE', '0'),
('portfolio', 'UPDATE_SAVINGNOTE_CHECKER', 'SAVINGNOTE', 'UPDATE', '0'),
('portfolio', 'DELETE_SAVINGNOTE_CHECKER', 'SAVINGNOTE', 'DELETE', '0'),
('portfolio', 'CREATE_GROUPNOTE', 'GROUPNOTE', 'CREATE', '0'),
('portfolio', 'READ_GROUPNOTE', 'GROUPNOTE', 'READ', '0'),
('portfolio', 'UPDATE_GROUPNOTE', 'GROUPNOTE', 'UPDATE', '0'),
('portfolio', 'DELETE_GROUPNOTE', 'GROUPNOTE', 'DELETE', '0'),
('portfolio', 'CREATE_GROUPNOTE_CHECKER', 'GROUPNOTE', 'CREATE', '0'),
('portfolio', 'UPDATE_GROUPNOTE_CHECKER', 'GROUPNOTE', 'UPDATE', '0'),
('portfolio', 'DELETE_GROUPNOTE_CHECKER', 'GROUPNOTE', 'DELETE', '0');
@@ -448,5 +448,18 @@ public class CommandWrapper {
public boolean isCalendarResource() {
return this.entityName.equalsIgnoreCase("CALENDAR");
}
public boolean isNoteResource() {
boolean isnoteResource = false;
if(this.entityName.equalsIgnoreCase("CLIENTNOTE") ||
this.entityName.equalsIgnoreCase("LOANNOTE") ||
this.entityName.equalsIgnoreCase("LOANTRANSACTIONNOTE") ||
this.entityName.equalsIgnoreCase("DEPOSITNOTE") ||
this.entityName.equalsIgnoreCase("SAVINGNOTE") ||
this.entityName.equalsIgnoreCase("GROUPNOTE")){
isnoteResource = true;
}
return isnoteResource;
}
}
@@ -301,23 +301,6 @@ public class CommandWrapperBuilder {
return this;
}
public CommandWrapperBuilder createClientNote(final Long clientId) {
this.actionName = "CREATE";
this.entityName = "CLIENTNOTE";
this.clientId = clientId;
this.href = "/clients/" + clientId + "/notes/template";
return this;
}
public CommandWrapperBuilder updateClientNote(final Long clientId, final Long noteId) {
this.actionName = "UPDATE";
this.entityName = "CLIENTNOTE";
this.entityId = noteId;
this.clientId = clientId;
this.href = "/clients/" + clientId + "/notes";
return this;
}
public CommandWrapperBuilder createClient() {
this.actionName = "CREATE";
this.entityName = "CLIENT";
@@ -892,4 +875,33 @@ public class CommandWrapperBuilder {
this.href = "/" + supportedEntityType + "/" + supportedEntityId + "/calendars/" + calendarId;
return this;
}
public CommandWrapperBuilder createNote(final String entityName, final String resourceType, final Long resourceId) {
this.actionName = "CREATE";
this.entityName = entityName;//Note supports multiple resources. Note Permissions are set for each resource.
this.supportedEntityType = resourceType;
this.supportedEntityId = resourceId;
this.href = "/" + resourceType + "/" + resourceId + "/notes/template";
return this;
}
public CommandWrapperBuilder updateNote(final String entityName, final String resourceType, final Long resourceId, final Long noteId) {
this.actionName = "UPDATE";
this.entityName = entityName;//Note supports multiple resources. Note Permissions are set for each resource.
this.entityId = noteId;
this.supportedEntityType = resourceType;
this.supportedEntityId = resourceId;
this.href = "/" + resourceType + "/" + resourceId + "/notes";
return this;
}
public CommandWrapperBuilder deleteNote(final String entityName, final String resourceType, final Long resourceId, final Long noteId) {
this.actionName = "DELETE";
this.entityName = entityName;//Note supports multiple resources. Note Permissions are set for each resource.
this.entityId = noteId;
this.supportedEntityType = resourceType;
this.supportedEntityId = resourceId;
this.href = "/" + resourceType + "/" + resourceId + "/calendars/" + noteId;
return this;
}
}
@@ -125,11 +125,13 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if (wrapper.isClientNoteResource()) {
} else if (wrapper.isNoteResource()) {
if (wrapper.isCreate()) {
handler = applicationContext.getBean("createClientNoteCommandHandler", NewCommandSourceHandler.class);
handler = applicationContext.getBean("createNoteCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isUpdate()) {
handler = applicationContext.getBean("updateClientNoteCommandHandler", NewCommandSourceHandler.class);
handler = applicationContext.getBean("updateNoteCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isDelete()) {
handler = applicationContext.getBean("deleteNoteCommandHandler", NewCommandSourceHandler.class);
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
@@ -1,117 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.client.api;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.mifosplatform.commands.domain.CommandWrapper;
import org.mifosplatform.commands.service.CommandWrapperBuilder;
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.client.data.NoteData;
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/clients/{clientId}/notes")
@Component
@Scope("singleton")
public class ClientNotesApiResource {
private final Set<String> NOTE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "clientId", "loanId", "loanTransactionId",
"noteType", "note", "createdById", "createdByUsername", "createdOn", "updatedById", "updatedByUsername", "updatedOn"));
private final PlatformSecurityContext context;
private final ClientReadPlatformService clientReadPlatformService;
private final DefaultToApiJsonSerializer<NoteData> toApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@Autowired
public ClientNotesApiResource(final PlatformSecurityContext context, final ClientReadPlatformService readPlatformService,
final DefaultToApiJsonSerializer<NoteData> toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
this.context = context;
this.clientReadPlatformService = readPlatformService;
this.toApiJsonSerializer = toApiJsonSerializer;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllClientNotes(@PathParam("clientId") final Long clientId, @Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission("CLIENTNOTE");
final Collection<NoteData> notes = this.clientReadPlatformService.retrieveAllClientNotes(clientId);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, notes, NOTE_DATA_PARAMETERS);
}
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String addNewClientNote(@PathParam("clientId") final Long clientId, final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createClientNote(clientId).withJson(apiRequestBodyAsJson).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
@GET
@Path("{noteId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveClientNote(@PathParam("clientId") final Long clientId, @PathParam("noteId") final Long noteId,
@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission("CLIENTNOTE");
final NoteData note = this.clientReadPlatformService.retrieveClientNote(clientId, noteId);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, note, NOTE_DATA_PARAMETERS);
}
@PUT
@Path("{noteId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateClientNote(@PathParam("clientId") final Long clientId, @PathParam("noteId") final Long noteId,
final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateClientNote(clientId, noteId).withJson(apiRequestBodyAsJson)
.build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
}
@@ -1,46 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.client.command;
/**
* Immutable command used for create or update of notes.
*/
public class NoteCommand {
private final Long id;
private final Long clientId;
private final Long loanId;
private final Long loanTransactionId;
private final String note;
public NoteCommand(final Long id, Long clientId, final String note) {
this.id = id;
this.clientId = clientId;
this.loanId = null;
this.loanTransactionId = null;
this.note = note;
}
public Long getId() {
return id;
}
public Long getClientId() {
return clientId;
}
public Long getLoanId() {
return loanId;
}
public Long getLoanTransactionId() {
return loanTransactionId;
}
public String getNote() {
return note;
}
}
@@ -1,41 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.client.domain;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.portfolio.client.domain.Note.NoteType;
public class NoteEnumerations {
public static EnumOptionData noteType(final Integer id) {
return noteType(Note.NoteType.parse(id));
}
public static EnumOptionData noteType(NoteType type) {
EnumOptionData optionData = null;
switch (type) {
case CLIENT:
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Client note");
break;
case LOAN:
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Loan note");
break;
case LOAN_TRANSACTION:
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Loan transaction note");
break;
case DEPOSIT:
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Deposit transaction note");
break;
case SAVING:
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Saving transaction note");
break;
default:
break;
}
return optionData;
}
}
@@ -1,18 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.client.domain;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface NoteRepository extends JpaRepository<Note, Long>, JpaSpecificationExecutor<Note> {
List<Note> findByLoanId(Long id);
List<Note> findByClientId(Long id);
}
@@ -1,59 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.client.serialization;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.portfolio.client.command.ClientCommand;
import org.mifosplatform.portfolio.client.command.ClientNoteCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
/**
* Implementation of {@link FromApiJsonDeserializer} for {@link ClientCommand}
* 's.
*/
@Component
public final class ClientNoteCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer<ClientNoteCommand> {
/**
* The parameters supported for this command.
*/
private final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("note"));
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public ClientNoteCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
@Override
public ClientNoteCommand commandFromApiJson(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
final JsonElement element = fromApiJsonHelper.parse(json);
final String note = fromApiJsonHelper.extractStringNamed("note", element);
return new ClientNoteCommand(note);
}
}
@@ -12,7 +12,6 @@ import org.mifosplatform.portfolio.client.data.ClientAccountSummaryData;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.client.data.ClientIdentifierData;
import org.mifosplatform.portfolio.client.data.ClientLookup;
import org.mifosplatform.portfolio.client.data.NoteData;
public interface ClientReadPlatformService {
@@ -30,10 +29,6 @@ public interface ClientReadPlatformService {
Collection<ClientAccountSummaryData> retrieveClientLoanAccountsByLoanOfficerId(Long clientId, Long loanOfficerId);
Collection<NoteData> retrieveAllClientNotes(Long clientId);
NoteData retrieveClientNote(Long clientId, Long noteId);
Collection<ClientIdentifierData> retrieveClientIdentifiers(Long clientId);
ClientIdentifierData retrieveClientIdentifier(Long clientId, Long clientIdentifierId);
@@ -12,9 +12,7 @@ import java.util.Collection;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
@@ -25,14 +23,10 @@ import org.mifosplatform.portfolio.client.data.ClientAccountSummaryData;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.client.data.ClientIdentifierData;
import org.mifosplatform.portfolio.client.data.ClientLookup;
import org.mifosplatform.portfolio.client.data.NoteData;
import org.mifosplatform.portfolio.client.domain.NoteEnumerations;
import org.mifosplatform.portfolio.client.exception.ClientIdentifierNotFoundException;
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
import org.mifosplatform.portfolio.client.exception.NoteNotFoundException;
import org.mifosplatform.portfolio.loanaccount.data.LoanStatusEnumData;
import org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations;
import org.mifosplatform.useradministration.data.AppUserData;
import org.mifosplatform.useradministration.domain.AppUser;
import org.mifosplatform.useradministration.service.AppUserReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -356,98 +350,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
}
}
@Override
public NoteData retrieveClientNote(final Long clientId, final Long noteId) {
try {
context.authenticatedUser();
// Check if client exists
retrieveIndividualClient(clientId);
// FIXME - KW - use join on sql query to fetch user information for
// note
// rather than fetching users?
Collection<AppUserData> allUsers = this.appUserReadPlatformService.retrieveAllUsers();
NoteMapper noteMapper = new NoteMapper(allUsers);
String sql = "select " + noteMapper.schema() + " where n.client_id = ? and n.id = ?";
return this.jdbcTemplate.queryForObject(sql, noteMapper, new Object[] { clientId, noteId });
} catch (EmptyResultDataAccessException e) {
throw new NoteNotFoundException(clientId);
}
}
@Override
public Collection<NoteData> retrieveAllClientNotes(final Long clientId) {
context.authenticatedUser();
// Check if client exists
retrieveIndividualClient(clientId);
// FIXME - KW - use join on sql query to fetch user information for note
// rather than fetching users?
Collection<AppUserData> allUsers = this.appUserReadPlatformService.retrieveAllUsers();
NoteMapper noteMapper = new NoteMapper(allUsers);
String sql = "select " + noteMapper.schema() + " where n.client_id = ? order by n.created_date DESC";
return this.jdbcTemplate.query(sql, noteMapper, new Object[] { clientId });
}
private static final class NoteMapper implements RowMapper<NoteData> {
private final Collection<AppUserData> allUsers;
public NoteMapper(final Collection<AppUserData> allUsers) {
this.allUsers = allUsers;
}
public String schema() {
return "n.id as id, n.client_id as clientId, n.loan_id as loanId, n.loan_transaction_id as transactionId, n.note_type_enum as noteTypeEnum, n.note as note, "
+ "n.created_date as createdDate, n.createdby_id as createdById, n.lastmodified_date as lastModifiedDate, n.lastmodifiedby_id as lastModifiedById"
+ " from m_note n";
}
@Override
public NoteData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
Long id = JdbcSupport.getLong(rs, "id");
Long clientId = JdbcSupport.getLong(rs, "clientId");
Long loanId = JdbcSupport.getLong(rs, "loanId");
Long transactionId = JdbcSupport.getLong(rs, "transactionId");
Integer noteTypeId = JdbcSupport.getInteger(rs, "noteTypeEnum");
EnumOptionData noteType = NoteEnumerations.noteType(noteTypeId);
String note = rs.getString("note");
DateTime createdDate = JdbcSupport.getDateTime(rs, "createdDate");
Long createdById = JdbcSupport.getLong(rs, "createdById");
String createdByUsername = findUserById(createdById, allUsers);
DateTime lastModifiedDate = JdbcSupport.getDateTime(rs, "lastModifiedDate");
Long lastModifiedById = JdbcSupport.getLong(rs, "lastModifiedById");
String updatedByUsername = findUserById(createdById, allUsers);
return new NoteData(id, clientId, loanId, transactionId, noteType, note, createdDate, createdById, createdByUsername,
lastModifiedDate, lastModifiedById, updatedByUsername);
}
private String findUserById(final Long createdById, final Collection<AppUserData> allUsers) {
String username = "";
for (AppUserData appUserData : allUsers) {
if (appUserData.hasIdentifyOf(createdById)) {
username = appUserData.username();
break;
}
}
return username;
}
}
@Override
public Collection<ClientIdentifierData> retrieveClientIdentifiers(final Long clientId) {
@@ -29,10 +29,6 @@ public interface ClientWritePlatformService {
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'DELETE_CLIENTIMAGE')")
CommandProcessingResult deleteClientImage(Long clientId);
CommandProcessingResult addClientNote(Long clientId, JsonCommand command);
CommandProcessingResult updateClientNote(Long clientId, Long noteId, JsonCommand command);
CommandProcessingResult addClientIdentifier(Long clientId, JsonCommand command);
CommandProcessingResult updateClientIdentifier(Long clientId, Long clientIdentifierId, JsonCommand command);
@@ -26,22 +26,17 @@ import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.office.domain.OfficeRepository;
import org.mifosplatform.organisation.office.exception.OfficeNotFoundException;
import org.mifosplatform.portfolio.client.command.ClientIdentifierCommand;
import org.mifosplatform.portfolio.client.command.ClientNoteCommand;
import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientIdentifier;
import org.mifosplatform.portfolio.client.domain.ClientIdentifierRepository;
import org.mifosplatform.portfolio.client.domain.ClientRepository;
import org.mifosplatform.portfolio.client.domain.Note;
import org.mifosplatform.portfolio.client.domain.NoteRepository;
import org.mifosplatform.portfolio.client.exception.ClientIdentifierNotFoundException;
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
import org.mifosplatform.portfolio.client.exception.DuplicateClientIdentifierException;
import org.mifosplatform.portfolio.client.exception.NoteNotFoundException;
import org.mifosplatform.portfolio.client.serialization.ClientCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.client.serialization.ClientIdentifierCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.client.serialization.ClientNoteCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.group.domain.GroupRepository;
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
@@ -62,19 +57,16 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
private final ClientIdentifierRepository clientIdentifierRepository;
private final OfficeRepository officeRepository;
private final GroupRepository groupRepository;
private final NoteRepository noteRepository;
private final CodeValueRepositoryWrapper codeValueRepository;
private final ClientCommandFromApiJsonDeserializer fromApiJsonDeserializer;
private final ClientNoteCommandFromApiJsonDeserializer clientNoteFromApiJsonDeserializer;
private final ClientIdentifierCommandFromApiJsonDeserializer clientIdentifierCommandFromApiJsonDeserializer;
private final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory;
@Autowired
public ClientWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final ClientRepository clientRepository,
final ClientIdentifierRepository clientIdentifierRepository, final OfficeRepository officeRepository,
final NoteRepository noteRepository, final CodeValueRepositoryWrapper codeValueRepository,
final CodeValueRepositoryWrapper codeValueRepository,
final ClientCommandFromApiJsonDeserializer fromApiJsonDeserializer,
final ClientNoteCommandFromApiJsonDeserializer clientNoteFromApiJsonDeserializer,
final ClientIdentifierCommandFromApiJsonDeserializer clientIdentifierCommandFromApiJsonDeserializer,
final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory,
final GroupRepository groupRepository) {
@@ -82,10 +74,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
this.clientRepository = clientRepository;
this.clientIdentifierRepository = clientIdentifierRepository;
this.officeRepository = officeRepository;
this.noteRepository = noteRepository;
this.codeValueRepository = codeValueRepository;
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.clientNoteFromApiJsonDeserializer = clientNoteFromApiJsonDeserializer;
this.clientIdentifierCommandFromApiJsonDeserializer = clientIdentifierCommandFromApiJsonDeserializer;
this.accountIdentifierGeneratorFactory = accountIdentifierGeneratorFactory;
this.groupRepository = groupRepository;
@@ -213,51 +203,6 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
}
}
@Transactional
@Override
public CommandProcessingResult addClientNote(final Long clientId, final JsonCommand command) {
context.authenticatedUser();
final ClientNoteCommand clientNoteCommand = this.clientNoteFromApiJsonDeserializer.commandFromApiJson(command.json());
clientNoteCommand.validate();
final Client clientForUpdate = this.clientRepository.findOne(clientId);
if (clientForUpdate == null) { throw new ClientNotFoundException(clientId); }
final Note note = Note.clientNoteFromJson(clientForUpdate, command);
this.noteRepository.save(note);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(clientForUpdate.getOffice().getId())
.withClientId(clientId).withEntityId(note.getId()).build();
}
@Transactional
@Override
public CommandProcessingResult updateClientNote(final Long clientId, final Long noteId, final JsonCommand command) {
context.authenticatedUser();
final ClientNoteCommand clientNoteCommand = this.clientNoteFromApiJsonDeserializer.commandFromApiJson(command.json());
clientNoteCommand.validate();
final Note noteForUpdate = this.noteRepository.findOne(noteId);
if (noteForUpdate == null || noteForUpdate.isNotAgainstClientWithIdOf(clientId)) { throw new NoteNotFoundException(noteId,
clientId, "client"); }
final Client client = this.clientRepository.findOne(clientId);
final Map<String, Object> changes = noteForUpdate.update(command);
if (!changes.isEmpty()) {
this.noteRepository.save(noteForUpdate);
}
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(client.getOffice().getId())
.withClientId(clientId).withEntityId(noteId).with(changes).build();
}
@Transactional
@Override
public CommandProcessingResult addClientIdentifier(final Long clientId, final JsonCommand command) {
@@ -296,4 +296,10 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
return thisTransactionData;
}
public Loan getLoan() {
return this.loan;
}
}
@@ -24,8 +24,6 @@ import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientRepository;
import org.mifosplatform.portfolio.client.domain.Note;
import org.mifosplatform.portfolio.client.domain.NoteRepository;
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
import org.mifosplatform.portfolio.fund.domain.Fund;
import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
@@ -49,6 +47,8 @@ import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRepository;
import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
import org.mifosplatform.portfolio.loanproduct.exception.LoanProductNotFoundException;
import org.mifosplatform.portfolio.note.domain.Note;
import org.mifosplatform.portfolio.note.domain.NoteRepository;
import org.mifosplatform.useradministration.domain.AppUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -25,8 +25,6 @@ import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.portfolio.charge.domain.Charge;
import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper;
import org.mifosplatform.portfolio.charge.exception.LoanChargeNotFoundException;
import org.mifosplatform.portfolio.client.domain.Note;
import org.mifosplatform.portfolio.client.domain.NoteRepository;
import org.mifosplatform.portfolio.loanaccount.command.LoanUpdateCommand;
import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
@@ -46,6 +44,8 @@ import org.mifosplatform.portfolio.loanaccount.exception.LoanTransactionNotFound
import org.mifosplatform.portfolio.loanaccount.serialization.LoanEventApiJsonValidator;
import org.mifosplatform.portfolio.loanaccount.serialization.LoanUpdateCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.loanproduct.exception.InvalidCurrencyException;
import org.mifosplatform.portfolio.note.domain.Note;
import org.mifosplatform.portfolio.note.domain.NoteRepository;
import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -0,0 +1,178 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.note.api;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.mifosplatform.commands.domain.CommandWrapper;
import org.mifosplatform.commands.service.CommandWrapperBuilder;
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.note.data.NoteData;
import org.mifosplatform.portfolio.note.domain.NoteType;
import org.mifosplatform.portfolio.note.service.NoteReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/{resourceType}/{resourceId}/notes")
@Component
@Scope("singleton")
public class NotesApiResource {
private final Set<String> NOTE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "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;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@Autowired
public NotesApiResource(final PlatformSecurityContext context, final NoteReadPlatformService readPlatformService,
final DefaultToApiJsonSerializer<NoteData> toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
this.context = context;
this.readPlatformService = readPlatformService;
this.toApiJsonSerializer = toApiJsonSerializer;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveNotesByResource(@PathParam("resourceType") final String resourceType,
@PathParam("resourceId") final Long resourceId, @Context final UriInfo uriInfo) {
NoteType noteType = NoteType.fromApiUrl(resourceType);
this.context.authenticatedUser().validateHasReadPermission(getResourceNameForPermissions(noteType));
final Integer noteTypeId = noteType.getValue();
final Collection<NoteData> notes = this.readPlatformService.retrieveNotesByResource(resourceId, noteTypeId);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, notes, this.NOTE_DATA_PARAMETERS);
}
@GET
@Path("{noteId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveNote(@PathParam("resourceType") final String resourceType, @PathParam("resourceId") final Long resourceId,
@PathParam("noteId") final Long noteId, @Context final UriInfo uriInfo) {
NoteType noteType = NoteType.fromApiUrl(resourceType);
this.context.authenticatedUser().validateHasReadPermission(getResourceNameForPermissions(noteType));
final Integer noteTypeId = noteType.getValue();
final NoteData note = this.readPlatformService.retrieveNote(noteId, resourceId, noteTypeId);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, note, this.NOTE_DATA_PARAMETERS);
}
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String addNewNote(@PathParam("resourceType") final String resourceType, @PathParam("resourceId") final Long resourceId,
final String apiRequestBodyAsJson) {
NoteType noteType = NoteType.fromApiUrl(resourceType);
final String resourceNameForPermissions = getResourceNameForPermissions(noteType);
final CommandWrapper commandRequest = new CommandWrapperBuilder().createNote(resourceNameForPermissions, resourceType, resourceId)
.withJson(apiRequestBodyAsJson).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
@PUT
@Path("{noteId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateNote(@PathParam("resourceType") final String resourceType, @PathParam("resourceId") final Long resourceId,
@PathParam("noteId") final Long noteId, final String apiRequestBodyAsJson) {
NoteType noteType = NoteType.fromApiUrl(resourceType);
final String resourceNameForPermissions = getResourceNameForPermissions(noteType);
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateNote(resourceNameForPermissions, resourceType, resourceId, noteId).withJson(apiRequestBodyAsJson).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
@DELETE
@Path("{noteId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteNote(@PathParam("resourceType") final String resourceType, @PathParam("resourceId") final Long resourceId,
@PathParam("noteId") final Long noteId) {
NoteType noteType = NoteType.fromApiUrl(resourceType);
final String resourceNameForPermissions = getResourceNameForPermissions(noteType);
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteNote(resourceNameForPermissions, resourceType, resourceId, noteId).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
private String getResourceNameForPermissions(NoteType type){
String resourceNameForPermissions = "INVALIDNOTE";
switch(type){
case CLIENT:
resourceNameForPermissions = "CLIENTNOTE";
break;
case LOAN:
resourceNameForPermissions = "LOANNOTE";
break;
case LOAN_TRANSACTION:
resourceNameForPermissions = "LOANTRANSACTIONNOTE";
break;
case DEPOSIT:
resourceNameForPermissions = "DEPOSITNOTE";
break;
case SAVING:
resourceNameForPermissions = "SAVINGNOTE";
break;
case GROUP:
resourceNameForPermissions = "GROUPNOTE";
break;
}
return resourceNameForPermissions;
}
}
@@ -0,0 +1,20 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.note.command;
/**
* Immutable command used for create or update of notes.
*/
public class NoteCommand {
@SuppressWarnings("unused")
private final String note;
public NoteCommand(final String note) {
this.note = note;
}
}
@@ -3,13 +3,14 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.client.data;
package org.mifosplatform.portfolio.note.data;
import org.joda.time.DateTime;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
/**
* Immutable data object represent note or case information about a client, loan or loan transaction.
* Immutable data object represent note or case information about a client, loan
* or loan transaction.
*/
public class NoteData {
@@ -18,10 +19,16 @@ public class NoteData {
@SuppressWarnings("unused")
private final Long clientId;
@SuppressWarnings("unused")
private final Long groupId;
@SuppressWarnings("unused")
private final Long loanId;
@SuppressWarnings("unused")
private final Long loanTransactionId;
@SuppressWarnings("unused")
private final Long depositAccountId;
@SuppressWarnings("unused")
private final Long savingAccountId;
@SuppressWarnings("unused")
private final EnumOptionData noteType;
@SuppressWarnings("unused")
private final String note;
@@ -38,13 +45,17 @@ public class NoteData {
@SuppressWarnings("unused")
private final DateTime updatedOn;
public NoteData(final Long id, final Long clientId, final Long loanId, final Long transactionId, final EnumOptionData noteType,
final String note, final DateTime createdDate, final Long createdById, final String createdByUsername,
final DateTime lastModifiedDate, final Long lastModifiedById, final String updatedByUsername) {
public NoteData(final Long id, final Long clientId, final Long groupId, final Long loanId, final Long transactionId,
final Long depositAccountId, final Long savingAccountId, final EnumOptionData noteType, final String note,
final DateTime createdDate, final Long createdById, final String createdByUsername, final DateTime lastModifiedDate,
final Long lastModifiedById, final String updatedByUsername) {
this.id = id;
this.clientId = clientId;
this.groupId = groupId;
this.loanId = loanId;
this.loanTransactionId = transactionId;
this.depositAccountId = depositAccountId;
this.savingAccountId = savingAccountId;
this.noteType = noteType;
this.note = note;
this.createdOn = createdDate;
@@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.client.domain;
package org.mifosplatform.portfolio.note.domain;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -17,6 +17,8 @@ import javax.persistence.Table;
import org.apache.commons.lang.StringUtils;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.savingsaccount.domain.SavingAccount;
@@ -28,9 +30,14 @@ import org.mifosplatform.useradministration.domain.AppUser;
public class Note extends AbstractAuditableCustom<AppUser, Long> {
@ManyToOne
@JoinColumn(name = "client_id", nullable = false)
@JoinColumn(name = "client_id", nullable = true)
private final Client client;
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "group_id", nullable = true)
private Group group;
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "loan_id", nullable = true)
@@ -46,55 +53,28 @@ public class Note extends AbstractAuditableCustom<AppUser, Long> {
@SuppressWarnings("unused")
@Column(name = "note_type_enum")
private Integer noteTypeId;
private final Integer noteTypeId;
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "deposit_account_id", nullable = true)
private DepositAccount depositAccount;
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "saving_account_id", nullable = true)
private SavingAccount savingAccount;
public enum NoteType {
CLIENT(100, "noteType.client"), LOAN(200, "noteType.loan"), LOAN_TRANSACTION(300, "noteType.loan.transaction"), DEPOSIT(400,
"noteType.deposit"), SAVING(500,"noteType.saving");
private Integer value;
private String code;
NoteType(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public Integer getValue() {
return value;
}
public String getCode() {
return code;
}
public static NoteType parse(Integer id) {
NoteType right = null; // Default
for (NoteType item : NoteType.values()) {
if (item.getValue().intValue() == id.intValue()) {
right = item;
break;
}
}
return right;
}
}
public static Note clientNoteFromJson(final Client client, final JsonCommand command) {
final String note = command.stringValueOfParameterNamed("note");
return new Note(client, note);
}
public static Note groupNoteFromJson(final Group group, final JsonCommand command) {
final String note = command.stringValueOfParameterNamed("note");
return new Note(group, note);
}
public static Note loanNote(final Loan loan, final String note) {
return new Note(loan, note);
}
@@ -103,24 +83,35 @@ public class Note extends AbstractAuditableCustom<AppUser, Long> {
return new Note(loan, loanTransaction, note);
}
public static Note depositNote(final DepositAccount account, final String noteText) {
return new Note(account, noteText);
public static Note depositNote(final DepositAccount account, final String note) {
return new Note(account, note);
}
private Note(Client client, String note) {
public static Note savingNote(final SavingAccount account, final String note) {
return new Note(account, note);
}
private Note(final Client client, final String note) {
this.client = client;
this.note = note;
this.noteTypeId = NoteType.CLIENT.getValue();
}
private Note(Loan loan, String note) {
private Note(final Group group, final String note) {
this.group = group;
this.note = note;
this.client = null;
this.noteTypeId = NoteType.GROUP.getValue();
}
private Note(final Loan loan, final String note) {
this.loan = loan;
this.client = loan.client();
this.note = note;
this.noteTypeId = NoteType.LOAN.getValue();
}
private Note(Loan loan, LoanTransaction loanTransaction, String note) {
private Note(final Loan loan, final LoanTransaction loanTransaction, final String note) {
this.loan = loan;
this.loanTransaction = loanTransaction;
this.client = loan.client();
@@ -130,6 +121,7 @@ public class Note extends AbstractAuditableCustom<AppUser, Long> {
protected Note() {
this.client = null;
this.group = null;
this.loan = null;
this.loanTransaction = null;
this.note = null;
@@ -143,14 +135,14 @@ public class Note extends AbstractAuditableCustom<AppUser, Long> {
this.noteTypeId = NoteType.DEPOSIT.getValue();
}
public Note(SavingAccount account, String note) {
this.savingAccount = account;
this.client = account.getClient();
this.note = note;
this.noteTypeId = NoteType.SAVING.getValue();
}
public Note(final SavingAccount account, final String note) {
this.savingAccount = account;
this.client = account.getClient();
this.note = note;
this.noteTypeId = NoteType.SAVING.getValue();
}
public Map<String, Object> update(final JsonCommand command) {
public Map<String, Object> update(final JsonCommand command) {
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(7);
final String noteParamName = "note";
@@ -162,11 +154,8 @@ public class Note extends AbstractAuditableCustom<AppUser, Long> {
return actualChanges;
}
public boolean isNotAgainstClientWithIdOf(Long clientId) {
public boolean isNotAgainstClientWithIdOf(final Long clientId) {
return !this.client.identifiedBy(clientId);
}
public static Note savingNote(final SavingAccount account, final String noteText) {
return new Note(account, noteText);
}
}
@@ -0,0 +1,30 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.note.domain;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface NoteRepository extends JpaRepository<Note, Long>, JpaSpecificationExecutor<Note> {
List<Note> findByLoanId(Long id);
List<Note> findByClientId(Long id);
Note findByLoanIdAndId(Long loanId, Long id);
Note findByClientIdAndId(Long clientId, Long id);
Note findByGroupIdAndId(Long groupId, Long id);
Note findByLoanTransactionIdAndId(Long loanTransactionId, Long id);
Note findByDepositAccountIdAndId(Long depositAccountId, Long id);
Note findBySavingAccountIdAndId(Long savingAccountId, Long id);
}
@@ -0,0 +1,81 @@
package org.mifosplatform.portfolio.note.domain;
import java.util.HashMap;
import java.util.Map;
public enum NoteType {
CLIENT(100, "noteType.client", "clients"), LOAN(200, "noteType.loan", "loans"), LOAN_TRANSACTION(300, "noteType.loan.transaction",
"loanTransactions"), DEPOSIT(400, "noteType.deposit", "deposits"), SAVING(500, "noteType.saving", "savings"), GROUP(600,
"noteType.group", "groups");
private Integer value;
private String code;
private String apiUrl;
NoteType(final Integer value, final String code, final String apiUrl) {
this.value = value;
this.code = code;
this.apiUrl = apiUrl;
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return this.code;
}
private static final Map<Integer, NoteType> intToEnumMap = new HashMap<Integer, NoteType>();
private static int minValue;
private static int maxValue;
static {
int i = 0;
for (final NoteType type : NoteType.values()) {
if (i == 0) {
minValue = type.value;
}
intToEnumMap.put(type.value, type);
if (minValue >= type.value) {
minValue = type.value;
}
if (maxValue < type.value) {
maxValue = type.value;
}
i = i + 1;
}
}
public static NoteType fromInt(final int i) {
final NoteType type = intToEnumMap.get(Integer.valueOf(i));
return type;
}
public static int getMinValue() {
return minValue;
}
public static int getMaxValue() {
return maxValue;
}
@Override
public String toString() {
return name().toString();
}
private static final Map<String, NoteType> apiUrlToEnumMap = new HashMap<String, NoteType>();
static {
for (final NoteType type : NoteType.values()) {
apiUrlToEnumMap.put(type.apiUrl, type);
}
}
public static NoteType fromApiUrl(final String url) {
final NoteType type = apiUrlToEnumMap.get(url);
return type;
}
}
@@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.client.exception;
package org.mifosplatform.portfolio.note.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
@@ -12,12 +12,13 @@ import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceN
*/
public class NoteNotFoundException extends AbstractPlatformResourceNotFoundException {
public NoteNotFoundException(Long id) {
public NoteNotFoundException(final Long id) {
super("error.msg.note.id.invalid", "Note with identifier " + id + " does not exist", id);
}
public NoteNotFoundException(Long id, Long clientId, final String resource) {
public NoteNotFoundException(final Long id, final Long resourceId, final String resource) {
super("error.msg." + resource + ".note.id.invalid", "Note with identifier " + id + " does not exist for " + resource
+ " with identifier " + clientId, id, clientId);
+ " with identifier " + resourceId, id, resourceId);
}
}
@@ -3,30 +3,30 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.client.handler;
package org.mifosplatform.portfolio.note.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.portfolio.client.service.ClientWritePlatformService;
import org.mifosplatform.portfolio.note.service.NoteWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UpdateClientNoteCommandHandler implements NewCommandSourceHandler {
public class CreateNoteCommandHandler implements NewCommandSourceHandler {
private final ClientWritePlatformService clientWritePlatformService;
private final NoteWritePlatformService writePlatformService;
@Autowired
public UpdateClientNoteCommandHandler(final ClientWritePlatformService clientWritePlatformService) {
this.clientWritePlatformService = clientWritePlatformService;
public CreateNoteCommandHandler(final NoteWritePlatformService writePlatformService) {
this.writePlatformService = writePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.clientWritePlatformService.updateClientNote(command.getClientId(), command.entityId(), command);
return this.writePlatformService.createNote(command);
}
}
}
@@ -3,30 +3,29 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.client.handler;
package org.mifosplatform.portfolio.note.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.portfolio.client.service.ClientWritePlatformService;
import org.mifosplatform.portfolio.note.service.NoteWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class CreateClientNoteCommandHandler implements NewCommandSourceHandler {
public class DeleteNoteCommandHandler implements NewCommandSourceHandler {
private final ClientWritePlatformService clientWritePlatformService;
private final NoteWritePlatformService writePlatformService;
@Autowired
public CreateClientNoteCommandHandler(final ClientWritePlatformService clientWritePlatformService) {
this.clientWritePlatformService = clientWritePlatformService;
public DeleteNoteCommandHandler(final NoteWritePlatformService writePlatformService) {
this.writePlatformService = writePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.clientWritePlatformService.addClientNote(command.getClientId(), command);
return this.writePlatformService.deleteNote(command);
}
}
@@ -0,0 +1,28 @@
package org.mifosplatform.portfolio.note.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.portfolio.note.service.NoteWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UpdateNoteCommandHandler implements NewCommandSourceHandler {
private final NoteWritePlatformService writePlatformService;
@Autowired
public UpdateNoteCommandHandler(final NoteWritePlatformService noteWritePlatformService) {
this.writePlatformService = noteWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.updateNote(command);
}
}
@@ -0,0 +1,82 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.note.serialization;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.portfolio.note.command.NoteCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
/**
* Implementation of {@link FromApiJsonDeserializer} for {@link NoteCommand}
* 's.
*/
@Component
public final class NoteCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer<NoteCommand> {
/**
* The parameters supported for this command.
*/
private final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("note"));
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public NoteCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
@Override
public NoteCommand commandFromApiJson(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters);
final JsonElement element = this.fromApiJsonHelper.parse(json);
final String note = this.fromApiJsonHelper.extractStringNamed("note", element);
return new NoteCommand(note);
}
public void validateNote(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters);
final JsonElement element = this.fromApiJsonHelper.parse(json);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("note");
final String note = this.fromApiJsonHelper.extractStringNamed("note", element);
baseDataValidator.reset().parameter("note").value(note).notBlank().notExceedingLengthOf(1000);
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -0,0 +1,45 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.note.service;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.portfolio.note.domain.NoteType;
public class NoteEnumerations {
public static EnumOptionData noteType(final Integer id) {
return noteType(NoteType.fromInt(id));
}
public static EnumOptionData noteType(final NoteType type) {
EnumOptionData optionData = null;
switch (type) {
case CLIENT:
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Client note");
break;
case LOAN:
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Loan note");
break;
case LOAN_TRANSACTION:
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Loan transaction note");
break;
case DEPOSIT:
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Deposit transaction note");
break;
case SAVING:
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Saving transaction note");
break;
case GROUP:
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Group note");
break;
default:
break;
}
return optionData;
}
}
@@ -0,0 +1,17 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.note.service;
import java.util.Collection;
import org.mifosplatform.portfolio.note.data.NoteData;
public interface NoteReadPlatformService {
NoteData retrieveNote(final Long noteId, Long resourceId, Integer noteTypeId);
Collection<NoteData> retrieveNotesByResource(final Long resourceId, final Integer noteTypeId);
}
@@ -0,0 +1,120 @@
package org.mifosplatform.portfolio.note.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.mifosplatform.portfolio.note.data.NoteData;
import org.mifosplatform.portfolio.note.domain.NoteType;
import org.mifosplatform.portfolio.note.exception.NoteNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
public class NoteReadPlatformServiceImpl implements NoteReadPlatformService {
private final JdbcTemplate jdbcTemplate;
@Autowired
public NoteReadPlatformServiceImpl(final TenantAwareRoutingDataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
private static final class NoteMapper implements RowMapper<NoteData> {
public String schema() {
return " select n.id as id, n.client_id as clientId, n.group_id as groupId, n.loan_id as loanId, n.loan_transaction_id as transactionId, n.deposit_account_id as depositAccountId, "
+ " n.saving_account_id as savingAccountId, n.note_type_enum as noteTypeEnum, n.note as note, n.created_date as createdDate, n.createdby_id as createdById, "
+ " cb.username as createdBy, n.lastmodified_date as lastModifiedDate, n.lastmodifiedby_id as lastModifiedById, mb.username as modifiedBy "
+ " from m_note n left join m_appuser cb on cb.id=n.createdby_id left join m_appuser mb on mb.id=n.lastmodifiedby_id ";
}
@Override
public NoteData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = JdbcSupport.getLong(rs, "id");
final Long clientId = JdbcSupport.getLong(rs, "clientId");
final Long groupId = JdbcSupport.getLong(rs, "groupId");
final Long loanId = JdbcSupport.getLong(rs, "loanId");
final Long transactionId = JdbcSupport.getLong(rs, "transactionId");
final Long depositAccountId = JdbcSupport.getLong(rs, "depositAccountId");
final Long savingAccountId = JdbcSupport.getLong(rs, "savingAccountId");
final Integer noteTypeId = JdbcSupport.getInteger(rs, "noteTypeEnum");
final EnumOptionData noteType = NoteEnumerations.noteType(noteTypeId);
final String note = rs.getString("note");
final DateTime createdDate = JdbcSupport.getDateTime(rs, "createdDate");
final Long createdById = JdbcSupport.getLong(rs, "createdById");
final DateTime lastModifiedDate = JdbcSupport.getDateTime(rs, "lastModifiedDate");
final Long lastModifiedById = JdbcSupport.getLong(rs, "lastModifiedById");
final String createdByUsername = rs.getString("createdBy");
final String updatedByUsername = rs.getString("modifiedBy");
return new NoteData(id, clientId, groupId, loanId, transactionId, depositAccountId, savingAccountId, noteType, note,
createdDate, createdById, createdByUsername, lastModifiedDate, lastModifiedById, updatedByUsername);
}
}
@Override
public NoteData retrieveNote(final Long noteId, final Long resourceId, final Integer noteTypeId) {
final NoteType noteType = NoteType.fromInt(noteTypeId);
try {
final NoteMapper rm = new NoteMapper();
String conditionSql = getResourceCondition(noteType);
if (StringUtils.isNotBlank(conditionSql)) {
conditionSql = " and " + conditionSql;
}
final String sql = rm.schema() + " where n.id = ? " + conditionSql + " order by n.created_date DESC";
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { noteId, resourceId });
} catch (final EmptyResultDataAccessException e) {
throw new NoteNotFoundException(noteId, resourceId, noteType.name().toLowerCase());
}
}
@Override
public Collection<NoteData> retrieveNotesByResource(final Long resourceId, final Integer noteTypeId) {
final NoteType noteType = NoteType.fromInt(noteTypeId);
final NoteMapper rm = new NoteMapper();
String conditionSql = getResourceCondition(noteType);
final String sql = rm.schema() + " where " + conditionSql + " order by n.created_date DESC";
return this.jdbcTemplate.query(sql, rm, new Object[] { resourceId });
}
public static String getResourceCondition(final NoteType noteType) {
String conditionSql = "";
switch (noteType) {
case CLIENT:
conditionSql = " n.client_id = ? ";
break;
case LOAN:
conditionSql = " n.loan_id = ? ";
break;
case LOAN_TRANSACTION:
conditionSql = " n.loan_transaction_id = ? ";
break;
case DEPOSIT:
conditionSql = " n.deposit_account_id = ? ";
break;
case SAVING:
conditionSql = " n.saving_account_id = ? ";
break;
case GROUP:
conditionSql = " n.group_id = ? ";
break;
default:
break;
}
return conditionSql;
}
}
@@ -0,0 +1,13 @@
package org.mifosplatform.portfolio.note.service;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
public interface NoteWritePlatformService {
CommandProcessingResult createNote(JsonCommand command);
CommandProcessingResult updateNote(JsonCommand command);
CommandProcessingResult deleteNote(JsonCommand command);
}
@@ -0,0 +1,198 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.note.service;
import java.util.Map;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientRepository;
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.group.domain.GroupRepository;
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepository;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionRepository;
import org.mifosplatform.portfolio.loanaccount.exception.LoanNotFoundException;
import org.mifosplatform.portfolio.loanaccount.exception.LoanTransactionNotFoundException;
import org.mifosplatform.portfolio.note.domain.Note;
import org.mifosplatform.portfolio.note.domain.NoteRepository;
import org.mifosplatform.portfolio.note.domain.NoteType;
import org.mifosplatform.portfolio.note.exception.NoteNotFoundException;
import org.mifosplatform.portfolio.note.serialization.NoteCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.savingsaccount.domain.SavingAccount;
import org.mifosplatform.portfolio.savingsaccount.domain.SavingAccountRepository;
import org.mifosplatform.portfolio.savingsaccount.exception.SavingAccountNotFoundException;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccount;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountRepository;
import org.mifosplatform.portfolio.savingsdepositaccount.exception.DepositAccountNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class NoteWritePlatformServiceJpaRepositoryImpl implements NoteWritePlatformService {
private final NoteRepository noteRepository;
private final ClientRepository clientRepository;
private final GroupRepository groupRepository;
private final DepositAccountRepository depositAccountRepository;
private final SavingAccountRepository savingAccountRepository;
private final LoanRepository loanRepository;
private final LoanTransactionRepository loanTransactionRepository;
private final NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer;
@Autowired
public NoteWritePlatformServiceJpaRepositoryImpl(final NoteRepository noteRepository, final ClientRepository clientRepository,
final GroupRepository groupRepository, final DepositAccountRepository depositAccountRepository,
final SavingAccountRepository savingAccountRepository, final LoanRepository loanRepository,
final LoanTransactionRepository loanTransactionRepository, final NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer) {
this.noteRepository = noteRepository;
this.clientRepository = clientRepository;
this.groupRepository = groupRepository;
this.depositAccountRepository = depositAccountRepository;
this.savingAccountRepository = savingAccountRepository;
this.loanRepository = loanRepository;
this.loanTransactionRepository = loanTransactionRepository;
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
}
@Override
public CommandProcessingResult createNote(final JsonCommand command) {
this.fromApiJsonDeserializer.validateNote(command.json());
final Note newNote = getNewNote(command);
this.noteRepository.save(newNote);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(newNote.getId()) //
.build();
}
@Override
public CommandProcessingResult updateNote(final JsonCommand command) {
this.fromApiJsonDeserializer.validateNote(command.json());
final Note noteForUpdate = getNoteForUpdate(command);
final Map<String, Object> changes = noteForUpdate.update(command);
if (!changes.isEmpty()) {
this.noteRepository.saveAndFlush(noteForUpdate);
}
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(noteForUpdate.getId()) //
.with(changes) //
.build();
}
@Override
public CommandProcessingResult deleteNote(JsonCommand command) {
final Note noteForDelete = getNoteForUpdate(command);
this.noteRepository.delete(noteForDelete);
return new CommandProcessingResultBuilder() //
.withCommandId(null) //
.withEntityId(command.entityId()) //
.build();
}
private Note getNewNote(final JsonCommand command) {
final String resourceUrl = command.getSupportedEntityType();
final Long resourceId = command.getSupportedEntityId();
final NoteType type = NoteType.fromApiUrl(resourceUrl);
Note newNote = null;
final String note = command.stringValueOfParameterNamed("note");
switch (type) {
case CLIENT: {
final Client client = this.clientRepository.findOne(resourceId);
if (client == null) { throw new ClientNotFoundException(resourceId); }
newNote = Note.clientNoteFromJson(client, command);
}
break;
case DEPOSIT: {
final DepositAccount depositAccount = this.depositAccountRepository.findOne(resourceId);
if (depositAccount == null) { throw new DepositAccountNotFoundException(resourceId); }
newNote = Note.depositNote(depositAccount, note);
}
break;
case GROUP: {
final Group group = this.groupRepository.findOne(resourceId);
if (group == null) { throw new GroupNotFoundException(resourceId); }
newNote = Note.groupNoteFromJson(group, command);
}
break;
case LOAN: {
final Loan loan = this.loanRepository.findOne(resourceId);
if (loan == null) { throw new LoanNotFoundException(resourceId); }
newNote = Note.loanNote(loan, note);
}
break;
case LOAN_TRANSACTION: {
final LoanTransaction loanTransaction = this.loanTransactionRepository.findOne(resourceId);
if (loanTransaction == null) { throw new LoanTransactionNotFoundException(resourceId); }
final Loan loan = loanTransaction.getLoan();
newNote = Note.loanTransactionNote(loan, loanTransaction, note);
}
break;
case SAVING: {
final SavingAccount savingAccount = this.savingAccountRepository.findOne(resourceId);
if (savingAccount == null) { throw new SavingAccountNotFoundException(resourceId); }
newNote = Note.savingNote(savingAccount, note);
}
break;
}
return newNote;
}
private Note getNoteForUpdate(final JsonCommand command) {
final String resourceUrl = command.getSupportedEntityType();
final Long resourceId = command.getSupportedEntityId();
final Long noteId = command.entityId();
final NoteType type = NoteType.fromApiUrl(resourceUrl);
Note noteForUpdate = null;
switch (type) {
case CLIENT: {
noteForUpdate = this.noteRepository.findByClientIdAndId(resourceId, noteId);
}
break;
case DEPOSIT: {
noteForUpdate = this.noteRepository.findByDepositAccountIdAndId(resourceId, noteId);
}
break;
case GROUP: {
noteForUpdate = this.noteRepository.findByGroupIdAndId(resourceId, noteId);
}
break;
case LOAN: {
noteForUpdate = this.noteRepository.findByLoanIdAndId(resourceId, noteId);
}
break;
case LOAN_TRANSACTION: {
noteForUpdate = this.noteRepository.findByLoanTransactionIdAndId(resourceId, noteId);
}
break;
case SAVING: {
noteForUpdate = this.noteRepository.findBySavingAccountIdAndId(resourceId, noteId);
}
break;
}
if (noteForUpdate == null) { throw new NoteNotFoundException(noteId, resourceId, type.name().toLowerCase()); }
return noteForUpdate;
}
}
@@ -18,8 +18,8 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.client.domain.Note;
import org.mifosplatform.portfolio.client.domain.NoteRepository;
import org.mifosplatform.portfolio.note.domain.Note;
import org.mifosplatform.portfolio.note.domain.NoteRepository;
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountForLookup;
import org.mifosplatform.portfolio.savingsaccount.domain.SavingAccount;
import org.mifosplatform.portfolio.savingsaccount.domain.SavingAccountRepository;
@@ -21,8 +21,8 @@ import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityExce
import org.mifosplatform.infrastructure.security.exception.NoAuthorizationException;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.portfolio.client.domain.Note;
import org.mifosplatform.portfolio.client.domain.NoteRepository;
import org.mifosplatform.portfolio.note.domain.Note;
import org.mifosplatform.portfolio.note.domain.NoteRepository;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountsForLookup;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccount;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountRepository;