Merge branch 'Fineract-521' into develop
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java
index 4758b01..fec8a21 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java
@@ -262,14 +262,19 @@
if (isOverdraftType != null) {
if (inClauseAdded) {
- sql += " and sp.allow_overdraft=?";
+ sql += " and sp.allow_overdraft=? and sp.deposit_type_enum = ?";
} else {
- sql += " where sp.allow_overdraft=?";
+ sql += " where sp.allow_overdraft=? and sp.deposit_type_enum = ?";
}
- return this.jdbcTemplate.query(sql, this.savingsProductLookupsRowMapper, isOverdraftType);
+ return this.jdbcTemplate.query(sql, this.savingsProductLookupsRowMapper, new Object[] {isOverdraftType, DepositAccountType.SAVINGS_DEPOSIT.getValue() });
}
-
- return this.jdbcTemplate.query(sql, this.savingsProductLookupsRowMapper);
+
+ if(inClauseAdded) {
+ sql += " and sp.deposit_type_enum = ?";
+ }else {
+ sql += " where sp.deposit_type_enum = ?";
+ }
+ return this.jdbcTemplate.query(sql, this.savingsProductLookupsRowMapper, new Object[] { DepositAccountType.SAVINGS_DEPOSIT.getValue() });
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/api/ScorecardApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/spm/api/ScorecardApiResource.java
index 84987da..e2927d5 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/spm/api/ScorecardApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/spm/api/ScorecardApiResource.java
@@ -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.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.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 @@
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);
}
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/api/SpmApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/spm/api/SpmApiResource.java
index 8da5c15..46afed0 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/spm/api/SpmApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/spm/api/SpmApiResource.java
@@ -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.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 @@
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 @@
@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 @@
@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 @@
@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 @@
@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);
+ }
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/data/ScorecardData.java b/fineract-provider/src/main/java/org/apache/fineract/spm/data/ScorecardData.java
index b19b79e..6c35993 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/spm/data/ScorecardData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/spm/data/ScorecardData.java
@@ -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;
+ }
+
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/data/ScorecardValue.java b/fineract-provider/src/main/java/org/apache/fineract/spm/data/ScorecardValue.java
index 9f22c2a..c45b19b 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/spm/data/ScorecardValue.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/spm/data/ScorecardValue.java
@@ -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 void setValue(Integer value) {
this.value = value;
}
+
+
+ public Date getCreatedOn() {
+ return this.createdOn;
+ }
+
+
+ public void setCreatedOn(Date createdOn) {
+ this.createdOn = createdOn;
+ }
+
+
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/domain/Survey.java b/fineract-provider/src/main/java/org/apache/fineract/spm/domain/Survey.java
index bd68905..ad4f961 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/spm/domain/Survey.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/spm/domain/Survey.java
@@ -21,6 +21,8 @@
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 @@
@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 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() {
diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/domain/SurveyValidator.java b/fineract-provider/src/main/java/org/apache/fineract/spm/domain/SurveyValidator.java
new file mode 100644
index 0000000..a3e2ee6
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/spm/domain/SurveyValidator.java
@@ -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);
+ }
+ }
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/service/ScorecardReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/spm/service/ScorecardReadPlatformService.java
new file mode 100644
index 0000000..78d74dc
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/spm/service/ScorecardReadPlatformService.java
@@ -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);
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/service/ScorecardReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/spm/service/ScorecardReadPlatformServiceImpl.java
new file mode 100644
index 0000000..2859a3c
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/spm/service/ScorecardReadPlatformServiceImpl.java
@@ -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;
+ }
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/service/SpmService.java b/fineract-provider/src/main/java/org/apache/fineract/spm/service/SpmService.java
index 424bdaf..52c159d 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/spm/service/SpmService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/spm/service/SpmService.java
@@ -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 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());
}
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/util/ScorecardMapper.java b/fineract-provider/src/main/java/org/apache/fineract/spm/util/ScorecardMapper.java
index c317ccd..60588d8 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/spm/util/ScorecardMapper.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/spm/util/ScorecardMapper.java
@@ -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.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 @@
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 @@
}
}
}
-}
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/util/SurveyApiConstants.java b/fineract-provider/src/main/java/org/apache/fineract/spm/util/SurveyApiConstants.java
new file mode 100644
index 0000000..6b93511
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/spm/util/SurveyApiConstants.java
@@ -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;
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/util/SurveyMapper.java b/fineract-provider/src/main/java/org/apache/fineract/spm/util/SurveyMapper.java
index 45ebd57..db3718d 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/spm/util/SurveyMapper.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/spm/util/SurveyMapper.java
@@ -45,8 +45,7 @@
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());
diff --git a/fineract-provider/src/main/resources/META-INF/spring/spmContext.xml b/fineract-provider/src/main/resources/META-INF/spring/spmContext.xml
index 4248110..d057b10 100644
--- a/fineract-provider/src/main/resources/META-INF/spring/spmContext.xml
+++ b/fineract-provider/src/main/resources/META-INF/spring/spmContext.xml
@@ -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"/>