Merge pull request #548 from ashok-conflux/MIFOSX-607

MIFOSX-607 - capture client atendance in collection sheet
This commit is contained in:
Vishwas Babu A J
2013-08-28 00:34:34 -07:00
23 changed files with 547 additions and 239 deletions
@@ -6,6 +6,7 @@
package org.mifosplatform.commands.service;
import org.mifosplatform.commands.domain.CommandWrapper;
import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType;
public class CommandWrapperBuilder {
@@ -1016,6 +1017,8 @@ public class CommandWrapperBuilder {
this.entityName = "GROUP";
this.entityId = groupId;
this.groupId = groupId;
this.supportedEntityId = groupId;
this.supportedEntityType = CalendarEntityType.GROUPS.name();
this.href = "/groups/" + groupId + "?command=saveCollectionSheet";
return this;
}
@@ -1145,6 +1148,8 @@ public class CommandWrapperBuilder {
this.actionName = "SAVECOLLECTIONSHEET";
this.entityName = "CENTER";
this.entityId = centerId;
this.supportedEntityId = centerId;
this.supportedEntityType = CalendarEntityType.CENTERS.name();
this.href = "/centers/" + centerId + "?command=saveCollectionSheet";
return this;
}
@@ -37,6 +37,7 @@ public class CalendarData {
private final Collection<LocalDate> recurringDates;
private final Collection<LocalDate> nextTenRecurringDates;
private final String humanReadable;
private final LocalDate recentEligibleMeetingDate;
private final LocalDate createdDate;
private final LocalDate lastUpdatedDate;
@@ -53,7 +54,7 @@ public class CalendarData {
public CalendarData(final Long id, final Long entityId, final EnumOptionData entityType, final String title, final String description,
final String location, final LocalDate startDate, final LocalDate endDate, final Integer duration, final EnumOptionData type,
final boolean repeating, final String recurrence, final EnumOptionData remindBy, final Integer firstReminder,
final Integer secondReminder, final String humanReadable, final LocalDate createdDate, final LocalDate lastUpdatedDate,
final Integer secondReminder, final String humanReadable, final LocalDate recentEligibleMeetingDate, final LocalDate createdDate, final LocalDate lastUpdatedDate,
final Long createdByUserId, final String createdByUsername, final Long lastUpdatedByUserId, final String lastUpdatedByUsername) {
this.id = id;
@@ -77,6 +78,7 @@ public class CalendarData {
this.recurringDates = null;
this.nextTenRecurringDates = null;
this.humanReadable = humanReadable;
this.recentEligibleMeetingDate = recentEligibleMeetingDate;
this.createdDate = createdDate;
this.lastUpdatedDate = lastUpdatedDate;
@@ -109,6 +111,7 @@ public class CalendarData {
this.recurringDates = calendarData.recurringDates;
this.nextTenRecurringDates = calendarData.nextTenRecurringDates;
this.humanReadable = calendarData.humanReadable;
this.recentEligibleMeetingDate = calendarData.recentEligibleMeetingDate;
this.createdDate = calendarData.createdDate;
this.lastUpdatedDate = calendarData.lastUpdatedDate;
this.createdByUserId = calendarData.createdByUserId;
@@ -117,7 +120,7 @@ public class CalendarData {
this.lastUpdatedByUsername = calendarData.lastUpdatedByUsername;
}
public CalendarData(final CalendarData calendarData, final Collection<LocalDate> recurringDates, final Collection<LocalDate> nextTenRecurringDates) {
public CalendarData(final CalendarData calendarData, final Collection<LocalDate> recurringDates, final Collection<LocalDate> nextTenRecurringDates, final LocalDate recentEligibleMeetingDate) {
this.id = calendarData.id;
this.entityId = calendarData.entityId;
this.entityType = calendarData.entityType;
@@ -139,6 +142,7 @@ public class CalendarData {
this.recurringDates = recurringDates;
this.nextTenRecurringDates = nextTenRecurringDates;
this.humanReadable = calendarData.humanReadable;
this.recentEligibleMeetingDate = recentEligibleMeetingDate;
this.createdDate = calendarData.createdDate;
this.lastUpdatedDate = calendarData.lastUpdatedDate;
this.createdByUserId = calendarData.createdByUserId;
@@ -165,9 +169,18 @@ public class CalendarData {
final Integer firstReminder = new Integer(0);
final Integer secondReminder = new Integer(0);
final String humanReadable = null;
final LocalDate recentEligibleMeetingDate = null;
final LocalDate createdDate = null;
final LocalDate lastUpdatedDate = null;
final Long createdByUserId = null;
final String createdByUsername = null;
final Long lastUpdatedByUserId = null;
final String lastUpdatedByUsername = null;
return new CalendarData(id, entityId, entityType, title, description, location, startDate, endDate, duration, type, repeating,
recurrence, remindBy, firstReminder, secondReminder, humanReadable, null, null, null, null, null, null);
recurrence, remindBy, firstReminder, secondReminder, humanReadable, recentEligibleMeetingDate, createdDate,
lastUpdatedDate, createdByUserId, createdByUsername, lastUpdatedByUserId, lastUpdatedByUsername);
}
public Long getId() {
@@ -0,0 +1,51 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.calendar.domain;
import org.mifosplatform.portfolio.calendar.exception.CalendarNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* <p>
* Wrapper for {@link CalendarRepository} that is responsible for checking
* if {@link Calendar} is returned when using <code>findOne</code>
* repository method and throwing an appropriate not found exception.
* </p>
*
* <p>
* This is to avoid need for checking and throwing in multiple areas of code
* base where {@link CalendarRepository} is required.
* </p>
*/
@Service
public class CalendarRepositoryWrapper {
private final CalendarRepository repository;
@Autowired
public CalendarRepositoryWrapper(final CalendarRepository repository) {
this.repository = repository;
}
public Calendar findOneWithNotFoundDetection(final Long calendarId) {
final Calendar calendar = this.repository.findOne(calendarId);
if (calendar == null) { throw new CalendarNotFoundException(calendarId); }
return calendar;
}
public void save(final Calendar calendar) {
this.repository.save(calendar);
}
public void delete(final Calendar calendar) {
this.repository.delete(calendar);
}
public void saveAndFlush(final Calendar calendar) {
this.repository.saveAndFlush(calendar);
}
}
@@ -81,9 +81,11 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
final String createdByUserName = rs.getString("creatingUserName");
final Long lastUpdatedByUserId = rs.getLong("updatingUserId");
final String lastUpdatedByUserName = rs.getString("updatingUserName");
final LocalDate recentEligibleMeetingDate = null;
return new CalendarData(id, entityId, entityType, title, description, location, startDate, endDate, duration, type, repeating,
recurrence, remindBy, firstReminder, secondReminder, humanReadable, createdDate, lastUpdatedDate, createdByUserId,
recurrence, remindBy, firstReminder, secondReminder, humanReadable, recentEligibleMeetingDate, createdDate, lastUpdatedDate, createdByUserId,
createdByUserName, lastUpdatedByUserId, lastUpdatedByUserName);
}
}
@@ -207,7 +209,8 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
final Collection<LocalDate> recurringDates = CalendarUtils.getRecurringDates(rrule, seedDate, startDate, endDate, -1);
final Collection<LocalDate> nextTenRecurringDates = CalendarUtils.getRecurringDates(rrule, seedDate, endDate);
return new CalendarData(calendarData, recurringDates, nextTenRecurringDates);
final LocalDate recentEligibleMeetingDate = CalendarUtils.getRecentEligibleMeetingDate(rrule, seedDate);
return new CalendarData(calendarData, recurringDates, nextTenRecurringDates, recentEligibleMeetingDate);
}
@@ -415,4 +415,26 @@ public class CalendarUtils {
sqlCalendarTypeOptions += calendarTypeOptions.get(size - 1).toString();
return sqlCalendarTypeOptions;
}
public static LocalDate getRecentEligibleMeetingDate(final String recurringRule, final LocalDate seedDate){
LocalDate currentDate = DateUtils.getLocalDateOfTenant();
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
if (recur == null) { return null; }
if(isValidRecurringDate(recur, seedDate, currentDate)){
return currentDate;
}
if(recur.getFrequency().equals(Recur.DAILY)){
currentDate = currentDate.plusDays(recur.getInterval());
}else if(recur.getFrequency().equals(Recur.WEEKLY)){
currentDate = currentDate.plusWeeks(recur.getInterval());
}else if(recur.getFrequency().equals(Recur.MONTHLY)){
currentDate = currentDate.plusMonths(recur.getInterval());
}else if(recur.getFrequency().equals(Recur.YEARLY)){
currentDate = currentDate.plusYears(recur.getInterval());
}
return getNextRecurringDate(recur, seedDate, currentDate);
}
}
@@ -0,0 +1,37 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.collectionsheet;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class CollectionSheetConstants {
public static final String COLLECTIONSHEET_RESOURCE_NAME = "collectionsheet";
public static final String localeParamName = "locale";
public static final String dateFormatParamName = "dateFormat";
public static final String transactionDateParamName = "transactionDate";
public static final String actualDisbursementDateParamName = "actualDisbursementDate";
public static final String bulkRepaymentTransactionsParamName = "bulkRepaymentTransactions";
public static final String bulkDisbursementTransactionsParamName = "bulkDisbursementTransactions";
public static final String noteParamName = "note";
public static final String calendarIdParamName = "calendarId";
// attendance parameters
public static final String clientsAttendanceParamName = "clientsAttendance";
public static final String clientIdParamName = "clientId";
public static final String attendanceTypeParamName = "attendanceType";
public static final String loanIdParamName = "loanId";
public static final String transactionAmountParamName = "transactionAmount";
public static final Set<String> COLLECTIONSHEET_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
dateFormatParamName, transactionDateParamName, actualDisbursementDateParamName, bulkRepaymentTransactionsParamName,
bulkDisbursementTransactionsParamName, noteParamName, calendarIdParamName, clientsAttendanceParamName));
}
@@ -0,0 +1,154 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.collectionsheet.data;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.COLLECTIONSHEET_REQUEST_DATA_PARAMETERS;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.COLLECTIONSHEET_RESOURCE_NAME;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.attendanceTypeParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.bulkDisbursementTransactionsParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.bulkRepaymentTransactionsParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.calendarIdParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.clientIdParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.clientsAttendanceParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.loanIdParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.noteParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.transactionAmountParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.transactionDateParamName;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
@Component
public class CollectionSheetTransactionDataValidator {
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public CollectionSheetTransactionDataValidator(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
public void validateTransaction(final JsonCommand command) {
final String json = command.json();
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, COLLECTIONSHEET_REQUEST_DATA_PARAMETERS);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(COLLECTIONSHEET_RESOURCE_NAME);
final JsonElement element = fromApiJsonHelper.parse(json);
final LocalDate transactionDate = fromApiJsonHelper.extractLocalDateNamed(transactionDateParamName, element);
baseDataValidator.reset().parameter(transactionDateParamName).value(transactionDate).notNull();
final String note = fromApiJsonHelper.extractStringNamed(noteParamName, element);
if (StringUtils.isNotBlank(note)) {
baseDataValidator.reset().parameter(noteParamName).value(note).notExceedingLengthOf(1000);
}
final Long calendarId = this.fromApiJsonHelper.extractLongNamed(calendarIdParamName, element);
baseDataValidator.reset().parameter(calendarIdParamName).value(calendarId).notNull();
validateAttendanceDetails(element, baseDataValidator);
validateDisbursementTransactions(element, baseDataValidator);
validateRepaymentTransactions(element, baseDataValidator);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void validateAttendanceDetails(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
final JsonObject topLevelJsonElement = element.getAsJsonObject();
if (element.isJsonObject()) {
if (topLevelJsonElement.has(clientsAttendanceParamName) && topLevelJsonElement.get(clientsAttendanceParamName).isJsonArray()) {
final JsonArray array = topLevelJsonElement.get(clientsAttendanceParamName).getAsJsonArray();
for (int i = 0; i < array.size(); i++) {
final JsonObject attendanceElement = array.get(i).getAsJsonObject();
final Long clientId = this.fromApiJsonHelper.extractLongNamed(clientIdParamName, attendanceElement);
final Long attendanceType = this.fromApiJsonHelper.extractLongNamed(attendanceTypeParamName, attendanceElement);
baseDataValidator.reset().parameter(clientsAttendanceParamName + "[" + i + "]." + clientIdParamName).value(clientId)
.notNull().integerGreaterThanZero();
baseDataValidator.reset().parameter(clientsAttendanceParamName + "[" + i + "]." + attendanceTypeParamName)
.value(attendanceType).notNull().integerGreaterThanZero();
}
}
}
}
private void validateDisbursementTransactions(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
final JsonObject topLevelJsonElement = element.getAsJsonObject();
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
if (element.isJsonObject()) {
if (topLevelJsonElement.has(bulkDisbursementTransactionsParamName)
&& topLevelJsonElement.get(bulkDisbursementTransactionsParamName).isJsonArray()) {
final JsonArray array = topLevelJsonElement.get(bulkDisbursementTransactionsParamName).getAsJsonArray();
for (int i = 0; i < array.size(); i++) {
final JsonObject loanTransactionElement = array.get(i).getAsJsonObject();
final Long loanId = this.fromApiJsonHelper.extractLongNamed(loanIdParamName, loanTransactionElement);
final BigDecimal disbursementAmount = this.fromApiJsonHelper.extractBigDecimalNamed(transactionAmountParamName,
loanTransactionElement, locale);
baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].loan.id").value(loanId).notNull()
.integerGreaterThanZero();
baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].disbursement.amount").value(disbursementAmount)
.notNull().zeroOrPositiveAmount();
}
}
}
}
private void validateRepaymentTransactions(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
final JsonObject topLevelJsonElement = element.getAsJsonObject();
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
if (element.isJsonObject()) {
if (topLevelJsonElement.has(bulkRepaymentTransactionsParamName)
&& topLevelJsonElement.get(bulkRepaymentTransactionsParamName).isJsonArray()) {
final JsonArray array = topLevelJsonElement.get(bulkRepaymentTransactionsParamName).getAsJsonArray();
for (int i = 0; i < array.size(); i++) {
final JsonObject loanTransactionElement = array.get(i).getAsJsonObject();
final Long loanId = this.fromApiJsonHelper.extractLongNamed(loanIdParamName, loanTransactionElement);
final BigDecimal disbursementAmount = this.fromApiJsonHelper.extractBigDecimalNamed(transactionAmountParamName,
loanTransactionElement, locale);
baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].loan.id").value(loanId).notNull()
.integerGreaterThanZero();
baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].disbursement.amount").value(disbursementAmount)
.notNull().zeroOrPositiveAmount();
}
}
}
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
}
}
@@ -7,25 +7,30 @@ package org.mifosplatform.portfolio.collectionsheet.data;
import java.util.Collection;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
/**
* Immutable data object for clients with loans due for disbursement or collection.
*/
public class ClientLoansData {
public class JLGClientData {
private final Long clientId;
private final String clientName;
private Collection<LoanDueData> loans;
private final EnumOptionData attendanceType;
public ClientLoansData(final Long clientId, final String clientName, final Collection<LoanDueData> loans) {
public JLGClientData(final Long clientId, final String clientName, final Collection<LoanDueData> loans, final EnumOptionData attendanceType) {
this.clientId = clientId;
this.clientName = clientName;
this.loans = loans;
this.attendanceType = attendanceType;
}
public ClientLoansData(final Long clientId, final String clientName) {
public JLGClientData(final Long clientId, final String clientName, final EnumOptionData attendanceType) {
this.clientId = clientId;
this.clientName = clientName;
this.loans = null;
this.attendanceType = attendanceType;
}
public Long getClientId() {
@@ -6,8 +6,10 @@
package org.mifosplatform.portfolio.collectionsheet.data;
import java.util.Collection;
import java.util.List;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
/**
@@ -17,19 +19,23 @@ public class JLGCollectionSheetData {
private final LocalDate dueDate;
private final Collection<LoanProductData> loanProducts;
private final Collection<JLGClientsData> groups;
private final Collection<JLGGroupData> groups;
@SuppressWarnings("unused")
private final List<EnumOptionData> attendanceTypeOptions;
public JLGCollectionSheetData(final LocalDate date, final Collection<LoanProductData> loanProducts, final Collection<JLGClientsData> groups) {
public JLGCollectionSheetData(final LocalDate date, final Collection<LoanProductData> loanProducts,
final Collection<JLGGroupData> groups, final List<EnumOptionData> attendanceTypeOptions) {
this.dueDate = date;
this.loanProducts = loanProducts;
this.groups = groups;
this.attendanceTypeOptions = attendanceTypeOptions;
}
public LocalDate getDate() {
return this.dueDate;
}
public Collection<JLGClientsData> getGroups() {
public Collection<JLGGroupData> getGroups() {
return this.groups;
}
@@ -7,6 +7,7 @@ package org.mifosplatform.portfolio.collectionsheet.data;
import java.math.BigDecimal;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.organisation.monetary.data.CurrencyData;
/**
@@ -34,12 +35,13 @@ public class JLGCollectionSheetFlatData {
private BigDecimal interestDue = BigDecimal.ZERO;
private BigDecimal interestPaid = BigDecimal.ZERO;
private BigDecimal chargesDue = BigDecimal.ZERO;
private final EnumOptionData attendanceType;
public JLGCollectionSheetFlatData(final String groupName, final Long groupId, final Long staffId, final String staffName,
final Long levelId, final String levelName, final String clientName, final Long clientId, final Long loanId,
final String accountId, final Integer accountStatusId, final String productShortName, final Long productId,
final CurrencyData currency, final BigDecimal disbursementAmount, final BigDecimal principalDue,
final BigDecimal principalPaid, final BigDecimal interestDue, final BigDecimal interestPaid, final BigDecimal chargesDue) {
final BigDecimal principalPaid, final BigDecimal interestDue, final BigDecimal interestPaid, final BigDecimal chargesDue, final EnumOptionData attendanceType) {
this.groupName = groupName;
this.groupId = groupId;
this.staffId = staffId;
@@ -60,6 +62,7 @@ public class JLGCollectionSheetFlatData {
this.interestDue = interestDue;
this.interestPaid = interestPaid;
this.chargesDue = chargesDue;
this.attendanceType = attendanceType;
}
public String getGroupName() {
@@ -147,13 +150,13 @@ public class JLGCollectionSheetFlatData {
this.disbursementAmount, this.principalDue, this.principalPaid, this.interestDue, this.interestPaid, this.chargesDue);
}
public ClientLoansData getClientLoansData() {
return new ClientLoansData(this.clientId, this.clientName);
public JLGClientData getClientData() {
return new JLGClientData(this.clientId, this.clientName, this.attendanceType);
}
public JLGClientsData getJLGClientsData() {
public JLGGroupData getJLGGroupData() {
return new JLGClientsData(this.groupId, this.groupName, this.staffId, this.staffName, this.levelId, this.levelName);
return new JLGGroupData(this.groupId, this.groupName, this.staffId, this.staffName, this.levelId, this.levelName);
}
}
@@ -10,7 +10,7 @@ import java.util.Collection;
/**
* Immutable data object for groups with clients due for disbursement or collection.
*/
public class JLGClientsData {
public class JLGGroupData {
private final Long groupId;
private final String groupName;
@@ -18,9 +18,9 @@ public class JLGClientsData {
private final String staffName;
private final Long levelId;
private final String levelName;
private Collection<ClientLoansData> clients;
private Collection<JLGClientData> clients;
public JLGClientsData(final Long groupId, final String groupName, final Long staffId, final String staffName, final Long levelId,
public JLGGroupData(final Long groupId, final String groupName, final Long staffId, final String staffName, final Long levelId,
final String levelName) {
this.groupId = groupId;
this.groupName = groupName;
@@ -54,11 +54,11 @@ public class JLGClientsData {
return this.levelName;
}
public Collection<ClientLoansData> getCutomers() {
public Collection<JLGClientData> getClients() {
return this.clients;
}
public void setClients(final Collection<ClientLoansData> clients) {
public void setClients(final Collection<JLGClientData> clients) {
this.clients = clients;
}
}
@@ -5,22 +5,12 @@
*/
package org.mifosplatform.portfolio.collectionsheet.serialization;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
@@ -32,7 +22,6 @@ import org.springframework.stereotype.Component;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
/**
* Implementation of {@link FromApiJsonDeserializer} for
@@ -52,21 +41,12 @@ public final class CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer ex
public CollectionSheetBulkDisbursalCommand commandFromApiJson(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
//TODO: AA need to refactor transactionDate and actualDisbursementDate
//actualDisbursementDate used in Loan.disburse()
final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("transactionDate", "actualDisbursementDate", "bulkRepaymentTransactions", "bulkDisbursementTransactions", "note",
"locale", "dateFormat"));
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
final JsonElement element = this.fromApiJsonHelper.parse(json);
final LocalDate transactionDate = fromApiJsonHelper.extractLocalDateNamed("transactionDate", element);
final String note = fromApiJsonHelper.extractStringNamed("note", element);
final JsonObject topLevelJsonElement = element.getAsJsonObject();
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
final LocalDate transactionDate = fromApiJsonHelper.extractLocalDateNamed("transactionDate", element);
final String note = fromApiJsonHelper.extractStringNamed("note", element);
SingleDisbursalCommand[] loanDisbursementTransactions = null;
@@ -86,33 +66,4 @@ public final class CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer ex
}
return new CollectionSheetBulkDisbursalCommand(note, transactionDate, loanDisbursementTransactions);
}
public void validateBulkDisbursalTransaction(final CollectionSheetBulkDisbursalCommand bulkDisburseCommand) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.bulk.disbursement.transaction");
baseDataValidator.reset().parameter("transactionDate").value(bulkDisburseCommand.getTransactionDate()).notNull();
if (StringUtils.isNotBlank(bulkDisburseCommand.getNote())) {
baseDataValidator.reset().parameter("note").value(bulkDisburseCommand.getNote()).notExceedingLengthOf(1000);
}
final SingleDisbursalCommand[] loanDisbursements = bulkDisburseCommand.getDisburseTransactions();
if (loanDisbursements != null) {
for (int i = 0; i < loanDisbursements.length; i++) {
SingleDisbursalCommand singleLoanDisburseCommand = loanDisbursements[i];
baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].loan.id").value(singleLoanDisburseCommand.getLoanId())
.notNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].disbursement.amount")
.value(singleLoanDisburseCommand.getTransactionAmount()).notNull().zeroOrPositiveAmount();
}
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -5,22 +5,12 @@
*/
package org.mifosplatform.portfolio.collectionsheet.serialization;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
@@ -32,7 +22,6 @@ import org.springframework.stereotype.Component;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
/**
* Implementation of {@link FromApiJsonDeserializer} for
@@ -52,11 +41,6 @@ public final class CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer ex
public CollectionSheetBulkRepaymentCommand commandFromApiJson(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("transactionDate", "actualDisbursementDate", "bulkRepaymentTransactions", "bulkDisbursementTransactions", "note",
"locale", "dateFormat"));
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
final JsonElement element = this.fromApiJsonHelper.parse(json);
final LocalDate transactionDate = fromApiJsonHelper.extractLocalDateNamed("transactionDate", element);
@@ -84,33 +68,5 @@ public final class CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer ex
}
return new CollectionSheetBulkRepaymentCommand(note, transactionDate, loanRepaymentTransactions);
}
public void validateBulkRepaymentTransaction(final CollectionSheetBulkRepaymentCommand bulkRepaymentCommand) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.bulk.repayment.transaction");
baseDataValidator.reset().parameter("transactionDate").value(bulkRepaymentCommand.getTransactionDate()).notNull();
if (StringUtils.isNotBlank(bulkRepaymentCommand.getNote())) {
baseDataValidator.reset().parameter("note").value(bulkRepaymentCommand.getNote()).notExceedingLengthOf(1000);
}
final SingleRepaymentCommand[] loanRepayments = bulkRepaymentCommand.getLoanTransactions();
if (loanRepayments != null) {
for (int i = 0; i < loanRepayments.length; i++) {
SingleRepaymentCommand singleLoanRepaymentCommand = loanRepayments[i];
baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].loan.id")
.value(singleLoanRepaymentCommand.getLoanId()).notNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].transaction.amount")
.value(singleLoanRepaymentCommand.getTransactionAmount()).notNull().zeroOrPositiveAmount();
}
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -13,6 +13,11 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.localeParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.dateFormatParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.calendarIdParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.transactionDateParamName;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
@@ -32,7 +37,8 @@ public class CollectionSheetGenerateCommandFromApiJsonDeserializer {
/**
* The parameters supported for this command.
*/
final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("dueDate", "locale", "dateFormat"));
final Set<String> supportedParameters = new HashSet<String>(Arrays.asList(transactionDateParamName, localeParamName,
dateFormatParamName, calendarIdParamName));
private final FromJsonHelper fromApiJsonHelper;
@@ -53,15 +59,17 @@ public class CollectionSheetGenerateCommandFromApiJsonDeserializer {
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("collectionsheet");
final String dueDateParameterName = "dueDate";
final String dueDateStr = this.fromApiJsonHelper.extractStringNamed(dueDateParameterName, element);
baseDataValidator.reset().parameter(dueDateParameterName).value(dueDateStr).notBlank();
final String transactionDateStr = this.fromApiJsonHelper.extractStringNamed(transactionDateParamName, element);
baseDataValidator.reset().parameter(transactionDateParamName).value(transactionDateStr).notBlank();
if(!StringUtils.isBlank(dueDateStr)){
final LocalDate dueDate = this.fromApiJsonHelper.extractLocalDateNamed(dueDateParameterName, element);
baseDataValidator.reset().parameter(dueDateParameterName).value(dueDate).notNull();
if (!StringUtils.isBlank(transactionDateStr)) {
final LocalDate dueDate = this.fromApiJsonHelper.extractLocalDateNamed(transactionDateParamName, element);
baseDataValidator.reset().parameter(transactionDateParamName).value(dueDate).notNull();
}
final Long calendarId = this.fromApiJsonHelper.extractLongNamed(calendarIdParamName, element);
baseDataValidator.reset().parameter(calendarIdParamName).value(calendarId).notNull();
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
@@ -5,6 +5,9 @@
*/
package org.mifosplatform.portfolio.collectionsheet.service;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.calendarIdParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.transactionDateParamName;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -18,14 +21,20 @@ import java.util.Set;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.api.JsonQuery;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.portfolio.collectionsheet.data.ClientLoansData;
import org.mifosplatform.portfolio.collectionsheet.data.JLGClientsData;
import org.mifosplatform.portfolio.calendar.domain.Calendar;
import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType;
import org.mifosplatform.portfolio.calendar.domain.CalendarRepositoryWrapper;
import org.mifosplatform.portfolio.calendar.exception.NotValidRecurringDateException;
import org.mifosplatform.portfolio.calendar.service.CalendarUtils;
import org.mifosplatform.portfolio.collectionsheet.data.JLGClientData;
import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetData;
import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetFlatData;
import org.mifosplatform.portfolio.collectionsheet.data.JLGGroupData;
import org.mifosplatform.portfolio.collectionsheet.data.LoanDueData;
import org.mifosplatform.portfolio.collectionsheet.serialization.CollectionSheetGenerateCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.group.data.CenterData;
@@ -33,6 +42,8 @@ import org.mifosplatform.portfolio.group.data.GroupGeneralData;
import org.mifosplatform.portfolio.group.service.CenterReadPlatformService;
import org.mifosplatform.portfolio.group.service.GroupReadPlatformService;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.mifosplatform.portfolio.meeting.attendance.service.AttendanceDropdownReadPlatformService;
import org.mifosplatform.portfolio.meeting.attendance.service.AttendanceEnumerations;
import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
@@ -49,16 +60,22 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
private final CenterReadPlatformService centerReadPlatformService;
private final GroupReadPlatformService groupReadPlatformService;
private final CollectionSheetGenerateCommandFromApiJsonDeserializer collectionSheetGenerateCommandFromApiJsonDeserializer;
private final CalendarRepositoryWrapper calendarRepositoryWrapper;
private final AttendanceDropdownReadPlatformService attendanceDropdownReadPlatformService;
@Autowired
public CollectionSheetReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource,
final CenterReadPlatformService centerReadPlatformService, final GroupReadPlatformService groupReadPlatformService,
final CollectionSheetGenerateCommandFromApiJsonDeserializer collectionSheetGenerateCommandFromApiJsonDeserializer) {
final CollectionSheetGenerateCommandFromApiJsonDeserializer collectionSheetGenerateCommandFromApiJsonDeserializer,
final CalendarRepositoryWrapper calendarRepositoryWrapper,
final AttendanceDropdownReadPlatformService attendanceDropdownReadPlatformService) {
this.context = context;
this.centerReadPlatformService = centerReadPlatformService;
this.namedParameterjdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
this.collectionSheetGenerateCommandFromApiJsonDeserializer = collectionSheetGenerateCommandFromApiJsonDeserializer;
this.groupReadPlatformService = groupReadPlatformService;
this.calendarRepositoryWrapper = calendarRepositoryWrapper;
this.attendanceDropdownReadPlatformService = attendanceDropdownReadPlatformService;
}
@Override
@@ -92,9 +109,9 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
Long prevGroupId = null;
Long prevClientId = null;
final List<JLGClientsData> jlgClientsDatas = new ArrayList<JLGClientsData>();
List<ClientLoansData> clientLoansDatas = new ArrayList<ClientLoansData>();
List<LoanDueData> loanDueDatas = new ArrayList<LoanDueData>();
final List<JLGGroupData> jlgGroupsData = new ArrayList<JLGGroupData>();
List<JLGClientData> clientsData = new ArrayList<JLGClientData>();
List<LoanDueData> loansDueData = new ArrayList<LoanDueData>();
JLGCollectionSheetData jlgCollectionSheetData = null;
JLGCollectionSheetFlatData prevCollectioSheetFlatData = null;
@@ -113,35 +130,35 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
if (firstTime || collectionSheetFlatData.getGroupId().equals(prevGroupId)) {
if (firstTime || collectionSheetFlatData.getClientId().equals(prevClientId)) {
if (collectionSheetFlatData.getLoanId() != null) {
loanDueDatas.add(collectionSheetFlatData.getLoanDueData());
loansDueData.add(collectionSheetFlatData.getLoanDueData());
}
} else {
final ClientLoansData clientLoansData = prevCollectioSheetFlatData.getClientLoansData();
clientLoansData.setLoans(loanDueDatas);
clientLoansDatas.add(clientLoansData);
loanDueDatas = new ArrayList<LoanDueData>();
final JLGClientData clientData = prevCollectioSheetFlatData.getClientData();
clientData.setLoans(loansDueData);
clientsData.add(clientData);
loansDueData = new ArrayList<LoanDueData>();
if (collectionSheetFlatData.getLoanId() != null) {
loanDueDatas.add(collectionSheetFlatData.getLoanDueData());
loansDueData.add(collectionSheetFlatData.getLoanDueData());
}
}
} else {
final ClientLoansData clientLoansData = prevCollectioSheetFlatData.getClientLoansData();
clientLoansData.setLoans(loanDueDatas);
clientLoansDatas.add(clientLoansData);
final JLGClientData clientData = prevCollectioSheetFlatData.getClientData();
clientData.setLoans(loansDueData);
clientsData.add(clientData);
final JLGClientsData jlgClientsData = prevCollectioSheetFlatData.getJLGClientsData();
jlgClientsData.setClients(clientLoansDatas);
final JLGGroupData jlgGroupData = prevCollectioSheetFlatData.getJLGGroupData();
jlgGroupData.setClients(clientsData);
jlgClientsDatas.add(jlgClientsData);
jlgGroupsData.add(jlgGroupData);
loanDueDatas = new ArrayList<LoanDueData>();
clientLoansDatas = new ArrayList<ClientLoansData>();
loansDueData = new ArrayList<LoanDueData>();
clientsData = new ArrayList<JLGClientData>();
if (collectionSheetFlatData.getLoanId() != null) {
loanDueDatas.add(collectionSheetFlatData.getLoanDueData());
loansDueData.add(collectionSheetFlatData.getLoanDueData());
}
}
@@ -155,16 +172,17 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
// client/group or new client / previous group or new client / new
// group
if (corrCollectioSheetFlatData != null) {
final ClientLoansData lastClientLoansData = corrCollectioSheetFlatData.getClientLoansData();
lastClientLoansData.setLoans(loanDueDatas);
clientLoansDatas.add(lastClientLoansData);
final JLGClientData lastClientData = corrCollectioSheetFlatData.getClientData();
lastClientData.setLoans(loansDueData);
clientsData.add(lastClientData);
final JLGClientsData jlgClientsData = corrCollectioSheetFlatData.getJLGClientsData();
jlgClientsData.setClients(clientLoansDatas);
jlgClientsDatas.add(jlgClientsData);
final JLGGroupData jlgGroupData = corrCollectioSheetFlatData.getJLGGroupData();
jlgGroupData.setClients(clientsData);
jlgGroupsData.add(jlgGroupData);
}
jlgCollectionSheetData = new JLGCollectionSheetData(dueDate, loanProducts, jlgClientsDatas);
jlgCollectionSheetData = new JLGCollectionSheetData(dueDate, loanProducts, jlgGroupsData,
attendanceDropdownReadPlatformService.retrieveAttendanceTypeOptions());
}
return jlgCollectionSheetData;
@@ -206,7 +224,8 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
+ "ln.principal_repaid_derived As principalPaid, "
+ "sum(ifnull(if(ln.loan_status_id = 300, ls.interest_amount, 0.0), 0.0) - ifnull(if(ln.loan_status_id = 300, ls.interest_completed_derived, 0.0), 0.0)) As interestDue, "
+ "ln.interest_repaid_derived As interestPaid, "
+ "sum(if(ln.loan_status_id = 300, lc.amount_outstanding_derived, 0.0)) as chargesDue "
+ "sum(if(ln.loan_status_id = 300, lc.amount_outstanding_derived, 0.0)) as chargesDue, "
+ "ca.attendance_type_enum as attendanceTypeId "
+ "FROM m_group gp "
+ "LEFT JOIN m_office of ON of.id = gp.office_id AND of.hierarchy like :officeHierarchy "
// + "LEFT JOIN m_office of ON of.id = gp.office_id "
@@ -218,7 +237,10 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
+ "LEFT JOIN m_product_loan pl ON pl.id = ln.product_id "
+ "LEFT JOIN m_currency rc on rc.`code` = ln.currency_code "
+ "LEFT JOIN m_loan_repayment_schedule ls ON ls.loan_id = ln.id AND ls.completed_derived = 0 AND ls.duedate <= :dueDate "
+ "LEFT JOIN m_loan_charge lc ON lc.loan_id = ln.id AND lc.is_paid_derived = 0 AND ( lc.due_for_collection_as_of_date <= :dueDate OR lc.charge_time_enum = 1) ";
+ "LEFT JOIN m_loan_charge lc ON lc.loan_id = ln.id AND lc.is_paid_derived = 0 AND ( lc.due_for_collection_as_of_date <= :dueDate OR lc.charge_time_enum = 1) "
+ "left join m_calendar_instance ci on gp.parent_id = ci.entity_id and ci.entity_type_enum =:entityTypeId "
+ "left join m_meeting mt on ci.id = mt.calendar_instance_id and mt.meeting_date =:dueDate "
+ "left join m_client_attendance ca on ca.meeting_id=mt.id and ca.client_id=cl.id ";
// + "WHERE gp.hierarchy like :hierarchy " +
// "GROUP BY gp.id ,cl.id , ln.id " +
@@ -261,9 +283,12 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
final BigDecimal interestPaid = rs.getBigDecimal("interestPaid");
final BigDecimal chargesDue = rs.getBigDecimal("chargesDue");
final Integer attendanceTypeId = rs.getInt("attendanceTypeId");
final EnumOptionData attendanceType = AttendanceEnumerations.attendanceType(attendanceTypeId);
return new JLGCollectionSheetFlatData(groupName, groupId, staffId, staffName, levelId, levelName, clientName, clientId, loanId,
accountId, accountStatusId, productShortName, productId, currencyData, disbursementAmount, principalDue, principalPaid,
interestDue, interestPaid, chargesDue);
interestDue, interestPaid, chargesDue, attendanceType);
}
}
@@ -273,28 +298,34 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
this.collectionSheetGenerateCommandFromApiJsonDeserializer.validateForGenerateCollectionSheet(query.json());
final Long calendarId = query.longValueOfParameterNamed(calendarIdParamName);
final LocalDate transactionDate = query.localDateValueOfParameterNamed(transactionDateParamName);
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
final String transactionDateStr = df.format(transactionDate.toDate());
final Calendar calendar = this.calendarRepositoryWrapper.findOneWithNotFoundDetection(calendarId);
if (!CalendarUtils.isValidRedurringDate(calendar.getRecurrence(), calendar.getStartDateLocalDate(), transactionDate)) { throw new NotValidRecurringDateException(
"collectionsheet", "The date '" + transactionDate + "' is not a valid meeting date.", transactionDate); }
final AppUser currentUser = this.context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
final String officeHierarchy = hierarchy + "%";
final GroupGeneralData group = this.groupReadPlatformService.retrieveOne(groupId);
final LocalDate dueDate = query.localDateValueOfParameterNamed("dueDate");
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
final String dueDateStr = df.format(dueDate.toDate());
final JLGCollectionSheetFaltDataMapper mapper = new JLGCollectionSheetFaltDataMapper();
String sql = mapper.collectionSheetSchema();
sql += "WHERE gp.id = :groupId GROUP BY gp.id ,cl.id , ln.id ORDER BY gp.id , cl.id , ln.id";
StringBuilder sql = new StringBuilder(mapper.collectionSheetSchema());
sql.append(" WHERE gp.id = :groupId GROUP BY gp.id ,cl.id , ln.id ORDER BY gp.id , cl.id , ln.id ");
final SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("dueDate", dueDateStr)
.addValue("groupId", group.getId()).addValue("officeHierarchy", officeHierarchy);
final SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("dueDate", transactionDateStr)
.addValue("groupId", group.getId()).addValue("officeHierarchy", officeHierarchy)
.addValue("entityTypeId", CalendarEntityType.CENTERS.getValue());
final Collection<JLGCollectionSheetFlatData> collectionSheetFlatDatas = this.namedParameterjdbcTemplate.query(sql, namedParameters,
mapper);
final Collection<JLGCollectionSheetFlatData> collectionSheetFlatDatas = this.namedParameterjdbcTemplate.query(sql.toString(),
namedParameters, mapper);
return buildJLGCollectionSheet(dueDate, collectionSheetFlatDatas);
return buildJLGCollectionSheet(transactionDate, collectionSheetFlatDatas);
}
@Override
@@ -308,9 +339,9 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
final CenterData center = this.centerReadPlatformService.retrieveOne(centerId);
final LocalDate dueDate = query.localDateValueOfParameterNamed("dueDate");
final LocalDate transactionDate = query.localDateValueOfParameterNamed(transactionDateParamName);
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
final String dueDateStr = df.format(dueDate.toDate());
final String dueDateStr = df.format(transactionDate.toDate());
final JLGCollectionSheetFaltDataMapper mapper = new JLGCollectionSheetFaltDataMapper();
@@ -318,12 +349,13 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
sql += "WHERE gp.parent_id = :centerId GROUP BY gp.id ,cl.id , ln.id ORDER BY gp.id , cl.id , ln.id";
final SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("dueDate", dueDateStr)
.addValue("centerId", center.getId()).addValue("officeHierarchy", officeHierarchy);
.addValue("centerId", center.getId()).addValue("officeHierarchy", officeHierarchy)
.addValue("entityTypeId", CalendarEntityType.CENTERS.getValue());
final Collection<JLGCollectionSheetFlatData> collectionSheetFlatDatas = this.namedParameterjdbcTemplate.query(sql, namedParameters,
mapper);
return buildJLGCollectionSheet(dueDate, collectionSheetFlatDatas);
return buildJLGCollectionSheet(transactionDate, collectionSheetFlatDatas);
}
}
@@ -14,9 +14,11 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkDisbursalCommand;
import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkRepaymentCommand;
import org.mifosplatform.portfolio.collectionsheet.data.CollectionSheetTransactionDataValidator;
import org.mifosplatform.portfolio.collectionsheet.serialization.CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.collectionsheet.serialization.CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.loanaccount.service.LoanWritePlatformService;
import org.mifosplatform.portfolio.meeting.service.MeetingWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -25,21 +27,27 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
private final LoanWritePlatformService loanWritePlatformService;
private final CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer bulkRepaymentCommandFromApiJsonDeserializer;
private final CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer bulkDisbursalCommandFromApiJsonDeserializer;
private final CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer bulkDisbursalCommandFromApiJsonDeserializer;
private final CollectionSheetTransactionDataValidator transactionDataValidator;
private final MeetingWritePlatformService meetingWritePlatformService;
@Autowired
public CollectionSheetWritePlatformServiceJpaRepositoryImpl(LoanWritePlatformService loanWritePlatformService,
CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer bulkRepaymentCommandFromApiJsonDeserializer,
CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer bulkDisbursalCommandFromApiJsonDeserializer) {
CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer bulkDisbursalCommandFromApiJsonDeserializer,
final CollectionSheetTransactionDataValidator transactionDataValidator, final MeetingWritePlatformService meetingWritePlatformService) {
this.loanWritePlatformService = loanWritePlatformService;
this.bulkRepaymentCommandFromApiJsonDeserializer = bulkRepaymentCommandFromApiJsonDeserializer;
this.bulkDisbursalCommandFromApiJsonDeserializer = bulkDisbursalCommandFromApiJsonDeserializer;
this.transactionDataValidator = transactionDataValidator;
this.meetingWritePlatformService = meetingWritePlatformService;
}
@Override
public CommandProcessingResult updateCollectionSheet(JsonCommand command) {
this.transactionDataValidator.validateTransaction(command);
Map<String, Object> changes = new HashMap<String, Object>();
changes.put("locale", command.locale());
changes.put("dateFormat", command.dateFormat());
@@ -52,6 +60,8 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
changes.putAll(updateBulkReapayments(command));
changes.putAll(updateBulkDisbursals(command));
this.meetingWritePlatformService.updateCollectionSheetAttendance(command);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
@@ -64,7 +74,6 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
private Map<String, Object> updateBulkReapayments(JsonCommand command) {
Map<String, Object> changes = new HashMap<String, Object>();
final CollectionSheetBulkRepaymentCommand bulkRepaymentCommand = this.bulkRepaymentCommandFromApiJsonDeserializer.commandFromApiJson(command.json());
this.bulkRepaymentCommandFromApiJsonDeserializer.validateBulkRepaymentTransaction(bulkRepaymentCommand);
changes.putAll(this.loanWritePlatformService.makeLoanBulkRepayment(bulkRepaymentCommand));
return changes;
}
@@ -72,7 +81,6 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
private Map<String, Object> updateBulkDisbursals(JsonCommand command) {
Map<String, Object> changes = new HashMap<String, Object>();
final CollectionSheetBulkDisbursalCommand bulkDisbursalCommand = this.bulkDisbursalCommandFromApiJsonDeserializer.commandFromApiJson(command.json());
this.bulkDisbursalCommandFromApiJsonDeserializer.validateBulkDisbursalTransaction(bulkDisbursalCommand);
changes.putAll(this.loanWritePlatformService.bulkLoanDisbursal(command, bulkDisbursalCommand));
return changes;
}
@@ -150,6 +150,9 @@ public class CentersApiResource {
if (associationParameters.contains("collectionMeetingCalendar")) {
collectionMeetingCalendar = this.calendarReadPlatformService.retrieveCollctionCalendarByEntity(centerId, CalendarEntityType.CENTERS.getValue());
if(collectionMeetingCalendar != null){
collectionMeetingCalendar = this.calendarReadPlatformService.generateRecurringDate(collectionMeetingCalendar);
}
}
center = CenterData.withAssociations(center, groups, collectionMeetingCalendar);
@@ -203,7 +203,7 @@ public class GroupsApiResource {
groupRoles = null;
}
}
if (associationParameters.contains("calendars")) {
if (associationParameters.contains("parentCalendars")) {
final List<Integer> calendarTypeOptions = CalendarUtils.createIntegerListFromQueryParameter("all");
calendars = this.calendarReadPlatformService.retrieveParentCalendarsByEntity(groupId, CalendarEntityType.GROUPS.getValue(), calendarTypeOptions);
if (CollectionUtils.isEmpty(calendars)) {
@@ -211,7 +211,14 @@ public class GroupsApiResource {
}
}
if (associationParameters.contains("collectionMeetingCalendar")) {
collectionMeetingCalendar = this.calendarReadPlatformService.retrieveCollctionCalendarByEntity(groupId, CalendarEntityType.GROUPS.getValue());
if(group.isChildGroup()){
collectionMeetingCalendar = this.calendarReadPlatformService.retrieveCollctionCalendarByEntity(group.getParentId(), CalendarEntityType.CENTERS.getValue());
}else {
collectionMeetingCalendar = this.calendarReadPlatformService.retrieveCollctionCalendarByEntity(groupId, CalendarEntityType.GROUPS.getValue());
}
if(collectionMeetingCalendar != null){
collectionMeetingCalendar = this.calendarReadPlatformService.generateRecurringDate(collectionMeetingCalendar);
}
}
group = GroupGeneralData.withAssocations(group, membersOfGroup, groupRoles, calendars, collectionMeetingCalendar);
@@ -168,7 +168,16 @@ public class GroupGeneralData {
public String getHierarchy() {
return this.hierarchy;
}
public boolean isChildGroup(){
return this.centerId == null ? false : true;
}
public Long getParentId(){
return this.centerId;
}
public static GroupGeneralData updateSelectedRole(final GroupGeneralData grouping, final GroupRoleData selectedRole) {
return new GroupGeneralData(grouping.id, grouping.name, grouping.externalId, grouping.status, grouping.activationDate,
grouping.officeId, grouping.officeName, grouping.centerId, grouping.centerName, grouping.staffId, grouping.staffName,
@@ -67,16 +67,15 @@ public class Meeting extends AbstractPersistable<Long> {
}
public static Meeting createNew(final CalendarInstance calendarInstance, final Date meetingDate) {
if(!isValidMeetingDate(calendarInstance, meetingDate)){
throw new NotValidRecurringDateException("meeting", "The date '" + meetingDate + "' is not a valid meeting date.", meetingDate);
}
if (!isValidMeetingDate(calendarInstance, meetingDate)) { throw new NotValidRecurringDateException("meeting", "The date '"
+ meetingDate + "' is not a valid meeting date.", meetingDate); }
return new Meeting(calendarInstance, meetingDate);
}
public void associateClientsAttendance(final Collection<ClientAttendance> clientsAttendance) {
//do not allow to capture attendance in advance.
if(isMeetingDateAfter(DateUtils.getLocalDateOfTenant())){
// do not allow to capture attendance in advance.
if (isMeetingDateAfter(DateUtils.getLocalDateOfTenant())) {
final String errorMessage = "Attendance cannot be in the future.";
throw new MeetingDateException("cannot.be.a.future.date", errorMessage, getMeetingDateLocalDate());
}
@@ -95,11 +94,10 @@ public class Meeting extends AbstractPersistable<Long> {
actualChanges.put("dateFormat", dateFormatAsInput);
actualChanges.put("locale", localeAsInput);
this.meetingDate = newValue.toDate();
if(!isValidMeetingDate(this.calendarInstance, this.meetingDate)){
throw new NotValidRecurringDateException("meeting", "Not a valid meeting date", meetingDate);
}
if (!isValidMeetingDate(this.calendarInstance, this.meetingDate)) { throw new NotValidRecurringDateException("meeting",
"Not a valid meeting date", meetingDate); }
}
return actualChanges;
@@ -108,12 +106,15 @@ public class Meeting extends AbstractPersistable<Long> {
public Map<String, Object> updateAttendance(final Collection<ClientAttendance> clientsAttendance) {
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(1);
final Map<String, Object> clientAttendanceChanges = new LinkedHashMap<String, Object>(clientsAttendance.size());
updateAttendanceLoop: for (ClientAttendance clientAttendance : clientsAttendance) {
if (this.clientsAttendance == null) {
this.clientsAttendance = new HashSet<ClientAttendance>();
}
for (ClientAttendance clientAttendanceOriginal : this.clientsAttendance) {
if (clientAttendanceOriginal.clientId().equals(clientAttendance.clientId())) {
final Integer newValue = clientAttendance.getAttendanceTypeId();
if(!newValue.equals(clientAttendanceOriginal.getAttendanceTypeId())){
final Integer newValue = clientAttendance.getAttendanceTypeId();
if (!newValue.equals(clientAttendanceOriginal.getAttendanceTypeId())) {
clientAttendanceOriginal.updateAttendanceTypeId(newValue);
final Map<String, Object> clientAttendanceChange = new LinkedHashMap<String, Object>(2);
clientAttendanceChange.put(clientIdParamName, clientAttendanceOriginal.clientId());
@@ -123,32 +124,32 @@ public class Meeting extends AbstractPersistable<Long> {
continue updateAttendanceLoop;
}
}
final Map<String, Object> clientAttendanceChange = new LinkedHashMap<String, Object>();
clientAttendanceChange.put(clientIdParamName, clientAttendance.clientId());
clientAttendanceChange.put(attendanceTypeParamName, clientAttendance.getAttendanceTypeId());
clientAttendanceChanges.put(clientAttendance.clientId().toString(), clientAttendanceChange);
//New attendance record
// New attendance record
this.clientsAttendance.add(clientAttendance);
}
actualChanges.put(clientsAttendanceParamName, clientAttendanceChanges);
return actualChanges;
}
public Long entityId() {
return calendarInstance.getEntityId();
}
public boolean isCenterEntity(){
public boolean isCenterEntity() {
return CalendarEntityType.isCenter(calendarInstance.getEntityTypeId());
}
public boolean isGroupEntity(){
public boolean isGroupEntity() {
return CalendarEntityType.isGroup(calendarInstance.getEntityTypeId());
}
public LocalDate getMeetingDateLocalDate() {
LocalDate meetingDateLocalDate = null;
if (this.meetingDate != null) {
@@ -156,8 +157,8 @@ public class Meeting extends AbstractPersistable<Long> {
}
return meetingDateLocalDate;
}
public Date getMeetingDate(){
public Date getMeetingDate() {
return this.meetingDate;
}
@@ -165,24 +166,23 @@ public class Meeting extends AbstractPersistable<Long> {
return (this.meetingDate != null && newStartDate != null && getMeetingDateLocalDate().isBefore(newStartDate)) ? true : false;
}
private static boolean isValidMeetingDate(final CalendarInstance calendarInstance, final Date meetingDate ){
private static boolean isValidMeetingDate(final CalendarInstance calendarInstance, final Date meetingDate) {
final Calendar calendar = calendarInstance.getCalendar();
LocalDate meetingDateLocalDate = null;
LocalDate meetingDateLocalDate = null;
if (meetingDate != null) {
meetingDateLocalDate = LocalDate.fromDateFields(meetingDate);
}
if(meetingDateLocalDate == null || !CalendarUtils.isValidRedurringDate(calendar.getRecurrence(), calendar.getStartDateLocalDate(), meetingDateLocalDate)){
return false;
}
if (meetingDateLocalDate == null
|| !CalendarUtils.isValidRedurringDate(calendar.getRecurrence(), calendar.getStartDateLocalDate(), meetingDateLocalDate)) { return false; }
return true;
}
private boolean isMeetingDateAfter(final LocalDate date){
private boolean isMeetingDateAfter(final LocalDate date) {
return getMeetingDateLocalDate().isAfter(date);
}
public Collection<ClientAttendance> getClientsAttendance() {
return this.clientsAttendance;
}
}
@@ -5,9 +5,11 @@
*/
package org.mifosplatform.portfolio.meeting.domain;
import java.util.Date;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface MeetingRepository extends JpaRepository<Meeting, Long>, JpaSpecificationExecutor<Meeting> {
Meeting findByCalendarInstanceIdAndMeetingDate(Long calendarInstanceId, Date meetingDate);
}
@@ -11,6 +11,8 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
public interface MeetingWritePlatformService {
CommandProcessingResult createMeeting(JsonCommand command);
void updateCollectionSheetAttendance(JsonCommand command);
CommandProcessingResult updateMeeting(JsonCommand command);
@@ -10,12 +10,14 @@ import static org.mifosplatform.portfolio.meeting.MeetingApiConstants.calendarId
import static org.mifosplatform.portfolio.meeting.MeetingApiConstants.clientIdParamName;
import static org.mifosplatform.portfolio.meeting.MeetingApiConstants.clientsAttendanceParamName;
import static org.mifosplatform.portfolio.meeting.MeetingApiConstants.meetingDateParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.transactionDateParamName;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
@@ -36,6 +38,7 @@ import org.mifosplatform.portfolio.group.exception.ClientNotInGroupException;
import org.mifosplatform.portfolio.meeting.attendance.domain.ClientAttendance;
import org.mifosplatform.portfolio.meeting.data.MeetingDataValidator;
import org.mifosplatform.portfolio.meeting.domain.Meeting;
import org.mifosplatform.portfolio.meeting.domain.MeetingRepository;
import org.mifosplatform.portfolio.meeting.domain.MeetingRepositoryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
@@ -48,7 +51,8 @@ import com.google.gson.JsonObject;
@Service
public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWritePlatformService {
private final MeetingRepositoryWrapper meetingRepository;
private final MeetingRepositoryWrapper meetingRepositoryWrapper;
private final MeetingRepository meetingRepository;
private final MeetingDataValidator meetingDataValidator;
private final CalendarInstanceRepository calendarInstanceRepository;
private final CalendarRepository calendarRepository;
@@ -57,10 +61,11 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public MeetingWritePlatformServiceJpaRepositoryImpl(MeetingRepositoryWrapper meetingRepository,
MeetingDataValidator meetingDataValidator, CalendarInstanceRepository calendarInstanceRepository,
CalendarRepository calendarRepository, final ClientRepository clientRepository, final GroupRepository groupRepository,
final FromJsonHelper fromApiJsonHelper) {
public MeetingWritePlatformServiceJpaRepositoryImpl(final MeetingRepositoryWrapper meetingRepositoryWrapper,
final MeetingRepository meetingRepository, final MeetingDataValidator meetingDataValidator,
final CalendarInstanceRepository calendarInstanceRepository, final CalendarRepository calendarRepository,
final ClientRepository clientRepository, final GroupRepository groupRepository, final FromJsonHelper fromApiJsonHelper) {
this.meetingRepositoryWrapper = meetingRepositoryWrapper;
this.meetingRepository = meetingRepository;
this.meetingDataValidator = meetingDataValidator;
this.calendarInstanceRepository = calendarInstanceRepository;
@@ -71,7 +76,7 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit
}
@Override
public CommandProcessingResult createMeeting(JsonCommand command) {
public CommandProcessingResult createMeeting(final JsonCommand command) {
this.meetingDataValidator.validateForCreate(command);
@@ -87,13 +92,13 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit
newMeeting.associateClientsAttendance(clientsAttendance);
}
// save meeting details
this.meetingRepository.save(newMeeting);
this.meetingRepositoryWrapper.save(newMeeting);
final Long groupId = newMeeting.isGroupEntity() ? newMeeting.entityId() : null;
return new CommandProcessingResultBuilder() //
.withEntityId(newMeeting.getId()) //
.withGroupId(groupId).build();
} catch (DataIntegrityViolationException dve) {
} catch (final DataIntegrityViolationException dve) {
handleMeetingDataIntegrityIssues(meetingDate, dve);
return new CommandProcessingResultBuilder() //
.build();
@@ -107,11 +112,12 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit
if (calendarForUpdate == null) { throw new CalendarNotFoundException(calendarId); }
final Integer entityTypeId = CalendarEntityType.valueOf(command.getSupportedEntityType().toUpperCase()).getValue();
final CalendarInstance calendarInstance = calendarInstanceRepository.findByCalendarIdAndEntityIdAndEntityTypeId(
final CalendarInstance calendarInstance = this.calendarInstanceRepository.findByCalendarIdAndEntityIdAndEntityTypeId(
calendarForUpdate.getId(), entityId, entityTypeId);
if(calendarInstance == null) {
if (calendarInstance == null) {
final String postFix = "for." + command.getSupportedEntityType() + "not.found";
final String defaultUserMessage = "No Calendar Instance details found for group with identifier " + entityId + " and calendar with identifier " + calendarId;
final String defaultUserMessage = "No Calendar Instance details found for group with identifier " + entityId
+ " and calendar with identifier " + calendarId;
throw new CalendarInstanceNotFoundException(postFix, defaultUserMessage, entityId, calendarId);
}
return calendarInstance;
@@ -144,16 +150,17 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit
} else if (meeting.isCenterEntity()) {
if (childGroups != null && !childGroups.isEmpty()) {
boolean isChildClient = false;
for (Group group : childGroups) {
if (group.isChildClient(clientId)){
for (final Group group : childGroups) {
if (group.isChildClient(clientId)) {
isChildClient = true;
break;
}
}
if(!isChildClient){
if (!isChildClient) {
final String defaultUserMessage = "Client with identifier " + clientId + " is not in center "
+ meeting.entityId();
throw new ClientNotInGroupException("client.not.in.center", defaultUserMessage, clientId, meeting.entityId());
throw new ClientNotInGroupException("client.not.in.center", defaultUserMessage, clientId,
meeting.entityId());
}
}
}
@@ -167,17 +174,17 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit
}
@Override
public CommandProcessingResult updateMeeting(JsonCommand command) {
public CommandProcessingResult updateMeeting(final JsonCommand command) {
this.meetingDataValidator.validateForUpdate(command);
final Meeting meetingForUpdate = this.meetingRepository.findOneWithNotFoundDetection(command.entityId());
final Meeting meetingForUpdate = this.meetingRepositoryWrapper.findOneWithNotFoundDetection(command.entityId());
final Map<String, Object> changes = meetingForUpdate.update(command);
try {
if (!changes.isEmpty()) {
this.meetingRepository.saveAndFlush(meetingForUpdate);
this.meetingRepositoryWrapper.saveAndFlush(meetingForUpdate);
}
} catch (DataIntegrityViolationException dve) {
} catch (final DataIntegrityViolationException dve) {
handleMeetingDataIntegrityIssues(meetingForUpdate.getMeetingDate(), dve);
return new CommandProcessingResultBuilder() //
.build();
@@ -191,23 +198,23 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit
}
@Override
public CommandProcessingResult deleteMeeting(Long meetingId) {
final Meeting meetingForDelete = this.meetingRepository.findOneWithNotFoundDetection(meetingId);
this.meetingRepository.delete(meetingForDelete);
public CommandProcessingResult deleteMeeting(final Long meetingId) {
final Meeting meetingForDelete = this.meetingRepositoryWrapper.findOneWithNotFoundDetection(meetingId);
this.meetingRepositoryWrapper.delete(meetingForDelete);
return new CommandProcessingResultBuilder() //
.withEntityId(meetingId) //
.build();
}
@Override
public CommandProcessingResult saveOrUpdateAttendance(JsonCommand command) {
public CommandProcessingResult saveOrUpdateAttendance(final JsonCommand command) {
this.meetingDataValidator.validateForUpdateAttendance(command);
final Meeting meetingForUpdate = this.meetingRepository.findOneWithNotFoundDetection(command.entityId());
final Meeting meetingForUpdate = this.meetingRepositoryWrapper.findOneWithNotFoundDetection(command.entityId());
final Collection<ClientAttendance> clientsAttendance = getClientsAttendance(meetingForUpdate, command);
final Map<String, Object> changes = meetingForUpdate.updateAttendance(clientsAttendance);
this.meetingRepository.saveAndFlush(meetingForUpdate);
this.meetingRepositoryWrapper.saveAndFlush(meetingForUpdate);
final Long groupId = meetingForUpdate.isGroupEntity() ? meetingForUpdate.entityId() : null;
return new CommandProcessingResultBuilder() //
.withEntityId(meetingForUpdate.getId()) //
@@ -219,11 +226,35 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit
private void handleMeetingDataIntegrityIssues(final Date meetingDate, final DataIntegrityViolationException dve) {
final Throwable realCause = dve.getMostSpecificCause();
if (realCause.getMessage().contains("unique_calendar_instance_id_meeting_date")) {
throw new PlatformDataIntegrityException("error.msg.meeting.duplicate", "A meeting with date '" + meetingDate + "' already exists",
meetingDateParamName, meetingDate); }
final LocalDate meetingDateLocal = LocalDate.fromDateFields(meetingDate);
throw new PlatformDataIntegrityException("error.msg.meeting.duplicate", "A meeting with date '" + meetingDateLocal + "' already exists",
meetingDateParamName, meetingDateLocal); }
throw new PlatformDataIntegrityException("error.msg.meeting.unknown.data.integrity.issue",
"Unknown data integrity issue with resource: " + realCause.getMessage());
}
@Override
public void updateCollectionSheetAttendance(final JsonCommand command) {
final Date meetingDate = command.DateValueOfParameterNamed(transactionDateParamName);
try {
final CalendarInstance calendarInstance = getCalendarInstance(command);
final Meeting meeting = this.meetingRepository.findByCalendarInstanceIdAndMeetingDate(calendarInstance.getId(), meetingDate);
// create new meeting
final Meeting newMeeting = (meeting != null) ? meeting : Meeting.createNew(calendarInstance, meetingDate);
final Collection<ClientAttendance> clientsAttendance = getClientsAttendance(newMeeting, command);
if (clientsAttendance != null && !clientsAttendance.isEmpty()) {
newMeeting.updateAttendance(clientsAttendance);
}
// save meeting details
this.meetingRepositoryWrapper.save(newMeeting);
} catch (final DataIntegrityViolationException dve) {
handleMeetingDataIntegrityIssues(meetingDate, dve);
}
}
}