handle client resource and sub resources for notes and loanaccount summaries.

This commit is contained in:
Keith Woodlock
2012-05-15 16:45:16 +01:00
parent dc1c39c5ec
commit 04d4fbaf85
32 changed files with 1324 additions and 1695 deletions
@@ -1,60 +0,0 @@
package org.mifosng.platform;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.mifosng.data.ErrorResponse;
import org.mifosng.data.command.EnrollClientCommand;
import org.mifosng.platform.exceptions.NewDataValidationException;
public class EnrollClientCommandValidator {
private final EnrollClientCommand command;
public EnrollClientCommandValidator(EnrollClientCommand command) {
this.command = command;
}
public void validate() {
List<ErrorResponse> dataValidationErrors = new ArrayList<ErrorResponse>();
if (command.getOfficeId() == null || command.getOfficeId().equals(Long.valueOf(-1))) {
ErrorResponse error = new ErrorResponse("validation.msg.client.office.cannot.be.blank", "officeId");
dataValidationErrors.add(error);
}
if (StringUtils.isNotBlank(command.getFullname()) && (StringUtils.isNotBlank(command.getFirstname()) || StringUtils.isNotBlank(command.getLastname()))) {
ErrorResponse error = new ErrorResponse("validation.msg.client.fullname.cannot.entered.when.firstname.or.lastname.entered", "fullname");
dataValidationErrors.add(error);
}
if (StringUtils.isBlank(command.getFirstname()) && StringUtils.isBlank(command.getLastname()) ) {
if (StringUtils.isBlank(command.getFullname())) {
ErrorResponse error = new ErrorResponse("validation.msg.client.fullname.must.be.provide.or.firstname.lastname", "fullname");
dataValidationErrors.add(error);
}
} else {
if (StringUtils.isBlank(command.getFirstname())) {
ErrorResponse error = new ErrorResponse("validation.msg.client.firstname.cannot.be.blank", "firstname");
dataValidationErrors.add(error);
}
if (StringUtils.isBlank(command.getLastname())) {
ErrorResponse error = new ErrorResponse("validation.msg.client.lastname.cannot.be.blank", "lastname");
dataValidationErrors.add(error);
}
}
if (command.getJoiningDate() == null) {
ErrorResponse error = new ErrorResponse("validation.msg.client.joining.date.cannot.be.blank", "joiningDate");
dataValidationErrors.add(error);
}
if (!dataValidationErrors.isEmpty()) {
throw new NewDataValidationException(dataValidationErrors, "Data validation erros exist.");
}
}
}
@@ -2,20 +2,15 @@ package org.mifosng.platform;
import java.util.Collection;
import org.mifosng.data.ClientData;
import org.mifosng.data.ClientDataWithAccountsData;
import org.mifosng.data.LoanAccountData;
import org.mifosng.data.LoanRepaymentData;
import org.mifosng.data.NewLoanWorkflowStepOneData;
import org.mifosng.data.NoteData;
import org.mifosng.data.OrganisationReadModel;
public interface ReadPlatformService {
Collection<OrganisationReadModel> retrieveAll();
ClientDataWithAccountsData retrieveClientAccountDetails(Long clientId);
NewLoanWorkflowStepOneData retrieveClientAndProductDetails(Long clientId, Long productId);
LoanAccountData retrieveLoanAccountDetails(Long loanId);
@@ -25,11 +20,4 @@ public interface ReadPlatformService {
LoanRepaymentData retrieveNewLoanWaiverDetails(Long loanId);
LoanRepaymentData retrieveLoanRepaymentDetails(Long loanId, Long repaymentId);
ClientData retrieveNewClientDetails();
Collection<NoteData> retrieveAllClientNotes(Long clientId);
NoteData retrieveClientNote(Long clientId, Long noteId);
}
@@ -1,6 +1,5 @@
package org.mifosng.platform;
import static org.mifosng.platform.Specifications.clientsThatMatch;
import static org.mifosng.platform.Specifications.loanTransactionsThatMatch;
import static org.mifosng.platform.Specifications.loansThatMatch;
@@ -8,16 +7,11 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.sql.DataSource;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.mifosng.data.AppUserData;
import org.mifosng.data.ClientData;
import org.mifosng.data.ClientDataWithAccountsData;
import org.mifosng.data.CurrencyData;
import org.mifosng.data.DerivedLoanData;
import org.mifosng.data.LoanAccountData;
@@ -25,16 +19,12 @@ import org.mifosng.data.LoanProductData;
import org.mifosng.data.LoanRepaymentData;
import org.mifosng.data.MoneyData;
import org.mifosng.data.NewLoanWorkflowStepOneData;
import org.mifosng.data.NoteData;
import org.mifosng.data.OfficeData;
import org.mifosng.data.OrganisationReadModel;
import org.mifosng.platform.client.domain.Client;
import org.mifosng.platform.client.domain.ClientRepository;
import org.mifosng.platform.client.service.ClientReadPlatformService;
import org.mifosng.platform.currency.domain.ApplicationCurrency;
import org.mifosng.platform.currency.domain.ApplicationCurrencyRepository;
import org.mifosng.platform.currency.domain.Money;
import org.mifosng.platform.exceptions.PlatformResourceNotFoundException;
import org.mifosng.platform.exceptions.UnAuthenticatedUserException;
import org.mifosng.platform.loan.domain.Loan;
import org.mifosng.platform.loan.domain.LoanRepository;
@@ -44,7 +34,6 @@ import org.mifosng.platform.loanproduct.service.LoanProductReadPlatformService;
import org.mifosng.platform.user.domain.AppUser;
import org.mifosng.platform.user.service.AppUserReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.security.core.Authentication;
@@ -127,189 +116,6 @@ public class ReadPlatformServiceImpl implements ReadPlatformService {
}
}
@Override
public NoteData retrieveClientNote(Long clientId, Long noteId) {
try {
AppUser currentUser = extractAuthenticatedUser();
Collection<AppUserData> allUsers = this.appUserReadPlatformService.retrieveAllUsers();
NoteMapper noteMapper = new NoteMapper(allUsers);
String sql = "select " + noteMapper.schema()
+ " where n.org_id = ? and n.client_id = ? and n.id = ?";
return this.jdbcTemplate.queryForObject(sql, noteMapper,
new Object[] { currentUser.getOrganisation().getId(),
clientId, noteId });
} catch (EmptyResultDataAccessException e) {
throw new PlatformResourceNotFoundException(
"error.msg.client.id.invalid",
"Client with identifier {0} does not exist", clientId);
}
}
@Override
public Collection<NoteData> retrieveAllClientNotes(Long clientId) {
AppUser currentUser = extractAuthenticatedUser();
Collection<AppUserData> allUsers = this.appUserReadPlatformService.retrieveAllUsers();
NoteMapper noteMapper = new NoteMapper(allUsers);
String sql = "select "
+ noteMapper.schema()
+ " where n.org_id = ? and n.client_id = ? order by n.created_date DESC";
return this.jdbcTemplate.query(sql, noteMapper, new Object[] {
currentUser.getOrganisation().getId(), clientId });
}
protected static final class NoteMapper implements RowMapper<NoteData> {
private final Collection<AppUserData> allUsers;
public NoteMapper(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 portfolio_note n";
}
@Override
public NoteData mapRow(final ResultSet rs, final int rowNum)
throws SQLException {
Long id = rs.getLong("id");
Long clientId = rs.getLong("clientId");
Long loanId = rs.getLong("loanId");
Long transactionId = rs.getLong("transactionId");
Integer noteTypeId = rs.getInt("noteTypeEnum");
String note = rs.getString("note");
DateTime createdDate = new DateTime(rs.getTimestamp("createdDate"));
Long createdById = rs.getLong("createdById");
String createdByUsername = findUserById(createdById, allUsers);
DateTime lastModifiedDate = new DateTime(
rs.getTimestamp("lastModifiedDate"));
Long lastModifiedById = rs.getLong("lastModifiedById");
String updatedByUsername = findUserById(createdById, allUsers);
return new NoteData(id, clientId, loanId, transactionId,
noteTypeId, note, createdDate, createdById,
createdByUsername, lastModifiedDate, lastModifiedById,
updatedByUsername);
}
private String findUserById(Long createdById,
Collection<AppUserData> allUsers) {
String username = "";
for (AppUserData appUserData : allUsers) {
if (appUserData.getId().equals(createdById)) {
username = appUserData.getUsername();
break;
}
}
return username;
}
}
private List<OfficeData> retrieveOffices() {
AppUser currentUser = extractAuthenticatedUser();
String hierarchy = currentUser.getOffice().getHierarchy();
String hierarchySearchString = hierarchy + "%";
OfficeMapper rm = new OfficeMapper();
String sql = "select "
+ rm.officeSchema()
+ "where o.org_id = ? and o.hierarchy like ? order by o.hierarchy";
return this.jdbcTemplate.query(sql, rm, new Object[] {
currentUser.getOrganisation().getId(), hierarchySearchString });
}
protected static final class OfficeMapper implements RowMapper<OfficeData> {
public String officeSchema() {
return " o.id as id, o.name as name, o.external_id as externalId, o.opening_date as openingDate, o.hierarchy as hierarchy, parent.id as parentId, parent.name as parentName "
+ "from org_office o LEFT JOIN org_office AS parent ON parent.id = o.parent_id ";
}
@Override
public OfficeData mapRow(final ResultSet rs, final int rowNum)
throws SQLException {
Long id = rs.getLong("id");
String name = rs.getString("name");
String externalId = rs.getString("externalId");
LocalDate openingDate = new LocalDate(rs.getDate("openingDate"));
String hierarchy = rs.getString("hierarchy");
Long parentId = rs.getLong("parentId");
String parentName = rs.getString("parentName");
return new OfficeData(id, name, externalId, openingDate, hierarchy,
parentId, parentName);
}
}
@Override
public ClientDataWithAccountsData retrieveClientAccountDetails(
final Long clientId) {
AppUser currentUser = extractAuthenticatedUser();
ClientData clientAccount = this.clientReadPlatformService.retrieveIndividualClient(clientId);
// TODO - rewrite using jdbc sql approach
Client client = this.clientRepository.findOne(clientsThatMatch(
currentUser.getOrganisation(), clientId));
Collection<Loan> allLoans = this.loanRepository.findAll(loansThatMatch(
currentUser.getOrganisation(), client));
List<LoanAccountData> pendingApprovalLoans = new ArrayList<LoanAccountData>();
List<LoanAccountData> awaitingDisbursalLoans = new ArrayList<LoanAccountData>();
List<LoanAccountData> openLoans = new ArrayList<LoanAccountData>();
List<LoanAccountData> closedLoans = new ArrayList<LoanAccountData>();
for (Loan realLoan : allLoans) {
ApplicationCurrency currency = this.applicationCurrencyRepository
.findOneByCode(realLoan.getLoanRepaymentScheduleDetail()
.getPrincipal().getCurrencyCode());
CurrencyData currencyData = new CurrencyData(currency.getCode(),
currency.getName(), currency.getDecimalPlaces(),
currency.getDisplaySymbol(), currency.getNameCode());
LoanAccountData loan = convertToData(realLoan, currencyData);
if (loan.isClosed() || loan.isInterestRebateOutstanding()) {
closedLoans.add(loan);
} else if (loan.isPendingApproval()) {
pendingApprovalLoans.add(loan);
} else if (loan.isWaitingForDisbursal()) {
awaitingDisbursalLoans.add(loan);
} else if (loan.isOpen()) {
openLoans.add(loan);
}
}
Collections.sort(closedLoans, new ClosedLoanComparator());
return new ClientDataWithAccountsData(clientAccount,
pendingApprovalLoans, awaitingDisbursalLoans, openLoans,
closedLoans);
}
@Override
public LoanRepaymentData retrieveNewLoanRepaymentDetails(Long loanId) {
@@ -562,25 +368,4 @@ public class ReadPlatformServiceImpl implements ReadPlatformService {
.getRepaymentPeriodFrequencyType().toString(),
tolerance, loanData, waiveAllowed, interestRebateOwed);
}
@Override
public ClientData retrieveNewClientDetails() {
AppUser currentUser = extractAuthenticatedUser();
List<OfficeData> offices = retrieveOffices();
ClientData clientData = new ClientData();
clientData.setOfficeId(currentUser.getOffice().getId());
clientData.setOrganisationId(currentUser.getOrganisation().getId());
clientData.setAllowedOffices(offices);
clientData.setDisplayName("");
clientData.setFirstname("");
clientData.setLastname("");
clientData.setId(Long.valueOf(-1));
clientData.setJoinedDate(new LocalDate());
return clientData;
}
}
@@ -2,10 +2,8 @@ package org.mifosng.platform;
import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.command.AdjustLoanTransactionCommand;
import org.mifosng.data.command.EnrollClientCommand;
import org.mifosng.data.command.LoanStateTransitionCommand;
import org.mifosng.data.command.LoanTransactionCommand;
import org.mifosng.data.command.NoteCommand;
import org.mifosng.data.command.SubmitLoanApplicationCommand;
import org.mifosng.data.command.UndoLoanApprovalCommand;
import org.mifosng.data.command.UndoLoanDisbursalCommand;
@@ -16,9 +14,6 @@ public interface WritePlatformService {
void updateUsernamePasswordOnFirstTimeLogin(UpdateUsernamePasswordCommand command);
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_ENROLL_NEW_CLIENT_ROLE')")
Long enrollClient(EnrollClientCommand command);
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_DELETE_LOAN_THAT_IS_SUBMITTED_AND_NOT_APPROVED')")
EntityIdentifier deleteLoan(Long loanId);
@@ -49,8 +44,4 @@ public interface WritePlatformService {
EntityIdentifier adjustLoanTransaction(AdjustLoanTransactionCommand command);
EntityIdentifier waiveLoanAmount(LoanTransactionCommand command);
EntityIdentifier addClientNote(NoteCommand command);
EntityIdentifier updateNote(NoteCommand command);
}
@@ -1,7 +1,6 @@
package org.mifosng.platform;
import static org.mifosng.platform.Specifications.loansThatMatch;
import static org.mifosng.platform.Specifications.officesThatMatch;
import static org.mifosng.platform.Specifications.usersThatMatch;
import java.math.BigDecimal;
@@ -18,10 +17,8 @@ import org.mifosng.data.MoneyData;
import org.mifosng.data.ScheduledLoanInstallment;
import org.mifosng.data.command.AdjustLoanTransactionCommand;
import org.mifosng.data.command.CalculateLoanScheduleCommand;
import org.mifosng.data.command.EnrollClientCommand;
import org.mifosng.data.command.LoanStateTransitionCommand;
import org.mifosng.data.command.LoanTransactionCommand;
import org.mifosng.data.command.NoteCommand;
import org.mifosng.data.command.SubmitLoanApplicationCommand;
import org.mifosng.data.command.UndoLoanApprovalCommand;
import org.mifosng.data.command.UndoLoanDisbursalCommand;
@@ -56,8 +53,6 @@ import org.mifosng.platform.loan.domain.LoanStatusRepository;
import org.mifosng.platform.loan.domain.LoanTransaction;
import org.mifosng.platform.loan.domain.LoanTransactionRepository;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosng.platform.organisation.domain.Office;
import org.mifosng.platform.organisation.domain.OfficeRepository;
import org.mifosng.platform.user.domain.AppUser;
import org.mifosng.platform.user.domain.AppUserRepository;
import org.mifosng.platform.user.domain.PlatformUserRepository;
@@ -72,7 +67,6 @@ import org.springframework.transaction.annotation.Transactional;
@Service
public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformService {
private final OfficeRepository officeRepository;
private final PlatformUserRepository platformUserRepository;
private final PlatformPasswordEncoder platformPasswordEncoder;
private final ClientRepository clientRepository;
@@ -85,7 +79,6 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
@Autowired
public WritePlatformServiceJpaRepositoryImpl(
final OfficeRepository officeRepository,
final PlatformUserRepository platformUserRepository,
final PlatformPasswordEncoder platformPasswordEncoder,
final ClientRepository clientRepository,
@@ -96,7 +89,6 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
final LoanStatusRepository loanStatusRepository,
final CalculationPlatformService calculationPlatformService
) {
this.officeRepository = officeRepository;
this.platformUserRepository = platformUserRepository;
this.platformPasswordEncoder = platformPasswordEncoder;
this.clientRepository = clientRepository;
@@ -136,32 +128,6 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
}
}
@Transactional
@Override
public Long enrollClient(final EnrollClientCommand command) {
AppUser currentUser = extractAuthenticatedUser();
EnrollClientCommandValidator validator = new EnrollClientCommandValidator(command);
validator.validate();
Office clientOffice = this.officeRepository.findOne(officesThatMatch(
currentUser.getOrganisation(), command.getOfficeId()));
String firstname = command.getFirstname();
String lastname = command.getLastname();
if (StringUtils.isNotBlank(command.getFullname())) {
lastname = command.getFullname();
firstname = null;
}
Client newClient = Client.newClient(currentUser.getOrganisation(), clientOffice, firstname, lastname, command.getJoiningDate(), command.getExternalId());
this.clientRepository.save(newClient);
return newClient.getId();
}
private AppUser extractAuthenticatedUser() {
AppUser currentUser = null;
SecurityContext context = SecurityContextHolder.getContext();
@@ -678,30 +644,4 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
return new EntityIdentifier(loan.getClient().getId());
}
@Transactional
@Override
public EntityIdentifier addClientNote(NoteCommand command) {
AppUser currentUser = extractAuthenticatedUser();
Client clientForUpdate = this.clientRepository.findOne(command.getClientId());
Note note = Note.clientNote(currentUser.getOrganisation(), clientForUpdate, command.getNote());
this.noteRepository.save(note);
return new EntityIdentifier(note.getId());
}
@Transactional
@Override
public EntityIdentifier updateNote(NoteCommand command) {
Note noteForUpdate = this.noteRepository.findOne(command.getId());
noteForUpdate.update(command.getNote());
return new EntityIdentifier(noteForUpdate.getId());
}
}
@@ -4,16 +4,26 @@ import java.util.Collection;
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.MediaType;
import javax.ws.rs.core.Response;
import org.joda.time.LocalDate;
import org.mifosng.data.ClientData;
import org.mifosng.data.ClientList;
import org.mifosng.platform.WritePlatformService;
import org.mifosng.data.ClientLoanAccountSummaryCollectionData;
import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.NoteData;
import org.mifosng.data.NoteDataList;
import org.mifosng.data.command.EnrollClientCommand;
import org.mifosng.data.command.NoteCommand;
import org.mifosng.platform.api.infrastructure.ApiDataConversionService;
import org.mifosng.platform.client.service.ClientReadPlatformService;
import org.mifosng.platform.client.service.ClientWritePlatformService;
import org.mifosng.platform.user.domain.AppUser;
import org.mifosng.platform.user.domain.AppUserRepository;
import org.springframework.beans.factory.annotation.Autowired;
@@ -33,7 +43,10 @@ public class ClientApiResource {
private ClientReadPlatformService clientReadPlatformService;
@Autowired
private WritePlatformService writePlatformService;
private ClientWritePlatformService clientWritePlatformService;
@Autowired
private ApiDataConversionService apiDataConversionService;
@Autowired
private AppUserRepository appUserRepository;
@@ -71,77 +84,102 @@ public class ClientApiResource {
return Response.ok().entity(clientData).build();
}
// @GET
// @Path("template")
// @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
// @Produces({ MediaType.APPLICATION_JSON})
// public Response newClientDetails() {
//
// hardcodeUserIntoSecurityContext();
//
// ClientData clientData = this.clientReadPlatformService.retrieveNewClientDetails();
//
// return Response.ok().entity(clientData).build();
// }
//
// @POST
// @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
// @Produces({ MediaType.APPLICATION_JSON })
// public Response enrollClient(final EnrollClientCommand command) {
//
// hardcodeUserIntoSecurityContext();
//
// Long clientId = this.writePlatformService.enrollClient(command);
//
// return Response.ok().entity(new EntityIdentifier(clientId)).build();
// }
//
//
// @GET
// @Path("{clientId}/withaccounts")
// @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
// @Produces({ MediaType.APPLICATION_JSON })
// public Response retrieveClientAccount(@PathParam("clientId") final Long clientId) {
//
// hardcodeUserIntoSecurityContext();
//
// ClientDataWithAccountsData clientAccount = this.clientReadPlatformService.retrieveClientAccountDetails(clientId);
//
// return Response.ok().entity(clientAccount).build();
// }
//
// @POST
// @Path("{clientId}/note/new")
// @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
// @Produces({ MediaType.APPLICATION_JSON})
// public Response addNewClientNote(@PathParam("clientId") final Long clientId, final NoteCommand command) {
//
// hardcodeUserIntoSecurityContext();
//
// EntityIdentifier identifier = this.writePlatformService.addClientNote(command);
//
// return Response.ok().entity(identifier).build();
// }
//
// @GET
// @Path("{clientId}/note/all")
// @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
// @Produces({ MediaType.APPLICATION_JSON})
// public Response retrieveAllClientNotes(@PathParam("clientId") final Long clientId) {
//
// Collection<NoteData> notes = this.clientReadPlatformService.retrieveAllClientNotes(clientId);
//
// return Response.ok().entity(new NoteDataList(notes)).build();
// }
//
// @GET
// @Path("{clientId}/note/{noteId}")
// @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
// @Produces({ MediaType.APPLICATION_JSON })
// public Response retrieveClientNote(@PathParam("clientId") final Long clientId, @PathParam("noteId") final Long noteId) {
//
// NoteData note = this.clientReadPlatformService.retrieveClientNote(clientId, noteId);
//
// return Response.ok().entity(note).build();
// }
@GET
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({ MediaType.APPLICATION_JSON})
public Response newClientDetails() {
hardcodeUserIntoSecurityContext();
ClientData clientData = this.clientReadPlatformService.retrieveNewClientDetails();
return Response.ok().entity(clientData).build();
}
@POST
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON })
public Response enrollClient(final EnrollClientCommand command) {
hardcodeUserIntoSecurityContext();
LocalDate joiningDate = apiDataConversionService.convertFrom(command.getJoiningDateFormatted(), "joiningDateFormatted", command.getDateFormat());
command.setJoiningDate(joiningDate);
Long clientId = this.clientWritePlatformService.enrollClient(command);
return Response.ok().entity(new EntityIdentifier(clientId)).build();
}
@GET
@Path("{clientId}/loans")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON })
public Response retrieveClientAccount(@PathParam("clientId") final Long clientId) {
hardcodeUserIntoSecurityContext();
ClientLoanAccountSummaryCollectionData clientAccount = this.clientReadPlatformService.retrieveClientAccountDetails(clientId);
return Response.ok().entity(clientAccount).build();
}
@GET
@Path("{clientId}/notes")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({ MediaType.APPLICATION_JSON})
public Response retrieveAllClientNotes(@PathParam("clientId") final Long clientId) {
hardcodeUserIntoSecurityContext();
Collection<NoteData> notes = this.clientReadPlatformService.retrieveAllClientNotes(clientId);
return Response.ok().entity(new NoteDataList(notes)).build();
}
@POST
@Path("{clientId}/notes")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({ MediaType.APPLICATION_JSON})
public Response addNewClientNote(@PathParam("clientId") final Long clientId, final NoteCommand command) {
hardcodeUserIntoSecurityContext();
command.setClientId(clientId);
EntityIdentifier identifier = this.clientWritePlatformService.addClientNote(command);
return Response.ok().entity(identifier).build();
}
@GET
@Path("{clientId}/notes/{noteId}")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON })
public Response retrieveClientNote(@PathParam("clientId") final Long clientId, @PathParam("noteId") final Long noteId) {
hardcodeUserIntoSecurityContext();
NoteData note = this.clientReadPlatformService.retrieveClientNote(clientId, noteId);
return Response.ok().entity(note).build();
}
@PUT
@Path("{clientId}/notes/{noteId}")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON })
public Response updateClientNote(@PathParam("clientId") final Long clientId, @PathParam("noteId") final Long noteId, final NoteCommand command) {
hardcodeUserIntoSecurityContext();
command.setClientId(clientId);
command.setId(noteId);
EntityIdentifier identifier = this.clientWritePlatformService.updateNote(command);
return Response.ok().entity(identifier).build();
}
}
@@ -0,0 +1,9 @@
package org.mifosng.platform.api.infrastructure;
import org.joda.time.LocalDate;
public interface ApiDataConversionService {
LocalDate convertFrom(String dateAsString, String parameterName, String dateFormat);
}
@@ -0,0 +1,36 @@
package org.mifosng.platform.api.infrastructure;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.mifosng.data.ApiParameterError;
import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
@Service
public class ApiDataConversionServiceImpl implements ApiDataConversionService {
@Override
public LocalDate convertFrom(String dateAsString, String parameterName, String dateFormat) {
LocalDate eventLocalDate = null;
if (StringUtils.isNotBlank(dateAsString)) {
try {
Locale locale = LocaleContextHolder.getLocale();
eventLocalDate = DateTimeFormat.forPattern(dateFormat).withLocale(locale).parseLocalDate(dateAsString.toLowerCase(locale));
} catch (IllegalArgumentException e) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.date.format", "The parameter " + parameterName + " is invalid.", parameterName, dateAsString);
dataValidationErrors.add(error);
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
}
}
return eventLocalDate;
}
}
@@ -1,9 +1,6 @@
package org.mifosng.platform.api.office;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@@ -15,22 +12,18 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.mifosng.data.ApiParameterError;
import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.OfficeData;
import org.mifosng.data.OfficeList;
import org.mifosng.data.command.OfficeCommand;
import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
import org.mifosng.platform.api.infrastructure.ApiDataConversionService;
import org.mifosng.platform.organisation.service.OfficeReadPlatformService;
import org.mifosng.platform.organisation.service.OfficeWritePlatformService;
import org.mifosng.platform.user.domain.AppUser;
import org.mifosng.platform.user.domain.AppUserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
@@ -48,6 +41,9 @@ public class OfficeApiResource {
@Autowired
private OfficeWritePlatformService writePlatformService;
@Autowired
private ApiDataConversionService apiDataConversionService;
@Autowired
private AppUserRepository appUserRepository;
@@ -88,7 +84,7 @@ public class OfficeApiResource {
public Response createOffice(final OfficeCommand command) {
hardcodeUserIntoSecurityContext();
LocalDate openingDate = parseStringToLocalDate(command.getOpeningDateFormatted(), "openingDateFormatted", command.getDateFormat());
LocalDate openingDate = apiDataConversionService.convertFrom(command.getOpeningDateFormatted(), "openingDateFormatted", command.getDateFormat());
command.setOpeningDate(openingDate);
Long officeId = this.writePlatformService.createOffice(command);
@@ -113,33 +109,15 @@ public class OfficeApiResource {
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON})
public Response updateOffice(@PathParam("officeId") final Long officeId, final OfficeCommand command) {
LocalDate openingDate = parseStringToLocalDate(command.getOpeningDateFormatted(), "openingDateFormatted", command.getDateFormat());
hardcodeUserIntoSecurityContext();
command.setId(officeId);
LocalDate openingDate = apiDataConversionService.convertFrom(command.getOpeningDateFormatted(), "openingDateFormatted", command.getDateFormat());
command.setOpeningDate(openingDate);
command.setId(officeId);
Long entityId = this.writePlatformService.updateOffice(command);
return Response.ok().entity(new EntityIdentifier(entityId)).build();
}
private LocalDate parseStringToLocalDate(String eventDate, String dateFieldIdentifier, String dateFormat) {
LocalDate eventLocalDate = null;
if (StringUtils.isNotBlank(eventDate)) {
try {
Locale locale = LocaleContextHolder.getLocale();
eventLocalDate = DateTimeFormat.forPattern(dateFormat).withLocale(locale).parseLocalDate(eventDate.toLowerCase(locale));
} catch (IllegalArgumentException e) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.date.format", "The parameter " + dateFieldIdentifier + " is invalid.", dateFieldIdentifier, eventDate);
dataValidationErrors.add(error);
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
}
}
return eventLocalDate;
}
}
@@ -3,10 +3,20 @@ package org.mifosng.platform.client.service;
import java.util.Collection;
import org.mifosng.data.ClientData;
import org.mifosng.data.ClientLoanAccountSummaryCollectionData;
import org.mifosng.data.NoteData;
public interface ClientReadPlatformService {
Collection<ClientData> retrieveAllIndividualClients();
ClientData retrieveIndividualClient(Long clientId);
ClientData retrieveNewClientDetails();
ClientLoanAccountSummaryCollectionData retrieveClientAccountDetails(Long clientId);
Collection<NoteData> retrieveAllClientNotes(Long clientId);
NoteData retrieveClientNote(Long clientId, Long noteId);
}
@@ -9,14 +9,20 @@ import java.util.List;
import javax.sql.DataSource;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.mifosng.data.AppUserData;
import org.mifosng.data.ClientData;
import org.mifosng.data.ClientLoanAccountSummaryCollectionData;
import org.mifosng.data.ClientLoanAccountSummaryData;
import org.mifosng.data.NoteData;
import org.mifosng.data.OfficeData;
import org.mifosng.platform.exceptions.PlatformResourceNotFoundException;
import org.mifosng.platform.organisation.domain.Organisation;
import org.mifosng.platform.organisation.service.OfficeReadPlatformService;
import org.mifosng.platform.security.PlatformSecurityContext;
import org.mifosng.platform.user.domain.AppUser;
import org.mifosng.platform.user.service.AppUserReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.RowMapper;
@@ -29,11 +35,14 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
private final SimpleJdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context;
private final OfficeReadPlatformService officeReadPlatformService;
private final AppUserReadPlatformService appUserReadPlatformService;
@Autowired
public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final DataSource dataSource, final OfficeReadPlatformService officeReadPlatformService) {
public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final DataSource dataSource, final OfficeReadPlatformService officeReadPlatformService,
final AppUserReadPlatformService appUserReadPlatformService) {
this.context = context;
this.officeReadPlatformService = officeReadPlatformService;
this.appUserReadPlatformService = appUserReadPlatformService;
this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
}
@@ -87,6 +96,27 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
}
}
@Override
public ClientData retrieveNewClientDetails() {
AppUser currentUser = context.authenticatedUser();
List<OfficeData> offices = new ArrayList<OfficeData>(officeReadPlatformService.retrieveAllOffices());
ClientData clientData = new ClientData();
clientData.setOfficeId(currentUser.getOffice().getId());
clientData.setOrganisationId(currentUser.getOrganisation().getId());
clientData.setAllowedOffices(offices);
clientData.setDisplayName("");
clientData.setFirstname("");
clientData.setLastname("");
clientData.setId(Long.valueOf(-1));
clientData.setJoinedDate(new LocalDate());
return clientData;
}
private static final class ClientMapper implements RowMapper<ClientData> {
private final List<OfficeData> offices;
@@ -140,4 +170,211 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
return match;
}
}
@Override
public ClientLoanAccountSummaryCollectionData retrieveClientAccountDetails(final Long clientId) {
try {
AppUser currentUser = this.context.authenticatedUser();
List<ClientLoanAccountSummaryData> pendingApprovalLoans = new ArrayList<ClientLoanAccountSummaryData>();
List<ClientLoanAccountSummaryData> awaitingDisbursalLoans = new ArrayList<ClientLoanAccountSummaryData>();
List<ClientLoanAccountSummaryData> openLoans = new ArrayList<ClientLoanAccountSummaryData>();
List<ClientLoanAccountSummaryData> closedLoans = new ArrayList<ClientLoanAccountSummaryData>();
ClientLoanAccountSummaryDataMapper rm = new ClientLoanAccountSummaryDataMapper();
String sql = "select " + rm.loanAccountSummarySchema() + " where l.client_id = ? and l.org_id = ?";
List<ClientLoanAccountSummaryData> results = this.jdbcTemplate.query(sql, rm, new Object[] {clientId, currentUser.getOrganisation().getId()});
if (results != null) {
for (ClientLoanAccountSummaryData row : results) {
if (row.isOpen()) {
openLoans.add(row);
} else if (row.isWaitingForDisbursal()) {
awaitingDisbursalLoans.add(row);
} else if (row.isPendingApproval()) {
pendingApprovalLoans.add(row);
} else {
closedLoans.add(row);
}
}
}
return new ClientLoanAccountSummaryCollectionData(pendingApprovalLoans, awaitingDisbursalLoans, openLoans, closedLoans);
} catch (EmptyResultDataAccessException e) {
throw new PlatformResourceNotFoundException(
"error.msg.client.id.invalid",
"Client with identifier {0} does not exist", clientId);
}
// Collection<Loan> allLoans = this.loanRepository.findAll(loansThatMatch(currentUser.getOrganisation(), client));
//
// List<LoanAccountData> pendingApprovalLoans = new ArrayList<LoanAccountData>();
// List<LoanAccountData> awaitingDisbursalLoans = new ArrayList<LoanAccountData>();
// List<LoanAccountData> openLoans = new ArrayList<LoanAccountData>();
// List<LoanAccountData> closedLoans = new ArrayList<LoanAccountData>();
//
// for (Loan realLoan : allLoans) {
//
// ApplicationCurrency currency = this.applicationCurrencyRepository
// .findOneByCode(realLoan.getLoanRepaymentScheduleDetail()
// .getPrincipal().getCurrencyCode());
//
// CurrencyData currencyData = new CurrencyData(currency.getCode(),
// currency.getName(), currency.getDecimalPlaces(),
// currency.getDisplaySymbol(), currency.getNameCode());
//
// LoanAccountData loan = convertToData(realLoan, currencyData);
//
// if (loan.isClosed() || loan.isInterestRebateOutstanding()) {
// closedLoans.add(loan);
// } else if (loan.isPendingApproval()) {
// pendingApprovalLoans.add(loan);
// } else if (loan.isWaitingForDisbursal()) {
// awaitingDisbursalLoans.add(loan);
// } else if (loan.isOpen()) {
// openLoans.add(loan);
// }
// }
//
// Collections.sort(closedLoans, new ClosedLoanComparator());
//
// return new ClientDataWithAccountsData(clientAccount,
// pendingApprovalLoans, awaitingDisbursalLoans, openLoans,
// closedLoans);
}
private static final class ClientLoanAccountSummaryDataMapper implements RowMapper<ClientLoanAccountSummaryData> {
public String loanAccountSummarySchema() {
StringBuilder loanAccountSummary = new StringBuilder("l.id as id, l.external_id as externalId,");
loanAccountSummary.append("l.product_id as productId, lp.name as productName,")
.append("l.loan_status_id as statusId, ls.display_name as statusName ")
.append("from portfolio_loan l ")
.append("LEFT JOIN portfolio_product_loan AS lp ON lp.id = l.product_id ")
.append("LEFT JOIN ref_loan_status AS ls ON ls.id = l.loan_status_id ");
return loanAccountSummary.toString();
}
@Override
public ClientLoanAccountSummaryData mapRow(final ResultSet rs, final int rowNum) throws SQLException {
Long id = rs.getLong("id");
String externalId = rs.getString("externalId");
Long productId = rs.getLong("productId");
String loanProductName = rs.getString("productName");
Integer loanStatusId = rs.getInt("statusId");
String lifeCycleStatusText = rs.getString("statusName");
LoanStatusMapper statusMapper = new LoanStatusMapper(loanStatusId);
boolean pendingApproval = statusMapper.isPendingApproval();
boolean waitingForDisbursal = statusMapper.isAwaitingDisbursal();
boolean open = statusMapper.isOpen();
boolean closed = statusMapper.isClosed();
// LocalDate lifeCycleStatusDate;
return new ClientLoanAccountSummaryData(id, externalId, productId, loanProductName, loanStatusId, lifeCycleStatusText, pendingApproval, waitingForDisbursal, open, closed);
}
}
@Override
public NoteData retrieveClientNote(Long clientId, Long noteId) {
try {
AppUser currentUser = context.authenticatedUser();
// FIXME - 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.org_id = ? and n.client_id = ? and n.id = ?";
return this.jdbcTemplate.queryForObject(sql, noteMapper,
new Object[] { currentUser.getOrganisation().getId(),
clientId, noteId });
} catch (EmptyResultDataAccessException e) {
throw new PlatformResourceNotFoundException(
"error.msg.client.id.invalid",
"Client with identifier {0} does not exist", clientId);
}
}
@Override
public Collection<NoteData> retrieveAllClientNotes(Long clientId) {
AppUser currentUser = context.authenticatedUser();
// FIXME - 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.org_id = ? and n.client_id = ? order by n.created_date DESC";
return this.jdbcTemplate.query(sql, noteMapper, new Object[] {
currentUser.getOrganisation().getId(), clientId });
}
private static final class NoteMapper implements RowMapper<NoteData> {
private final Collection<AppUserData> allUsers;
public NoteMapper(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 portfolio_note n";
}
@Override
public NoteData mapRow(final ResultSet rs, final int rowNum)
throws SQLException {
Long id = rs.getLong("id");
Long clientId = rs.getLong("clientId");
Long loanId = rs.getLong("loanId");
Long transactionId = rs.getLong("transactionId");
Integer noteTypeId = rs.getInt("noteTypeEnum");
String note = rs.getString("note");
DateTime createdDate = new DateTime(rs.getTimestamp("createdDate"));
Long createdById = rs.getLong("createdById");
String createdByUsername = findUserById(createdById, allUsers);
DateTime lastModifiedDate = new DateTime(
rs.getTimestamp("lastModifiedDate"));
Long lastModifiedById = rs.getLong("lastModifiedById");
String updatedByUsername = findUserById(createdById, allUsers);
return new NoteData(id, clientId, loanId, transactionId,
noteTypeId, note, createdDate, createdById,
createdByUsername, lastModifiedDate, lastModifiedById,
updatedByUsername);
}
private String findUserById(Long createdById,
Collection<AppUserData> allUsers) {
String username = "";
for (AppUserData appUserData : allUsers) {
if (appUserData.getId().equals(createdById)) {
username = appUserData.getUsername();
break;
}
}
return username;
}
}
}
@@ -0,0 +1,17 @@
package org.mifosng.platform.client.service;
import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.command.EnrollClientCommand;
import org.mifosng.data.command.NoteCommand;
import org.springframework.security.access.prepost.PreAuthorize;
public interface ClientWritePlatformService {
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_ENROLL_NEW_CLIENT_ROLE')")
Long enrollClient(EnrollClientCommand command);
// FIXME - add permission for adding and updating client notes.
EntityIdentifier addClientNote(NoteCommand command);
EntityIdentifier updateNote(NoteCommand command);
}
@@ -0,0 +1,92 @@
package org.mifosng.platform.client.service;
import static org.mifosng.platform.Specifications.officesThatMatch;
import org.apache.commons.lang.StringUtils;
import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.command.EnrollClientCommand;
import org.mifosng.data.command.NoteCommand;
import org.mifosng.platform.client.domain.Client;
import org.mifosng.platform.client.domain.ClientRepository;
import org.mifosng.platform.client.domain.Note;
import org.mifosng.platform.client.domain.NoteRepository;
import org.mifosng.platform.organisation.domain.Office;
import org.mifosng.platform.organisation.domain.OfficeRepository;
import org.mifosng.platform.security.PlatformSecurityContext;
import org.mifosng.platform.user.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWritePlatformService {
private final PlatformSecurityContext context;
private final ClientRepository clientRepository;
private final OfficeRepository officeRepository;
private final NoteRepository noteRepository;
@Autowired
public ClientWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final ClientRepository clientRepository,
final OfficeRepository officeRepository, NoteRepository noteRepository) {
this.context = context;
this.clientRepository = clientRepository;
this.officeRepository = officeRepository;
this.noteRepository = noteRepository;
}
@Transactional
@Override
public Long enrollClient(final EnrollClientCommand command) {
AppUser currentUser = context.authenticatedUser();
EnrollClientCommandValidator validator = new EnrollClientCommandValidator(command);
validator.validate();
Office clientOffice = this.officeRepository.findOne(officesThatMatch(currentUser.getOrganisation(), command.getOfficeId()));
String firstname = command.getFirstname();
String lastname = command.getLastname();
if (StringUtils.isNotBlank(command.getFullname())) {
lastname = command.getFullname();
firstname = null;
}
Client newClient = Client.newClient(currentUser.getOrganisation(), clientOffice, firstname, lastname, command.getJoiningDate(), command.getExternalId());
this.clientRepository.save(newClient);
return newClient.getId();
}
@Transactional
@Override
public EntityIdentifier addClientNote(NoteCommand command) {
AppUser currentUser = context.authenticatedUser();
// FIXME - check resource is found for current organisation - throw PlatformXXXException if not found.
Client clientForUpdate = this.clientRepository.findOne(command.getClientId());
Note note = Note.clientNote(currentUser.getOrganisation(), clientForUpdate, command.getNote());
this.noteRepository.save(note);
return new EntityIdentifier(note.getId());
}
@Transactional
@Override
public EntityIdentifier updateNote(NoteCommand command) {
AppUser currentUser = context.authenticatedUser();
// FIXME - check resource is found for current organisation - throw PlatformXXXException if not found.
Note noteForUpdate = this.noteRepository.findOne(command.getId());
noteForUpdate.update(command.getNote());
return new EntityIdentifier(noteForUpdate.getId());
}
}
@@ -0,0 +1,60 @@
package org.mifosng.platform.client.service;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.mifosng.data.ApiParameterError;
import org.mifosng.data.command.EnrollClientCommand;
import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
public class EnrollClientCommandValidator {
private final EnrollClientCommand command;
public EnrollClientCommandValidator(EnrollClientCommand command) {
this.command = command;
}
public void validate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
if (command.getOfficeId() == null || command.getOfficeId().equals(Long.valueOf(-1))) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.client.office.cannot.be.blank", "The parameter officeId cannot be blank.", "officeId");
dataValidationErrors.add(error);
}
if (StringUtils.isNotBlank(command.getFullname()) && (StringUtils.isNotBlank(command.getFirstname()) || StringUtils.isNotBlank(command.getLastname()))) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.client.fullname.cannot.entered.when.firstname.or.lastname.entered", "The parameter fullname cannot be blank.", "fullname");
dataValidationErrors.add(error);
}
if (StringUtils.isBlank(command.getFirstname()) && StringUtils.isBlank(command.getLastname()) ) {
if (StringUtils.isBlank(command.getFullname())) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.client.fullname.must.be.provide.or.firstname.lastname", "The parameter fullname cannot be blank or firstName and lastName must be both provided.", "fullname");
dataValidationErrors.add(error);
}
} else {
if (StringUtils.isBlank(command.getFirstname())) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.client.firstname.cannot.be.blank", "The parameter firstname cannot be blank.", "firstname");
dataValidationErrors.add(error);
}
if (StringUtils.isBlank(command.getLastname())) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.client.lastname.cannot.be.blank", "The parameter lastname cannot be blank.", "lastname");
dataValidationErrors.add(error);
}
}
if (command.getJoiningDate() == null) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.client.joining.date.cannot.be.blank", "The parameter joiningDate cannot be blank.", "joiningDate");
dataValidationErrors.add(error);
}
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
}
}
}
@@ -0,0 +1,34 @@
package org.mifosng.platform.client.service;
public class LoanStatusMapper {
private final Integer statusId;
public LoanStatusMapper(Integer statusId) {
this.statusId = statusId;
}
public boolean isPendingApproval() {
return Integer.valueOf(100).equals(statusId);
}
public boolean isAwaitingDisbursal() {
return Integer.valueOf(200).equals(statusId);
}
public boolean isOpen() {
return Integer.valueOf(300).equals(statusId);
}
public boolean isWithdrawnByClient() {
return Integer.valueOf(400).equals(statusId);
}
public boolean isRejected() {
return Integer.valueOf(500).equals(statusId);
}
public boolean isClosed() {
return Integer.valueOf(600).equals(statusId) || isWithdrawnByClient() || isRejected();
}
}
@@ -1,214 +0,0 @@
package org.mifosng.platform.rest;
import java.util.Arrays;
import java.util.Collection;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.mifosng.data.ClientData;
import org.mifosng.data.ClientDataWithAccountsData;
import org.mifosng.data.ClientList;
import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.ErrorResponse;
import org.mifosng.data.ErrorResponseList;
import org.mifosng.data.NoteData;
import org.mifosng.data.NoteDataList;
import org.mifosng.data.command.EnrollClientCommand;
import org.mifosng.data.command.NoteCommand;
import org.mifosng.platform.ReadPlatformService;
import org.mifosng.platform.WritePlatformService;
import org.mifosng.platform.client.service.ClientReadPlatformService;
import org.mifosng.platform.exceptions.ApplicationDomainRuleException;
import org.mifosng.platform.exceptions.UnAuthenticatedUserException;
import org.mifosng.platform.exceptions.NewDataValidationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Component;
@Path("/protected/client")
@Component
@Scope("singleton")
public class ClientResource {
@Autowired
private ReadPlatformService readPlatformService;
@Autowired
private ClientReadPlatformService clientReadPlatformService;
@Autowired
private WritePlatformService writePlatformService;
@GET
@Path("all")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response retrieveAllIndividualClients() {
Collection<ClientData> clients = this.clientReadPlatformService.retrieveAllIndividualClients();
return Response.ok().entity(new ClientList(clients)).build();
}
@GET
@Path("new")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response newClientDetails() {
try {
ClientData clientData = this.readPlatformService.retrieveNewClientDetails();
return Response.ok().entity(clientData).build();
} catch (UnAuthenticatedUserException e) {
throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build());
} catch (AccessDeniedException e) {
ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id");
ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse));
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build());
} catch (ApplicationDomainRuleException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build());
} catch (NewDataValidationException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build());
}
}
@POST
@Path("new")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response enrollClient(final EnrollClientCommand command) {
try {
Long clientId = this.writePlatformService.enrollClient(command);
return Response.ok().entity(new EntityIdentifier(clientId)).build();
} catch (UnAuthenticatedUserException e) {
throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build());
} catch (AccessDeniedException e) {
ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id");
ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse));
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build());
} catch (ApplicationDomainRuleException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build());
} catch (NewDataValidationException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build());
}
}
@GET
@Path("{clientId}")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response retrieveClientData(
@PathParam("clientId") final Long clientId) {
ClientData clientData = this.clientReadPlatformService
.retrieveIndividualClient(clientId);
return Response.ok().entity(clientData).build();
}
@GET
@Path("{clientId}/withaccounts")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response retrieveClientAccount(@PathParam("clientId") final Long clientId) {
try {
ClientDataWithAccountsData clientAccount = this.readPlatformService
.retrieveClientAccountDetails(clientId);
return Response.ok().entity(clientAccount).build();
} catch (UnAuthenticatedUserException e) {
throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build());
} catch (AccessDeniedException e) {
ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id");
ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse));
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build());
} catch (ApplicationDomainRuleException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build());
} catch (NewDataValidationException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build());
}
}
@POST
@Path("{clientId}/note/new")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response addNewClientNote(@PathParam("clientId") final Long clientId, final NoteCommand command) {
try {
EntityIdentifier identifier = this.writePlatformService.addClientNote(command);
return Response.ok().entity(identifier).build();
} catch (UnAuthenticatedUserException e) {
throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build());
} catch (AccessDeniedException e) {
ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id");
ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse));
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build());
} catch (ApplicationDomainRuleException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build());
} catch (NewDataValidationException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build());
}
}
@GET
@Path("{clientId}/note/all")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response retrieveAllClientNotes(@PathParam("clientId") final Long clientId) {
try {
Collection<NoteData> notes = this.readPlatformService.retrieveAllClientNotes(clientId);
return Response.ok().entity(new NoteDataList(notes)).build();
} catch (UnAuthenticatedUserException e) {
throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build());
} catch (AccessDeniedException e) {
ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id");
ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse));
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build());
} catch (ApplicationDomainRuleException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build());
} catch (NewDataValidationException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build());
}
}
@GET
@Path("{clientId}/note/{noteId}")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response retrieveClientNote(@PathParam("clientId") final Long clientId, @PathParam("noteId") final Long noteId) {
try {
NoteData note = this.readPlatformService.retrieveClientNote(clientId, noteId);
return Response.ok().entity(note).build();
} catch (UnAuthenticatedUserException e) {
throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build());
} catch (AccessDeniedException e) {
ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id");
ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse));
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build());
} catch (ApplicationDomainRuleException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build());
} catch (NewDataValidationException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build());
}
}
}
@@ -1,36 +0,0 @@
package org.mifosng.platform.rest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.command.NoteCommand;
import org.mifosng.platform.WritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/protected/note")
@Component
@Scope("singleton")
public class NoteResource {
@Autowired
private WritePlatformService writePlatformService;
@POST
@Path("{noteId}")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response updateClientAccount(@PathParam("noteId") final Long noteId, final NoteCommand command) {
EntityIdentifier identifier = this.writePlatformService.updateNote(command);
return Response.ok().entity(identifier).build();
}
}