survey enhancement

This commit is contained in:
Nazeer Hussain Shaik
2017-09-22 12:37:17 +05:30
parent df16dc3cad
commit d857d8b47a
13 changed files with 553 additions and 153 deletions
@@ -18,7 +18,6 @@
*/
package org.apache.fineract.spm.api;
import java.util.Collections;
import java.util.List;
import javax.ws.rs.Consumes;
@@ -33,9 +32,8 @@ import org.apache.fineract.infrastructure.security.service.PlatformSecurityConte
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.fineract.spm.data.ScorecardData;
import org.apache.fineract.spm.domain.Scorecard;
import org.apache.fineract.spm.domain.Survey;
import org.apache.fineract.spm.exception.SurveyNotFoundException;
import org.apache.fineract.spm.service.ScorecardReadPlatformService;
import org.apache.fineract.spm.service.ScorecardService;
import org.apache.fineract.spm.service.SpmService;
import org.apache.fineract.spm.util.ScorecardMapper;
@@ -45,7 +43,7 @@ import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Path("/surveys/{surveyId}/scorecards")
@Path("/surveys/scorecards")
@Component
@Scope("singleton")
public class ScorecardApiResource {
@@ -54,68 +52,63 @@ public class ScorecardApiResource {
private final SpmService spmService;
private final ScorecardService scorecardService;
private final ClientRepositoryWrapper clientRepositoryWrapper;
private final ScorecardReadPlatformService scorecardReadPlatformService;
@Autowired
public ScorecardApiResource(final PlatformSecurityContext securityContext, final SpmService spmService,
final ScorecardService scorecardService, final ClientRepositoryWrapper clientRepositoryWrapper) {
super();
final ScorecardService scorecardService, final ClientRepositoryWrapper clientRepositoryWrapper,
final ScorecardReadPlatformService scorecardReadPlatformService) {
this.securityContext = securityContext;
this.spmService = spmService;
this.scorecardService = scorecardService;
this.clientRepositoryWrapper = clientRepositoryWrapper;
this.scorecardReadPlatformService = scorecardReadPlatformService;
}
@GET
@Path("{surveyId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Transactional
public List<ScorecardData> findBySurvey(@PathParam("surveyId") final Long surveyId) {
this.securityContext.authenticatedUser();
final Survey survey = findSurvey(surveyId);
final List<Scorecard> scorecards = this.scorecardService.findBySurvey(survey);
if (scorecards != null) {
return ScorecardMapper.map(scorecards);
}
return Collections.EMPTY_LIST;
this.spmService.findById(surveyId);
return (List<ScorecardData>) this.scorecardReadPlatformService.retrieveScorecardBySurvey(surveyId);
}
@POST
@Path("{surveyId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Transactional
public void createScorecard(@PathParam("surveyId") final Long surveyId, final ScorecardData scorecardData) {
final AppUser appUser = this.securityContext.authenticatedUser();
final Survey survey = findSurvey(surveyId);
final Survey survey = this.spmService.findById(surveyId);
final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(scorecardData.getClientId());
this.scorecardService.createScorecard(ScorecardMapper.map(scorecardData, survey, appUser, client));
}
@Path("/clients/{clientId}")
@GET
@Path("{surveyId}/clients/{clientId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Transactional
public List<ScorecardData> findBySurveyClient(@PathParam("surveyId") final Long surveyId,
@PathParam("clientId") final Long clientId) {
public List<ScorecardData> findBySurveyAndClient(@PathParam("surveyId") final Long surveyId, @PathParam("clientId") final Long clientId) {
this.securityContext.authenticatedUser();
final Survey survey = findSurvey(surveyId);
final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
final List<Scorecard> scorecards = this.scorecardService.findBySurveyAndClient(survey, client);
if (scorecards != null) {
return ScorecardMapper.map(scorecards);
}
return Collections.EMPTY_LIST;
this.spmService.findById(surveyId);
this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
return (List<ScorecardData>) this.scorecardReadPlatformService.retrieveScorecardBySurveyAndClient(surveyId, clientId);
}
private Survey findSurvey(final Long surveyId) {
final Survey survey = this.spmService.findById(surveyId);
if (survey == null) {
throw new SurveyNotFoundException(surveyId);
}
return survey;
@GET
@Path("clients/{clientId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Transactional
public List<ScorecardData> findByClient(@PathParam("clientId") final Long clientId) {
this.securityContext.authenticatedUser();
this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
return (List<ScorecardData>) this.scorecardReadPlatformService.retrieveScorecardByClient(clientId);
}
}
@@ -18,10 +18,23 @@
*/
package org.apache.fineract.spm.api;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
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.MediaType;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.spm.data.SurveyData;
import org.apache.fineract.spm.domain.Survey;
import org.apache.fineract.spm.exception.SurveyNotFoundException;
import org.apache.fineract.spm.service.SpmService;
import org.apache.fineract.spm.util.SurveyMapper;
import org.springframework.beans.factory.annotation.Autowired;
@@ -29,10 +42,7 @@ import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.Gson;
@Path("/surveys")
@Component
@@ -43,8 +53,7 @@ public class SpmApiResource {
private final SpmService spmService;
@Autowired
public SpmApiResource(final PlatformSecurityContext securityContext,
final SpmService spmService) {
public SpmApiResource(final PlatformSecurityContext securityContext, final SpmService spmService) {
this.securityContext = securityContext;
this.spmService = spmService;
}
@@ -55,17 +64,13 @@ public class SpmApiResource {
@Transactional
public List<SurveyData> fetchActiveSurveys() {
this.securityContext.authenticatedUser();
final List<SurveyData> result = new ArrayList<>();
final List<Survey> surveys = this.spmService.fetchValidSurveys();
if (surveys != null) {
for (final Survey survey : surveys) {
result.add(SurveyMapper.map(survey));
}
}
return result;
}
@@ -76,13 +81,7 @@ public class SpmApiResource {
@Transactional
public SurveyData findSurvey(@PathParam("id") final Long id) {
this.securityContext.authenticatedUser();
final Survey survey = this.spmService.findById(id);
if (survey == null) {
throw new SurveyNotFoundException(id);
}
return SurveyMapper.map(survey);
}
@@ -90,12 +89,25 @@ public class SpmApiResource {
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Transactional
public void createSurvey(final SurveyData surveyData) {
public String createSurvey(final SurveyData surveyData) {
this.securityContext.authenticatedUser();
final Survey survey = SurveyMapper.map(surveyData);
final Survey survey = SurveyMapper.map(surveyData, new Survey());
this.spmService.createSurvey(survey);
return getResponse(survey.getId());
}
@PUT
@Path("/{id}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Transactional
public String editSurvey(@PathParam("id") final Long id, final SurveyData surveyData) {
this.securityContext.authenticatedUser();
final Survey surveyToUpdate = this.spmService.findById(id);
final Survey survey = SurveyMapper.map(surveyData, surveyToUpdate);
this.spmService.updateSurvey(survey);
return getResponse(survey.getId());
}
@DELETE
@@ -105,7 +117,13 @@ public class SpmApiResource {
@Transactional
public void deactivateSurvey(@PathParam("id") final Long id) {
this.securityContext.authenticatedUser();
this.spmService.deactivateSurvey(id);
}
private String getResponse(Long id) {
Gson gson = new Gson();
HashMap<String, Object> response = new HashMap<>();
response.put("resourceId", id);
return gson.toJson(response);
}
}
@@ -18,58 +18,96 @@
*/
package org.apache.fineract.spm.data;
import java.util.Date;
import java.util.ArrayList;
import java.util.List;
public class ScorecardData {
private Long id;
private Long userId;
private String username;
private Long clientId;
private Date createdOn;
private Long surveyId;
private String surveyName;
private List<ScorecardValue> scorecardValues;
public ScorecardData() {
super();
}
public ScorecardData(final Long userId, final Long clientId, final Date createdOn,
final List<ScorecardValue> scorecardValues) {
super();
private ScorecardData(final Long id, final Long userId, final String username, final Long surveyId, final String surveyName,
final Long clientId) {
this.id = id;
this.userId = userId;
this.clientId = clientId;
this.createdOn = createdOn;
this.scorecardValues = scorecardValues;
this.scorecardValues = new ArrayList<>();
this.surveyId = surveyId;
this.surveyName = surveyName;
this.username = username;
}
public static ScorecardData instance(final Long id, final Long userId, final String username, final Long surveyId,
final String surveyName, final Long clientId) {
return new ScorecardData(id, userId, username, surveyId, surveyName, clientId);
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public Long getClientId() {
return clientId;
}
public void setClientId(Long clientId) {
this.clientId = clientId;
}
public Date getCreatedOn() {
return createdOn;
}
public void setCreatedOn(Date createdOn) {
this.createdOn = createdOn;
}
public List<ScorecardValue> getScorecardValues() {
return scorecardValues;
}
public void setScorecardValues(List<ScorecardValue> scorecardValues) {
this.scorecardValues = scorecardValues;
if (this.scorecardValues == null) {
this.scorecardValues = new ArrayList<>();
}
this.scorecardValues.addAll(scorecardValues);
}
public String getUsername() {
return this.username;
}
public Long getSurveyId() {
return this.surveyId;
}
public String getSurveyName() {
return this.surveyName;
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public void setUsername(String username) {
this.username = username;
}
public void setClientId(Long clientId) {
this.clientId = clientId;
}
public void setSurveyId(Long surveyId) {
this.surveyId = surveyId;
}
public void setSurveyName(String surveyName) {
this.surveyName = surveyName;
}
}
@@ -18,21 +18,28 @@
*/
package org.apache.fineract.spm.data;
import java.util.Date;
public class ScorecardValue {
private Long questionId;
private Long responseId;
private Integer value;
private Date createdOn;
public ScorecardValue() {
super();
}
public ScorecardValue(final Long questionId, final Long responseId, final Integer value) {
super();
private ScorecardValue(final Long questionId, final Long responseId, final Integer value, final Date createdOn) {
this.questionId = questionId;
this.responseId = responseId;
this.value = value;
this.createdOn = createdOn;
}
public static ScorecardValue instance(final Long questionId, final Long responseId, final Integer value, final Date createdOn) {
return new ScorecardValue(questionId, responseId, value, createdOn);
}
public Long getQuestionId() {
@@ -58,4 +65,16 @@ public class ScorecardValue {
public void setValue(Integer value) {
this.value = value;
}
public Date getCreatedOn() {
return this.createdOn;
}
public void setCreatedOn(Date createdOn) {
this.createdOn = createdOn;
}
}
@@ -21,6 +21,8 @@ package org.apache.fineract.spm.domain;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -28,11 +30,11 @@ import java.util.List;
@Table(name = "m_surveys")
public class Survey extends AbstractPersistableCustom<Long> {
@OneToMany(mappedBy = "survey", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@OneToMany(mappedBy = "survey", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval=true)
@OrderBy("sequenceNo")
private List<Component> components;
@OneToMany(mappedBy = "survey", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@OneToMany(mappedBy = "survey", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval=true)
@OrderBy("sequenceNo")
private List<Question> questions;
@@ -73,7 +75,13 @@ public class Survey extends AbstractPersistableCustom<Long> {
}
public void setQuestions(List<Question> questions) {
this.questions = questions;
if(this.questions != null){
this.questions.clear();;
}else{
this.questions = new ArrayList<>();
}
this.questions.addAll(questions);
}
public String getKey() {
@@ -0,0 +1,95 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.spm.domain;
import java.util.ArrayList;
import java.util.List;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.spm.util.SurveyApiConstants;
import org.springframework.stereotype.Component;
@Component
public class SurveyValidator {
public void validate(final Survey survey) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(SurveyApiConstants.SURVEY_RESOURCE_NAME);
baseDataValidator.reset().parameter(SurveyApiConstants.keyParamName).value(survey.getKey()).notNull().notBlank()
.notExceedingLengthOf(SurveyApiConstants.maxKeyLength);
baseDataValidator.reset().parameter(SurveyApiConstants.nameParamName).value(survey.getName()).notNull().notBlank()
.notExceedingLengthOf(SurveyApiConstants.maxNameLength);
baseDataValidator.reset().parameter(SurveyApiConstants.countryCodeParamName).value(survey.getCountryCode()).notNull().notBlank()
.notExceedingLengthOf(SurveyApiConstants.maxCountryCodeLength);
baseDataValidator.reset().parameter(SurveyApiConstants.descriptionParamName).value(survey.getDescription()).ignoreIfNull()
.notExceedingLengthOf(SurveyApiConstants.maxDescriptionLength);
List<Question> questions = survey.getQuestions();
baseDataValidator.reset().parameter(SurveyApiConstants.questionParamName).value(questions).notNull();
validateQuestions(baseDataValidator, questions);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void validateQuestions(final DataValidatorBuilder baseDataValidator, List<Question> questions) {
if (questions != null) {
baseDataValidator.reset().parameter(SurveyApiConstants.questionParamName + "." + SurveyApiConstants.lengthParamName)
.value(questions.toArray()).arrayNotEmpty();
for (Question question : questions) {
baseDataValidator.reset().parameter(SurveyApiConstants.questionParamName + "." + SurveyApiConstants.keyParamName)
.value(question.getKey()).notNull().notExceedingLengthOf(SurveyApiConstants.maxKeyLength);
baseDataValidator.reset().parameter(SurveyApiConstants.questionParamName + "." + SurveyApiConstants.textParamName)
.value(question.getText()).notNull().notExceedingLengthOf(SurveyApiConstants.maxTextLength);
baseDataValidator.reset().parameter(SurveyApiConstants.questionParamName + "." + SurveyApiConstants.descriptionParamName)
.value(question.getDescription()).ignoreIfNull().notExceedingLengthOf(SurveyApiConstants.maxDescriptionLength);
validateOptions(baseDataValidator, question);
}
}
}
private void validateOptions(final DataValidatorBuilder baseDataValidator, Question question) {
List<Response> responses = question.getResponses();
baseDataValidator.reset().parameter(SurveyApiConstants.questionParamName + "." + SurveyApiConstants.optionsParamName)
.value(responses).notNull();
if (responses != null) {
baseDataValidator.reset().parameter(SurveyApiConstants.questionParamName + "." + SurveyApiConstants.optionsParamName)
.value(responses.toArray()).arrayNotEmpty();
for (Response response : responses) {
baseDataValidator.reset().parameter(SurveyApiConstants.optionsParamName + "." + SurveyApiConstants.textParamName)
.value(response.getText()).notNull().notExceedingLengthOf(SurveyApiConstants.maxTextLength);
baseDataValidator.reset().parameter(SurveyApiConstants.optionsParamName + "." + SurveyApiConstants.valueParamName)
.value(response.getValue()).notNull().notGreaterThanMax(SurveyApiConstants.maxOptionsValue);
}
}
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException(dataValidationErrors);
}
}
}
@@ -0,0 +1,33 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.spm.service;
import java.util.Collection;
import org.apache.fineract.spm.data.ScorecardData;
public interface ScorecardReadPlatformService {
Collection<ScorecardData> retrieveScorecardByClient(final Long clientId);
Collection<ScorecardData> retrieveScorecardBySurveyAndClient(final Long surveyId,final Long clientId);
Collection<ScorecardData> retrieveScorecardBySurvey(final Long surveyId);
}
@@ -0,0 +1,144 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.spm.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.spm.data.ScorecardData;
import org.apache.fineract.spm.data.ScorecardValue;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
public class ScorecardReadPlatformServiceImpl implements ScorecardReadPlatformService {
private final JdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context;
@Autowired
public ScorecardReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource) {
this.context = context;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
private static final class ScorecardMapper implements RowMapper<ScorecardData> {
public String schema() {
StringBuilder sb = new StringBuilder(50);
sb.append(" sc.id as id, sc.survey_id as surveyId, s.a_name as surveyName, ");
sb.append(" sc.client_id as clientId,");
sb.append(" sc.user_id as userId, user.username as username ");
sb.append(" from m_survey_scorecards sc ");
sb.append(" left join m_surveys s ON s.id = sc.survey_id ");
sb.append(" left join m_appuser user ON user.id = sc.user_id ");
return sb.toString();
}
@Override
public ScorecardData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final Long surveyId = rs.getLong("surveyId");
final String surveyName = rs.getString("surveyName");
final Long clientId = rs.getLong("clientId");
final Long userId = rs.getLong("userId");
final String username = rs.getString("username");
return ScorecardData.instance(id, userId, username, surveyId, surveyName, clientId);
}
}
private static final class ScorecardValueMapper implements RowMapper<ScorecardValue> {
public String schema() {
StringBuilder sb = new StringBuilder(50);
sb.append(" sc.question_id as questionId, sc.response_id as responseId, ");
sb.append(" sc.created_on as createdOn, sc.a_value as value ");
sb.append(" from m_survey_scorecards sc ");
sb.append(" where sc.survey_id = ? and sc.client_id = ? ");
return sb.toString();
}
@Override
public ScorecardValue mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long questionId = rs.getLong("questionId");
final Long responseId = rs.getLong("responseId");
final LocalDate createdOn = JdbcSupport.getLocalDate(rs, "createdOn");
final Integer value = rs.getInt("value");
return ScorecardValue.instance(questionId, responseId, value, createdOn.toDate());
}
}
List<ScorecardValue> getScorecardValueBySurveyAndClient(final Long surveyId, final Long clientId) {
ScorecardValueMapper scvm = new ScorecardValueMapper();
String sql = "select " + scvm.schema();
return this.jdbcTemplate.query(sql, scvm, new Object[] { surveyId, clientId });
}
Collection<ScorecardData> updateScorecardValues(Collection<ScorecardData> scorecard) {
for (ScorecardData scorecardData : scorecard) {
scorecardData.setScorecardValues(getScorecardValueBySurveyAndClient(scorecardData.getSurveyId(), scorecardData.getClientId()));
}
return scorecard;
}
@Override
public Collection<ScorecardData> retrieveScorecardBySurvey(Long surveyId) {
this.context.authenticatedUser();
ScorecardMapper scm = new ScorecardMapper();
String sql = "select " + scm.schema() + " where sc.survey_id = ? " + " group by sc.survey_id, sc.client_id ";
Collection<ScorecardData> scorecardDatas = this.jdbcTemplate.query(sql, scm, new Object[] { surveyId });
updateScorecardValues(scorecardDatas);
return scorecardDatas;
}
@Override
public Collection<ScorecardData> retrieveScorecardByClient(Long clientId) {
this.context.authenticatedUser();
ScorecardMapper scm = new ScorecardMapper();
String sql = "select " + scm.schema() + " where sc.client_id = ? " + " group by sc.survey_id, sc.client_id ";
Collection<ScorecardData> scorecardDatas = this.jdbcTemplate.query(sql, scm, new Object[] { clientId });
updateScorecardValues(scorecardDatas);
return scorecardDatas;
}
@Override
public Collection<ScorecardData> retrieveScorecardBySurveyAndClient(Long surveyId, Long clientId) {
this.context.authenticatedUser();
ScorecardMapper scm = new ScorecardMapper();
String sql = "select " + scm.schema() + " where sc.survey_id = ? and sc.client_id = ? " + " group by sc.survey_id, sc.client_id ";
Collection<ScorecardData> scorecardDatas = this.jdbcTemplate.query(sql, scm, new Object[] { surveyId, clientId });
updateScorecardValues(scorecardDatas);
return scorecardDatas;
}
}
@@ -18,29 +18,39 @@
*/
package org.apache.fineract.spm.service;
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.spm.domain.Survey;
import org.apache.fineract.spm.domain.SurveyValidator;
import org.apache.fineract.spm.exception.SurveyNotFoundException;
import org.apache.fineract.spm.repository.SurveyRepository;
import org.apache.openjpa.persistence.EntityExistsException;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import javax.persistence.PersistenceException;
@Service
public class SpmService {
private final PlatformSecurityContext securityContext;
private final SurveyRepository surveyRepository;
private final SurveyValidator surveyValidator;
@Autowired
public SpmService(final PlatformSecurityContext securityContext,
final SurveyRepository surveyRepository) {
final SurveyRepository surveyRepository,
final SurveyValidator surveyValidator) {
super();
this.securityContext = securityContext;
this.surveyRepository = surveyRepository;
this.surveyValidator = surveyValidator;
}
public List<Survey> fetchValidSurveys() {
@@ -51,61 +61,83 @@ public class SpmService {
public Survey findById(final Long id) {
this.securityContext.authenticatedUser();
return this.surveyRepository.findOne(id);
Survey survey = this.surveyRepository.findOne(id);
if (survey == null) {
throw new SurveyNotFoundException(id);
}
return survey;
}
public Survey createSurvey(final Survey survey) {
this.securityContext.authenticatedUser();
this.surveyValidator.validate(survey);
final Survey previousSurvey = this.surveyRepository.findByKey(survey.getKey(), new Date());
if (previousSurvey != null) {
this.deactivateSurvey(previousSurvey.getId());
}
// set valid from to start of today
final DateTime validFrom = DateTime
.now()
.withHourOfDay(0)
.withMinuteOfHour(0)
.withSecondOfMinute(0)
.withMillisOfSecond(0);
final DateTime validFrom = getStartOfToday();
survey.setValidFrom(validFrom.toDate());
// set valid from to end in 100 years
final DateTime validTo = validFrom
.withDayOfMonth(31)
.withMonthOfYear(12)
.withHourOfDay(23)
.withMinuteOfHour(59)
.withSecondOfMinute(59)
.withMillisOfSecond(999)
.plusYears(100);
final DateTime validTo = validFrom.withDayOfMonth(31).withMonthOfYear(12).withHourOfDay(23).withMinuteOfHour(59)
.withSecondOfMinute(59).withMillisOfSecond(999).plusYears(100);
survey.setValidTo(validTo.toDate());
return this.surveyRepository.save(survey);
try {
this.surveyRepository.saveAndFlush(survey);
} catch (final EntityExistsException dve) {
handleDataIntegrityIssues(dve, dve, survey.getKey());
} catch (final DataIntegrityViolationException dve) {
handleDataIntegrityIssues(dve.getMostSpecificCause(), dve, survey.getKey());
} catch (final JpaSystemException dve) {
handleDataIntegrityIssues(dve.getMostSpecificCause(), dve, survey.getKey());
} catch (final PersistenceException dve) {
handleDataIntegrityIssues(dve, dve, survey.getKey());
}
return survey ;
}
public Survey updateSurvey(final Survey survey) {
try {
this.surveyValidator.validate(survey);
this.surveyRepository.saveAndFlush(survey);
} catch (final EntityExistsException dve) {
handleDataIntegrityIssues(dve, dve, survey.getKey());
} catch (final DataIntegrityViolationException dve) {
handleDataIntegrityIssues(dve.getMostSpecificCause(), dve, survey.getKey());
} catch (final JpaSystemException dve) {
handleDataIntegrityIssues(dve.getMostSpecificCause(), dve, survey.getKey());
} catch (final PersistenceException dve) {
handleDataIntegrityIssues(dve, dve, survey.getKey());
}
return survey;
}
public void deactivateSurvey(final Long id) {
this.securityContext.authenticatedUser();
final Survey survey = this.surveyRepository.findOne(id);
final Survey survey = findById(id);
final DateTime dateTime = getStartOfToday().minusMillis(1);
survey.setValidTo(dateTime.toDate());
if (survey != null) {
// set valid to to yesterday night
final DateTime dateTime = DateTime
.now()
.withHourOfDay(23)
.withMinuteOfHour(59)
.withSecondOfMinute(59)
.withMillisOfSecond(999)
.minusDays(1);
survey.setValidTo(dateTime.toDate());
this.surveyRepository.save(survey);
}
public static DateTime getStartOfToday() {
return DateTime.now().withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0);
}
private void handleDataIntegrityIssues(final Throwable realCause, final Exception dve, String key) {
this.surveyRepository.save(survey);
}
if (realCause.getMessage().contains("m_survey_scorecards")) { throw new PlatformDataIntegrityException(
"error.msg.survey.cannot.be.modified.as.used.in.client.survey",
"Survey can not be edited as it is already used in client survey", "name", key); }
if (realCause.getMessage().contains("key")) { throw new PlatformDataIntegrityException("error.msg.survey.duplicate.key",
"Survey with key already exists", "name", key); }
throw new PlatformDataIntegrityException("error.msg.survey.unknown.data.integrity.issue",
"Unknown data integrity issue with resource: " + realCause.getMessage());
}
}
@@ -18,7 +18,10 @@
*/
package org.apache.fineract.spm.util;
import org.apache.fineract.organisation.staff.domain.Staff;
import java.util.ArrayList;
import java.util.List;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.spm.data.ScorecardData;
import org.apache.fineract.spm.data.ScorecardValue;
@@ -28,38 +31,12 @@ import org.apache.fineract.spm.domain.Scorecard;
import org.apache.fineract.spm.domain.Survey;
import org.apache.fineract.useradministration.domain.AppUser;
import java.util.*;
public class ScorecardMapper {
private ScorecardMapper() {
super();
}
public static List<ScorecardData> map(final List<Scorecard> scorecards) {
final Map<Date, ScorecardData> scorecardDataMap = new HashMap<>();
ScorecardData scorecardData = null;
if (scorecards != null && scorecards.isEmpty()) {
for (Scorecard scorecard : scorecards) {
if ((scorecardData = scorecardDataMap.get(scorecard.getCreatedOn())) == null) {
scorecardData = new ScorecardData();
scorecardDataMap.put(scorecard.getCreatedOn(), scorecardData);
scorecardData.setUserId(scorecard.getAppUser().getId());
scorecardData.setClientId(scorecard.getClient().getId());
scorecardData.setCreatedOn(scorecard.getCreatedOn());
scorecardData.setScorecardValues(new ArrayList<ScorecardValue>());
}
scorecardData.getScorecardValues().add(new ScorecardValue(scorecard.getQuestion().getId(), scorecard.getResponse().getId(),
scorecard.getValue()));
}
return new ArrayList<>(scorecardDataMap.values());
}
return Collections.EMPTY_LIST;
}
public static List<Scorecard> map(final ScorecardData scorecardData, final Survey survey,
final AppUser appUser, final Client client) {
final List<Scorecard> scorecards = new ArrayList<>();
@@ -74,7 +51,7 @@ public class ScorecardMapper {
ScorecardMapper.setQuestionAndResponse(scorecardValue, scorecard, survey);
scorecard.setAppUser(appUser);
scorecard.setClient(client);
scorecard.setCreatedOn(scorecardData.getCreatedOn());
scorecard.setCreatedOn(DateUtils.getLocalDateOfTenant().toDate());
scorecard.setValue(scorecardValue.getValue());
}
}
@@ -97,4 +74,4 @@ public class ScorecardMapper {
}
}
}
}
}
@@ -0,0 +1,44 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.spm.util;
public class SurveyApiConstants {
public static final String SURVEY_RESOURCE_NAME = "survey";
public static final String keyParamName = "key";
public static final String nameParamName = "name";
public static final String countryCodeParamName = "countrycode";
public static final String descriptionParamName = "description";
public static final String sequenceNumberParamName = "sequenceNo";
public static final String valueParamName = "value";
public static final String questionParamName = "question";
public static final String optionsParamName = "options";
public static final String textParamName = "text";
public static final String lengthParamName = "length";
//to validate length/max value
public static final Integer maxCountryCodeLength = 2;
public static final Integer maxTextLength = 255;
public static final Integer maxNameLength = 255;
public static final Integer maxKeyLength = 32;
public static final Integer maxOptionsValue = 9999;
public static final Integer maxDescriptionLength = 4000;
}
@@ -45,8 +45,7 @@ public class SurveyMapper {
return surveyData;
}
public static Survey map(final SurveyData surveyData) {
final Survey survey = new Survey();
public static Survey map(final SurveyData surveyData, Survey survey) {
survey.setComponents(SurveyMapper.mapComponentDatas(surveyData.getComponentDatas(), survey));
survey.setQuestions(SurveyMapper.mapQuestionDatas(surveyData.getQuestionDatas(), survey));
survey.setKey(surveyData.getKey());
@@ -32,7 +32,7 @@
<tx:annotation-driven />
<context:component-scan base-package="org.apache.fineract.spm"/>
<context:component-scan base-package="org.apache.fineract.spm.**"/>
<jpa:repositories base-package="org.apache.fineract.spm.repository"/>