MIFOSX-607 - capture client atendance in collection sheet

This commit is contained in:
ashok-conflux
2013-08-28 12:50:34 +05:30
parent 1f7a93b7aa
commit 2c8db68a40
23 changed files with 547 additions and 239 deletions
@@ -6,6 +6,7 @@
package org.mifosplatform.commands.service; package org.mifosplatform.commands.service;
import org.mifosplatform.commands.domain.CommandWrapper; import org.mifosplatform.commands.domain.CommandWrapper;
import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType;
public class CommandWrapperBuilder { public class CommandWrapperBuilder {
@@ -1016,6 +1017,8 @@ public class CommandWrapperBuilder {
this.entityName = "GROUP"; this.entityName = "GROUP";
this.entityId = groupId; this.entityId = groupId;
this.groupId = groupId; this.groupId = groupId;
this.supportedEntityId = groupId;
this.supportedEntityType = CalendarEntityType.GROUPS.name();
this.href = "/groups/" + groupId + "?command=saveCollectionSheet"; this.href = "/groups/" + groupId + "?command=saveCollectionSheet";
return this; return this;
} }
@@ -1145,6 +1148,8 @@ public class CommandWrapperBuilder {
this.actionName = "SAVECOLLECTIONSHEET"; this.actionName = "SAVECOLLECTIONSHEET";
this.entityName = "CENTER"; this.entityName = "CENTER";
this.entityId = centerId; this.entityId = centerId;
this.supportedEntityId = centerId;
this.supportedEntityType = CalendarEntityType.CENTERS.name();
this.href = "/centers/" + centerId + "?command=saveCollectionSheet"; this.href = "/centers/" + centerId + "?command=saveCollectionSheet";
return this; return this;
} }
@@ -37,6 +37,7 @@ public class CalendarData {
private final Collection<LocalDate> recurringDates; private final Collection<LocalDate> recurringDates;
private final Collection<LocalDate> nextTenRecurringDates; private final Collection<LocalDate> nextTenRecurringDates;
private final String humanReadable; private final String humanReadable;
private final LocalDate recentEligibleMeetingDate;
private final LocalDate createdDate; private final LocalDate createdDate;
private final LocalDate lastUpdatedDate; 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, 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 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 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) { final Long createdByUserId, final String createdByUsername, final Long lastUpdatedByUserId, final String lastUpdatedByUsername) {
this.id = id; this.id = id;
@@ -77,6 +78,7 @@ public class CalendarData {
this.recurringDates = null; this.recurringDates = null;
this.nextTenRecurringDates = null; this.nextTenRecurringDates = null;
this.humanReadable = humanReadable; this.humanReadable = humanReadable;
this.recentEligibleMeetingDate = recentEligibleMeetingDate;
this.createdDate = createdDate; this.createdDate = createdDate;
this.lastUpdatedDate = lastUpdatedDate; this.lastUpdatedDate = lastUpdatedDate;
@@ -109,6 +111,7 @@ public class CalendarData {
this.recurringDates = calendarData.recurringDates; this.recurringDates = calendarData.recurringDates;
this.nextTenRecurringDates = calendarData.nextTenRecurringDates; this.nextTenRecurringDates = calendarData.nextTenRecurringDates;
this.humanReadable = calendarData.humanReadable; this.humanReadable = calendarData.humanReadable;
this.recentEligibleMeetingDate = calendarData.recentEligibleMeetingDate;
this.createdDate = calendarData.createdDate; this.createdDate = calendarData.createdDate;
this.lastUpdatedDate = calendarData.lastUpdatedDate; this.lastUpdatedDate = calendarData.lastUpdatedDate;
this.createdByUserId = calendarData.createdByUserId; this.createdByUserId = calendarData.createdByUserId;
@@ -117,7 +120,7 @@ public class CalendarData {
this.lastUpdatedByUsername = calendarData.lastUpdatedByUsername; 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.id = calendarData.id;
this.entityId = calendarData.entityId; this.entityId = calendarData.entityId;
this.entityType = calendarData.entityType; this.entityType = calendarData.entityType;
@@ -139,6 +142,7 @@ public class CalendarData {
this.recurringDates = recurringDates; this.recurringDates = recurringDates;
this.nextTenRecurringDates = nextTenRecurringDates; this.nextTenRecurringDates = nextTenRecurringDates;
this.humanReadable = calendarData.humanReadable; this.humanReadable = calendarData.humanReadable;
this.recentEligibleMeetingDate = recentEligibleMeetingDate;
this.createdDate = calendarData.createdDate; this.createdDate = calendarData.createdDate;
this.lastUpdatedDate = calendarData.lastUpdatedDate; this.lastUpdatedDate = calendarData.lastUpdatedDate;
this.createdByUserId = calendarData.createdByUserId; this.createdByUserId = calendarData.createdByUserId;
@@ -165,9 +169,18 @@ public class CalendarData {
final Integer firstReminder = new Integer(0); final Integer firstReminder = new Integer(0);
final Integer secondReminder = new Integer(0); final Integer secondReminder = new Integer(0);
final String humanReadable = null; 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, 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() { 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 String createdByUserName = rs.getString("creatingUserName");
final Long lastUpdatedByUserId = rs.getLong("updatingUserId"); final Long lastUpdatedByUserId = rs.getLong("updatingUserId");
final String lastUpdatedByUserName = rs.getString("updatingUserName"); final String lastUpdatedByUserName = rs.getString("updatingUserName");
final LocalDate recentEligibleMeetingDate = null;
return new CalendarData(id, entityId, entityType, title, description, location, startDate, endDate, duration, type, repeating, 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); 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> recurringDates = CalendarUtils.getRecurringDates(rrule, seedDate, startDate, endDate, -1);
final Collection<LocalDate> nextTenRecurringDates = CalendarUtils.getRecurringDates(rrule, seedDate, endDate); 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(); sqlCalendarTypeOptions += calendarTypeOptions.get(size - 1).toString();
return sqlCalendarTypeOptions; 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 java.util.Collection;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
/** /**
* Immutable data object for clients with loans due for disbursement or collection. * Immutable data object for clients with loans due for disbursement or collection.
*/ */
public class ClientLoansData { public class JLGClientData {
private final Long clientId; private final Long clientId;
private final String clientName; private final String clientName;
private Collection<LoanDueData> loans; 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.clientId = clientId;
this.clientName = clientName; this.clientName = clientName;
this.loans = loans; 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.clientId = clientId;
this.clientName = clientName; this.clientName = clientName;
this.loans = null; this.loans = null;
this.attendanceType = attendanceType;
} }
public Long getClientId() { public Long getClientId() {
@@ -6,8 +6,10 @@
package org.mifosplatform.portfolio.collectionsheet.data; package org.mifosplatform.portfolio.collectionsheet.data;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData; import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
/** /**
@@ -17,19 +19,23 @@ public class JLGCollectionSheetData {
private final LocalDate dueDate; private final LocalDate dueDate;
private final Collection<LoanProductData> loanProducts; 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.dueDate = date;
this.loanProducts = loanProducts; this.loanProducts = loanProducts;
this.groups = groups; this.groups = groups;
this.attendanceTypeOptions = attendanceTypeOptions;
} }
public LocalDate getDate() { public LocalDate getDate() {
return this.dueDate; return this.dueDate;
} }
public Collection<JLGClientsData> getGroups() { public Collection<JLGGroupData> getGroups() {
return this.groups; return this.groups;
} }
@@ -7,6 +7,7 @@ package org.mifosplatform.portfolio.collectionsheet.data;
import java.math.BigDecimal; import java.math.BigDecimal;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.organisation.monetary.data.CurrencyData; import org.mifosplatform.organisation.monetary.data.CurrencyData;
/** /**
@@ -34,12 +35,13 @@ public class JLGCollectionSheetFlatData {
private BigDecimal interestDue = BigDecimal.ZERO; private BigDecimal interestDue = BigDecimal.ZERO;
private BigDecimal interestPaid = BigDecimal.ZERO; private BigDecimal interestPaid = BigDecimal.ZERO;
private BigDecimal chargesDue = 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, 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 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 String accountId, final Integer accountStatusId, final String productShortName, final Long productId,
final CurrencyData currency, final BigDecimal disbursementAmount, final BigDecimal principalDue, 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.groupName = groupName;
this.groupId = groupId; this.groupId = groupId;
this.staffId = staffId; this.staffId = staffId;
@@ -60,6 +62,7 @@ public class JLGCollectionSheetFlatData {
this.interestDue = interestDue; this.interestDue = interestDue;
this.interestPaid = interestPaid; this.interestPaid = interestPaid;
this.chargesDue = chargesDue; this.chargesDue = chargesDue;
this.attendanceType = attendanceType;
} }
public String getGroupName() { public String getGroupName() {
@@ -147,13 +150,13 @@ public class JLGCollectionSheetFlatData {
this.disbursementAmount, this.principalDue, this.principalPaid, this.interestDue, this.interestPaid, this.chargesDue); this.disbursementAmount, this.principalDue, this.principalPaid, this.interestDue, this.interestPaid, this.chargesDue);
} }
public ClientLoansData getClientLoansData() { public JLGClientData getClientData() {
return new ClientLoansData(this.clientId, this.clientName); 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. * Immutable data object for groups with clients due for disbursement or collection.
*/ */
public class JLGClientsData { public class JLGGroupData {
private final Long groupId; private final Long groupId;
private final String groupName; private final String groupName;
@@ -18,9 +18,9 @@ public class JLGClientsData {
private final String staffName; private final String staffName;
private final Long levelId; private final Long levelId;
private final String levelName; 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) { final String levelName) {
this.groupId = groupId; this.groupId = groupId;
this.groupName = groupName; this.groupName = groupName;
@@ -54,11 +54,11 @@ public class JLGClientsData {
return this.levelName; return this.levelName;
} }
public Collection<ClientLoansData> getCutomers() { public Collection<JLGClientData> getClients() {
return this.clients; return this.clients;
} }
public void setClients(final Collection<ClientLoansData> clients) { public void setClients(final Collection<JLGClientData> clients) {
this.clients = clients; this.clients = clients;
} }
} }
@@ -5,22 +5,12 @@
*/ */
package org.mifosplatform.portfolio.collectionsheet.serialization; package org.mifosplatform.portfolio.collectionsheet.serialization;
import java.lang.reflect.Type;
import java.math.BigDecimal; 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.Locale;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate; 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.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer; import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer; import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; 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.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
/** /**
* Implementation of {@link FromApiJsonDeserializer} for * Implementation of {@link FromApiJsonDeserializer} for
@@ -52,21 +41,12 @@ public final class CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer ex
public CollectionSheetBulkDisbursalCommand commandFromApiJson(final String json) { public CollectionSheetBulkDisbursalCommand commandFromApiJson(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } 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 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 JsonObject topLevelJsonElement = element.getAsJsonObject();
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement); final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
final LocalDate transactionDate = fromApiJsonHelper.extractLocalDateNamed("transactionDate", element);
final String note = fromApiJsonHelper.extractStringNamed("note", element);
SingleDisbursalCommand[] loanDisbursementTransactions = null; SingleDisbursalCommand[] loanDisbursementTransactions = null;
@@ -86,33 +66,4 @@ public final class CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer ex
} }
return new CollectionSheetBulkDisbursalCommand(note, transactionDate, loanDisbursementTransactions); 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; package org.mifosplatform.portfolio.collectionsheet.serialization;
import java.lang.reflect.Type;
import java.math.BigDecimal; 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.Locale;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate; 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.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer; import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer; import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; 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.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
/** /**
* Implementation of {@link FromApiJsonDeserializer} for * Implementation of {@link FromApiJsonDeserializer} for
@@ -52,11 +41,6 @@ public final class CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer ex
public CollectionSheetBulkRepaymentCommand commandFromApiJson(final String json) { public CollectionSheetBulkRepaymentCommand commandFromApiJson(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } 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 JsonElement element = this.fromApiJsonHelper.parse(json);
final LocalDate transactionDate = fromApiJsonHelper.extractLocalDateNamed("transactionDate", element); final LocalDate transactionDate = fromApiJsonHelper.extractLocalDateNamed("transactionDate", element);
@@ -84,33 +68,5 @@ public final class CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer ex
} }
return new CollectionSheetBulkRepaymentCommand(note, transactionDate, loanRepaymentTransactions); 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.Map;
import java.util.Set; 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.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.ApiParameterError; import org.mifosplatform.infrastructure.core.data.ApiParameterError;
@@ -32,7 +37,8 @@ public class CollectionSheetGenerateCommandFromApiJsonDeserializer {
/** /**
* The parameters supported for this command. * 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; private final FromJsonHelper fromApiJsonHelper;
@@ -53,15 +59,17 @@ public class CollectionSheetGenerateCommandFromApiJsonDeserializer {
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("collectionsheet"); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("collectionsheet");
final String dueDateParameterName = "dueDate"; final String transactionDateStr = this.fromApiJsonHelper.extractStringNamed(transactionDateParamName, element);
final String dueDateStr = this.fromApiJsonHelper.extractStringNamed(dueDateParameterName, element); baseDataValidator.reset().parameter(transactionDateParamName).value(transactionDateStr).notBlank();
baseDataValidator.reset().parameter(dueDateParameterName).value(dueDateStr).notBlank();
if(!StringUtils.isBlank(dueDateStr)){ if (!StringUtils.isBlank(transactionDateStr)) {
final LocalDate dueDate = this.fromApiJsonHelper.extractLocalDateNamed(dueDateParameterName, element); final LocalDate dueDate = this.fromApiJsonHelper.extractLocalDateNamed(transactionDateParamName, element);
baseDataValidator.reset().parameter(dueDateParameterName).value(dueDate).notNull(); 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", if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); } "Validation errors exist.", dataValidationErrors); }
} }
@@ -5,6 +5,9 @@
*/ */
package org.mifosplatform.portfolio.collectionsheet.service; 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.math.BigDecimal;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@@ -18,14 +21,20 @@ import java.util.Set;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.api.JsonQuery; 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.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource; import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.monetary.data.CurrencyData; import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.portfolio.collectionsheet.data.ClientLoansData; import org.mifosplatform.portfolio.calendar.domain.Calendar;
import org.mifosplatform.portfolio.collectionsheet.data.JLGClientsData; 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.JLGCollectionSheetData;
import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetFlatData; 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.data.LoanDueData;
import org.mifosplatform.portfolio.collectionsheet.serialization.CollectionSheetGenerateCommandFromApiJsonDeserializer; import org.mifosplatform.portfolio.collectionsheet.serialization.CollectionSheetGenerateCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.group.data.CenterData; 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.CenterReadPlatformService;
import org.mifosplatform.portfolio.group.service.GroupReadPlatformService; import org.mifosplatform.portfolio.group.service.GroupReadPlatformService;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData; 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.mifosplatform.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.RowMapper;
@@ -49,16 +60,22 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
private final CenterReadPlatformService centerReadPlatformService; private final CenterReadPlatformService centerReadPlatformService;
private final GroupReadPlatformService groupReadPlatformService; private final GroupReadPlatformService groupReadPlatformService;
private final CollectionSheetGenerateCommandFromApiJsonDeserializer collectionSheetGenerateCommandFromApiJsonDeserializer; private final CollectionSheetGenerateCommandFromApiJsonDeserializer collectionSheetGenerateCommandFromApiJsonDeserializer;
private final CalendarRepositoryWrapper calendarRepositoryWrapper;
private final AttendanceDropdownReadPlatformService attendanceDropdownReadPlatformService;
@Autowired @Autowired
public CollectionSheetReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource, public CollectionSheetReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource,
final CenterReadPlatformService centerReadPlatformService, final GroupReadPlatformService groupReadPlatformService, final CenterReadPlatformService centerReadPlatformService, final GroupReadPlatformService groupReadPlatformService,
final CollectionSheetGenerateCommandFromApiJsonDeserializer collectionSheetGenerateCommandFromApiJsonDeserializer) { final CollectionSheetGenerateCommandFromApiJsonDeserializer collectionSheetGenerateCommandFromApiJsonDeserializer,
final CalendarRepositoryWrapper calendarRepositoryWrapper,
final AttendanceDropdownReadPlatformService attendanceDropdownReadPlatformService) {
this.context = context; this.context = context;
this.centerReadPlatformService = centerReadPlatformService; this.centerReadPlatformService = centerReadPlatformService;
this.namedParameterjdbcTemplate = new NamedParameterJdbcTemplate(dataSource); this.namedParameterjdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
this.collectionSheetGenerateCommandFromApiJsonDeserializer = collectionSheetGenerateCommandFromApiJsonDeserializer; this.collectionSheetGenerateCommandFromApiJsonDeserializer = collectionSheetGenerateCommandFromApiJsonDeserializer;
this.groupReadPlatformService = groupReadPlatformService; this.groupReadPlatformService = groupReadPlatformService;
this.calendarRepositoryWrapper = calendarRepositoryWrapper;
this.attendanceDropdownReadPlatformService = attendanceDropdownReadPlatformService;
} }
@Override @Override
@@ -92,9 +109,9 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
Long prevGroupId = null; Long prevGroupId = null;
Long prevClientId = null; Long prevClientId = null;
final List<JLGClientsData> jlgClientsDatas = new ArrayList<JLGClientsData>(); final List<JLGGroupData> jlgGroupsData = new ArrayList<JLGGroupData>();
List<ClientLoansData> clientLoansDatas = new ArrayList<ClientLoansData>(); List<JLGClientData> clientsData = new ArrayList<JLGClientData>();
List<LoanDueData> loanDueDatas = new ArrayList<LoanDueData>(); List<LoanDueData> loansDueData = new ArrayList<LoanDueData>();
JLGCollectionSheetData jlgCollectionSheetData = null; JLGCollectionSheetData jlgCollectionSheetData = null;
JLGCollectionSheetFlatData prevCollectioSheetFlatData = null; JLGCollectionSheetFlatData prevCollectioSheetFlatData = null;
@@ -113,35 +130,35 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
if (firstTime || collectionSheetFlatData.getGroupId().equals(prevGroupId)) { if (firstTime || collectionSheetFlatData.getGroupId().equals(prevGroupId)) {
if (firstTime || collectionSheetFlatData.getClientId().equals(prevClientId)) { if (firstTime || collectionSheetFlatData.getClientId().equals(prevClientId)) {
if (collectionSheetFlatData.getLoanId() != null) { if (collectionSheetFlatData.getLoanId() != null) {
loanDueDatas.add(collectionSheetFlatData.getLoanDueData()); loansDueData.add(collectionSheetFlatData.getLoanDueData());
} }
} else { } else {
final ClientLoansData clientLoansData = prevCollectioSheetFlatData.getClientLoansData(); final JLGClientData clientData = prevCollectioSheetFlatData.getClientData();
clientLoansData.setLoans(loanDueDatas); clientData.setLoans(loansDueData);
clientLoansDatas.add(clientLoansData); clientsData.add(clientData);
loanDueDatas = new ArrayList<LoanDueData>(); loansDueData = new ArrayList<LoanDueData>();
if (collectionSheetFlatData.getLoanId() != null) { if (collectionSheetFlatData.getLoanId() != null) {
loanDueDatas.add(collectionSheetFlatData.getLoanDueData()); loansDueData.add(collectionSheetFlatData.getLoanDueData());
} }
} }
} else { } else {
final ClientLoansData clientLoansData = prevCollectioSheetFlatData.getClientLoansData(); final JLGClientData clientData = prevCollectioSheetFlatData.getClientData();
clientLoansData.setLoans(loanDueDatas); clientData.setLoans(loansDueData);
clientLoansDatas.add(clientLoansData); clientsData.add(clientData);
final JLGClientsData jlgClientsData = prevCollectioSheetFlatData.getJLGClientsData(); final JLGGroupData jlgGroupData = prevCollectioSheetFlatData.getJLGGroupData();
jlgClientsData.setClients(clientLoansDatas); jlgGroupData.setClients(clientsData);
jlgClientsDatas.add(jlgClientsData); jlgGroupsData.add(jlgGroupData);
loanDueDatas = new ArrayList<LoanDueData>(); loansDueData = new ArrayList<LoanDueData>();
clientLoansDatas = new ArrayList<ClientLoansData>(); clientsData = new ArrayList<JLGClientData>();
if (collectionSheetFlatData.getLoanId() != null) { 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 // client/group or new client / previous group or new client / new
// group // group
if (corrCollectioSheetFlatData != null) { if (corrCollectioSheetFlatData != null) {
final ClientLoansData lastClientLoansData = corrCollectioSheetFlatData.getClientLoansData(); final JLGClientData lastClientData = corrCollectioSheetFlatData.getClientData();
lastClientLoansData.setLoans(loanDueDatas); lastClientData.setLoans(loansDueData);
clientLoansDatas.add(lastClientLoansData); clientsData.add(lastClientData);
final JLGClientsData jlgClientsData = corrCollectioSheetFlatData.getJLGClientsData(); final JLGGroupData jlgGroupData = corrCollectioSheetFlatData.getJLGGroupData();
jlgClientsData.setClients(clientLoansDatas); jlgGroupData.setClients(clientsData);
jlgClientsDatas.add(jlgClientsData); jlgGroupsData.add(jlgGroupData);
} }
jlgCollectionSheetData = new JLGCollectionSheetData(dueDate, loanProducts, jlgClientsDatas); jlgCollectionSheetData = new JLGCollectionSheetData(dueDate, loanProducts, jlgGroupsData,
attendanceDropdownReadPlatformService.retrieveAttendanceTypeOptions());
} }
return jlgCollectionSheetData; return jlgCollectionSheetData;
@@ -206,7 +224,8 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
+ "ln.principal_repaid_derived As principalPaid, " + "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, " + "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, " + "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 " + "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 AND of.hierarchy like :officeHierarchy "
// + "LEFT JOIN m_office of ON of.id = gp.office_id " // + "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_product_loan pl ON pl.id = ln.product_id "
+ "LEFT JOIN m_currency rc on rc.`code` = ln.currency_code " + "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_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 " + // + "WHERE gp.hierarchy like :hierarchy " +
// "GROUP BY gp.id ,cl.id , ln.id " + // "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 interestPaid = rs.getBigDecimal("interestPaid");
final BigDecimal chargesDue = rs.getBigDecimal("chargesDue"); 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, return new JLGCollectionSheetFlatData(groupName, groupId, staffId, staffName, levelId, levelName, clientName, clientId, loanId,
accountId, accountStatusId, productShortName, productId, currencyData, disbursementAmount, principalDue, principalPaid, 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()); 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 AppUser currentUser = this.context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy(); final String hierarchy = currentUser.getOffice().getHierarchy();
final String officeHierarchy = hierarchy + "%"; final String officeHierarchy = hierarchy + "%";
final GroupGeneralData group = this.groupReadPlatformService.retrieveOne(groupId); 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(); final JLGCollectionSheetFaltDataMapper mapper = new JLGCollectionSheetFaltDataMapper();
String sql = mapper.collectionSheetSchema(); StringBuilder sql = new StringBuilder(mapper.collectionSheetSchema());
sql += "WHERE gp.id = :groupId GROUP BY gp.id ,cl.id , ln.id ORDER BY gp.id , cl.id , ln.id"; 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) final SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("dueDate", transactionDateStr)
.addValue("groupId", group.getId()).addValue("officeHierarchy", officeHierarchy); .addValue("groupId", group.getId()).addValue("officeHierarchy", officeHierarchy)
.addValue("entityTypeId", CalendarEntityType.CENTERS.getValue());
final Collection<JLGCollectionSheetFlatData> collectionSheetFlatDatas = this.namedParameterjdbcTemplate.query(sql, namedParameters, final Collection<JLGCollectionSheetFlatData> collectionSheetFlatDatas = this.namedParameterjdbcTemplate.query(sql.toString(),
mapper); namedParameters, mapper);
return buildJLGCollectionSheet(dueDate, collectionSheetFlatDatas); return buildJLGCollectionSheet(transactionDate, collectionSheetFlatDatas);
} }
@Override @Override
@@ -308,9 +339,9 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
final CenterData center = this.centerReadPlatformService.retrieveOne(centerId); 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 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(); 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"; 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) 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, final Collection<JLGCollectionSheetFlatData> collectionSheetFlatDatas = this.namedParameterjdbcTemplate.query(sql, namedParameters,
mapper); 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.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkDisbursalCommand; import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkDisbursalCommand;
import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkRepaymentCommand; 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.CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.collectionsheet.serialization.CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer; import org.mifosplatform.portfolio.collectionsheet.serialization.CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.loanaccount.service.LoanWritePlatformService; import org.mifosplatform.portfolio.loanaccount.service.LoanWritePlatformService;
import org.mifosplatform.portfolio.meeting.service.MeetingWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -25,21 +27,27 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
private final LoanWritePlatformService loanWritePlatformService; private final LoanWritePlatformService loanWritePlatformService;
private final CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer bulkRepaymentCommandFromApiJsonDeserializer; private final CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer bulkRepaymentCommandFromApiJsonDeserializer;
private final CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer bulkDisbursalCommandFromApiJsonDeserializer; private final CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer bulkDisbursalCommandFromApiJsonDeserializer;
private final CollectionSheetTransactionDataValidator transactionDataValidator;
private final MeetingWritePlatformService meetingWritePlatformService;
@Autowired @Autowired
public CollectionSheetWritePlatformServiceJpaRepositoryImpl(LoanWritePlatformService loanWritePlatformService, public CollectionSheetWritePlatformServiceJpaRepositoryImpl(LoanWritePlatformService loanWritePlatformService,
CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer bulkRepaymentCommandFromApiJsonDeserializer, CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer bulkRepaymentCommandFromApiJsonDeserializer,
CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer bulkDisbursalCommandFromApiJsonDeserializer) { CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer bulkDisbursalCommandFromApiJsonDeserializer,
final CollectionSheetTransactionDataValidator transactionDataValidator, final MeetingWritePlatformService meetingWritePlatformService) {
this.loanWritePlatformService = loanWritePlatformService; this.loanWritePlatformService = loanWritePlatformService;
this.bulkRepaymentCommandFromApiJsonDeserializer = bulkRepaymentCommandFromApiJsonDeserializer; this.bulkRepaymentCommandFromApiJsonDeserializer = bulkRepaymentCommandFromApiJsonDeserializer;
this.bulkDisbursalCommandFromApiJsonDeserializer = bulkDisbursalCommandFromApiJsonDeserializer; this.bulkDisbursalCommandFromApiJsonDeserializer = bulkDisbursalCommandFromApiJsonDeserializer;
this.transactionDataValidator = transactionDataValidator;
this.meetingWritePlatformService = meetingWritePlatformService;
} }
@Override @Override
public CommandProcessingResult updateCollectionSheet(JsonCommand command) { public CommandProcessingResult updateCollectionSheet(JsonCommand command) {
this.transactionDataValidator.validateTransaction(command);
Map<String, Object> changes = new HashMap<String, Object>(); Map<String, Object> changes = new HashMap<String, Object>();
changes.put("locale", command.locale()); changes.put("locale", command.locale());
changes.put("dateFormat", command.dateFormat()); changes.put("dateFormat", command.dateFormat());
@@ -52,6 +60,8 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
changes.putAll(updateBulkReapayments(command)); changes.putAll(updateBulkReapayments(command));
changes.putAll(updateBulkDisbursals(command)); changes.putAll(updateBulkDisbursals(command));
this.meetingWritePlatformService.updateCollectionSheetAttendance(command);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -64,7 +74,6 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
private Map<String, Object> updateBulkReapayments(JsonCommand command) { private Map<String, Object> updateBulkReapayments(JsonCommand command) {
Map<String, Object> changes = new HashMap<String, Object>(); Map<String, Object> changes = new HashMap<String, Object>();
final CollectionSheetBulkRepaymentCommand bulkRepaymentCommand = this.bulkRepaymentCommandFromApiJsonDeserializer.commandFromApiJson(command.json()); final CollectionSheetBulkRepaymentCommand bulkRepaymentCommand = this.bulkRepaymentCommandFromApiJsonDeserializer.commandFromApiJson(command.json());
this.bulkRepaymentCommandFromApiJsonDeserializer.validateBulkRepaymentTransaction(bulkRepaymentCommand);
changes.putAll(this.loanWritePlatformService.makeLoanBulkRepayment(bulkRepaymentCommand)); changes.putAll(this.loanWritePlatformService.makeLoanBulkRepayment(bulkRepaymentCommand));
return changes; return changes;
} }
@@ -72,7 +81,6 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
private Map<String, Object> updateBulkDisbursals(JsonCommand command) { private Map<String, Object> updateBulkDisbursals(JsonCommand command) {
Map<String, Object> changes = new HashMap<String, Object>(); Map<String, Object> changes = new HashMap<String, Object>();
final CollectionSheetBulkDisbursalCommand bulkDisbursalCommand = this.bulkDisbursalCommandFromApiJsonDeserializer.commandFromApiJson(command.json()); final CollectionSheetBulkDisbursalCommand bulkDisbursalCommand = this.bulkDisbursalCommandFromApiJsonDeserializer.commandFromApiJson(command.json());
this.bulkDisbursalCommandFromApiJsonDeserializer.validateBulkDisbursalTransaction(bulkDisbursalCommand);
changes.putAll(this.loanWritePlatformService.bulkLoanDisbursal(command, bulkDisbursalCommand)); changes.putAll(this.loanWritePlatformService.bulkLoanDisbursal(command, bulkDisbursalCommand));
return changes; return changes;
} }
@@ -150,6 +150,9 @@ public class CentersApiResource {
if (associationParameters.contains("collectionMeetingCalendar")) { if (associationParameters.contains("collectionMeetingCalendar")) {
collectionMeetingCalendar = this.calendarReadPlatformService.retrieveCollctionCalendarByEntity(centerId, CalendarEntityType.CENTERS.getValue()); collectionMeetingCalendar = this.calendarReadPlatformService.retrieveCollctionCalendarByEntity(centerId, CalendarEntityType.CENTERS.getValue());
if(collectionMeetingCalendar != null){
collectionMeetingCalendar = this.calendarReadPlatformService.generateRecurringDate(collectionMeetingCalendar);
}
} }
center = CenterData.withAssociations(center, groups, collectionMeetingCalendar); center = CenterData.withAssociations(center, groups, collectionMeetingCalendar);
@@ -203,7 +203,7 @@ public class GroupsApiResource {
groupRoles = null; groupRoles = null;
} }
} }
if (associationParameters.contains("calendars")) { if (associationParameters.contains("parentCalendars")) {
final List<Integer> calendarTypeOptions = CalendarUtils.createIntegerListFromQueryParameter("all"); final List<Integer> calendarTypeOptions = CalendarUtils.createIntegerListFromQueryParameter("all");
calendars = this.calendarReadPlatformService.retrieveParentCalendarsByEntity(groupId, CalendarEntityType.GROUPS.getValue(), calendarTypeOptions); calendars = this.calendarReadPlatformService.retrieveParentCalendarsByEntity(groupId, CalendarEntityType.GROUPS.getValue(), calendarTypeOptions);
if (CollectionUtils.isEmpty(calendars)) { if (CollectionUtils.isEmpty(calendars)) {
@@ -211,7 +211,14 @@ public class GroupsApiResource {
} }
} }
if (associationParameters.contains("collectionMeetingCalendar")) { 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); group = GroupGeneralData.withAssocations(group, membersOfGroup, groupRoles, calendars, collectionMeetingCalendar);
@@ -168,7 +168,16 @@ public class GroupGeneralData {
public String getHierarchy() { public String getHierarchy() {
return this.hierarchy; 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) { public static GroupGeneralData updateSelectedRole(final GroupGeneralData grouping, final GroupRoleData selectedRole) {
return new GroupGeneralData(grouping.id, grouping.name, grouping.externalId, grouping.status, grouping.activationDate, 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, 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) { public static Meeting createNew(final CalendarInstance calendarInstance, final Date meetingDate) {
if(!isValidMeetingDate(calendarInstance, meetingDate)){ if (!isValidMeetingDate(calendarInstance, meetingDate)) { throw new NotValidRecurringDateException("meeting", "The date '"
throw new NotValidRecurringDateException("meeting", "The date '" + meetingDate + "' is not a valid meeting date.", meetingDate); + meetingDate + "' is not a valid meeting date.", meetingDate); }
}
return new Meeting(calendarInstance, meetingDate); return new Meeting(calendarInstance, meetingDate);
} }
public void associateClientsAttendance(final Collection<ClientAttendance> clientsAttendance) { public void associateClientsAttendance(final Collection<ClientAttendance> clientsAttendance) {
//do not allow to capture attendance in advance. // do not allow to capture attendance in advance.
if(isMeetingDateAfter(DateUtils.getLocalDateOfTenant())){ if (isMeetingDateAfter(DateUtils.getLocalDateOfTenant())) {
final String errorMessage = "Attendance cannot be in the future."; final String errorMessage = "Attendance cannot be in the future.";
throw new MeetingDateException("cannot.be.a.future.date", errorMessage, getMeetingDateLocalDate()); 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("dateFormat", dateFormatAsInput);
actualChanges.put("locale", localeAsInput); actualChanges.put("locale", localeAsInput);
this.meetingDate = newValue.toDate(); this.meetingDate = newValue.toDate();
if(!isValidMeetingDate(this.calendarInstance, this.meetingDate)){ if (!isValidMeetingDate(this.calendarInstance, this.meetingDate)) { throw new NotValidRecurringDateException("meeting",
throw new NotValidRecurringDateException("meeting", "Not a valid meeting date", meetingDate); "Not a valid meeting date", meetingDate); }
}
} }
return actualChanges; return actualChanges;
@@ -108,12 +106,15 @@ public class Meeting extends AbstractPersistable<Long> {
public Map<String, Object> updateAttendance(final Collection<ClientAttendance> clientsAttendance) { public Map<String, Object> updateAttendance(final Collection<ClientAttendance> clientsAttendance) {
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(1); final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(1);
final Map<String, Object> clientAttendanceChanges = new LinkedHashMap<String, Object>(clientsAttendance.size()); final Map<String, Object> clientAttendanceChanges = new LinkedHashMap<String, Object>(clientsAttendance.size());
updateAttendanceLoop: for (ClientAttendance clientAttendance : clientsAttendance) { updateAttendanceLoop: for (ClientAttendance clientAttendance : clientsAttendance) {
if (this.clientsAttendance == null) {
this.clientsAttendance = new HashSet<ClientAttendance>();
}
for (ClientAttendance clientAttendanceOriginal : this.clientsAttendance) { for (ClientAttendance clientAttendanceOriginal : this.clientsAttendance) {
if (clientAttendanceOriginal.clientId().equals(clientAttendance.clientId())) { if (clientAttendanceOriginal.clientId().equals(clientAttendance.clientId())) {
final Integer newValue = clientAttendance.getAttendanceTypeId(); final Integer newValue = clientAttendance.getAttendanceTypeId();
if(!newValue.equals(clientAttendanceOriginal.getAttendanceTypeId())){ if (!newValue.equals(clientAttendanceOriginal.getAttendanceTypeId())) {
clientAttendanceOriginal.updateAttendanceTypeId(newValue); clientAttendanceOriginal.updateAttendanceTypeId(newValue);
final Map<String, Object> clientAttendanceChange = new LinkedHashMap<String, Object>(2); final Map<String, Object> clientAttendanceChange = new LinkedHashMap<String, Object>(2);
clientAttendanceChange.put(clientIdParamName, clientAttendanceOriginal.clientId()); clientAttendanceChange.put(clientIdParamName, clientAttendanceOriginal.clientId());
@@ -123,32 +124,32 @@ public class Meeting extends AbstractPersistable<Long> {
continue updateAttendanceLoop; continue updateAttendanceLoop;
} }
} }
final Map<String, Object> clientAttendanceChange = new LinkedHashMap<String, Object>(); final Map<String, Object> clientAttendanceChange = new LinkedHashMap<String, Object>();
clientAttendanceChange.put(clientIdParamName, clientAttendance.clientId()); clientAttendanceChange.put(clientIdParamName, clientAttendance.clientId());
clientAttendanceChange.put(attendanceTypeParamName, clientAttendance.getAttendanceTypeId()); clientAttendanceChange.put(attendanceTypeParamName, clientAttendance.getAttendanceTypeId());
clientAttendanceChanges.put(clientAttendance.clientId().toString(), clientAttendanceChange); clientAttendanceChanges.put(clientAttendance.clientId().toString(), clientAttendanceChange);
//New attendance record // New attendance record
this.clientsAttendance.add(clientAttendance); this.clientsAttendance.add(clientAttendance);
} }
actualChanges.put(clientsAttendanceParamName, clientAttendanceChanges); actualChanges.put(clientsAttendanceParamName, clientAttendanceChanges);
return actualChanges; return actualChanges;
} }
public Long entityId() { public Long entityId() {
return calendarInstance.getEntityId(); return calendarInstance.getEntityId();
} }
public boolean isCenterEntity(){ public boolean isCenterEntity() {
return CalendarEntityType.isCenter(calendarInstance.getEntityTypeId()); return CalendarEntityType.isCenter(calendarInstance.getEntityTypeId());
} }
public boolean isGroupEntity(){ public boolean isGroupEntity() {
return CalendarEntityType.isGroup(calendarInstance.getEntityTypeId()); return CalendarEntityType.isGroup(calendarInstance.getEntityTypeId());
} }
public LocalDate getMeetingDateLocalDate() { public LocalDate getMeetingDateLocalDate() {
LocalDate meetingDateLocalDate = null; LocalDate meetingDateLocalDate = null;
if (this.meetingDate != null) { if (this.meetingDate != null) {
@@ -156,8 +157,8 @@ public class Meeting extends AbstractPersistable<Long> {
} }
return meetingDateLocalDate; return meetingDateLocalDate;
} }
public Date getMeetingDate(){ public Date getMeetingDate() {
return this.meetingDate; return this.meetingDate;
} }
@@ -165,24 +166,23 @@ public class Meeting extends AbstractPersistable<Long> {
return (this.meetingDate != null && newStartDate != null && getMeetingDateLocalDate().isBefore(newStartDate)) ? true : false; 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(); final Calendar calendar = calendarInstance.getCalendar();
LocalDate meetingDateLocalDate = null; LocalDate meetingDateLocalDate = null;
if (meetingDate != null) { if (meetingDate != null) {
meetingDateLocalDate = LocalDate.fromDateFields(meetingDate); 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; return true;
} }
private boolean isMeetingDateAfter(final LocalDate date){ private boolean isMeetingDateAfter(final LocalDate date) {
return getMeetingDateLocalDate().isAfter(date); return getMeetingDateLocalDate().isAfter(date);
} }
public Collection<ClientAttendance> getClientsAttendance() { public Collection<ClientAttendance> getClientsAttendance() {
return this.clientsAttendance; return this.clientsAttendance;
} }
} }
@@ -5,9 +5,11 @@
*/ */
package org.mifosplatform.portfolio.meeting.domain; package org.mifosplatform.portfolio.meeting.domain;
import java.util.Date;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface MeetingRepository extends JpaRepository<Meeting, Long>, JpaSpecificationExecutor<Meeting> { 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 { public interface MeetingWritePlatformService {
CommandProcessingResult createMeeting(JsonCommand command); CommandProcessingResult createMeeting(JsonCommand command);
void updateCollectionSheetAttendance(JsonCommand command);
CommandProcessingResult updateMeeting(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.clientIdParamName;
import static org.mifosplatform.portfolio.meeting.MeetingApiConstants.clientsAttendanceParamName; import static org.mifosplatform.portfolio.meeting.MeetingApiConstants.clientsAttendanceParamName;
import static org.mifosplatform.portfolio.meeting.MeetingApiConstants.meetingDateParamName; import static org.mifosplatform.portfolio.meeting.MeetingApiConstants.meetingDateParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.transactionDateParamName;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; 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.attendance.domain.ClientAttendance;
import org.mifosplatform.portfolio.meeting.data.MeetingDataValidator; import org.mifosplatform.portfolio.meeting.data.MeetingDataValidator;
import org.mifosplatform.portfolio.meeting.domain.Meeting; import org.mifosplatform.portfolio.meeting.domain.Meeting;
import org.mifosplatform.portfolio.meeting.domain.MeetingRepository;
import org.mifosplatform.portfolio.meeting.domain.MeetingRepositoryWrapper; import org.mifosplatform.portfolio.meeting.domain.MeetingRepositoryWrapper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DataIntegrityViolationException;
@@ -48,7 +51,8 @@ import com.google.gson.JsonObject;
@Service @Service
public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWritePlatformService { public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWritePlatformService {
private final MeetingRepositoryWrapper meetingRepository; private final MeetingRepositoryWrapper meetingRepositoryWrapper;
private final MeetingRepository meetingRepository;
private final MeetingDataValidator meetingDataValidator; private final MeetingDataValidator meetingDataValidator;
private final CalendarInstanceRepository calendarInstanceRepository; private final CalendarInstanceRepository calendarInstanceRepository;
private final CalendarRepository calendarRepository; private final CalendarRepository calendarRepository;
@@ -57,10 +61,11 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit
private final FromJsonHelper fromApiJsonHelper; private final FromJsonHelper fromApiJsonHelper;
@Autowired @Autowired
public MeetingWritePlatformServiceJpaRepositoryImpl(MeetingRepositoryWrapper meetingRepository, public MeetingWritePlatformServiceJpaRepositoryImpl(final MeetingRepositoryWrapper meetingRepositoryWrapper,
MeetingDataValidator meetingDataValidator, CalendarInstanceRepository calendarInstanceRepository, final MeetingRepository meetingRepository, final MeetingDataValidator meetingDataValidator,
CalendarRepository calendarRepository, final ClientRepository clientRepository, final GroupRepository groupRepository, final CalendarInstanceRepository calendarInstanceRepository, final CalendarRepository calendarRepository,
final FromJsonHelper fromApiJsonHelper) { final ClientRepository clientRepository, final GroupRepository groupRepository, final FromJsonHelper fromApiJsonHelper) {
this.meetingRepositoryWrapper = meetingRepositoryWrapper;
this.meetingRepository = meetingRepository; this.meetingRepository = meetingRepository;
this.meetingDataValidator = meetingDataValidator; this.meetingDataValidator = meetingDataValidator;
this.calendarInstanceRepository = calendarInstanceRepository; this.calendarInstanceRepository = calendarInstanceRepository;
@@ -71,7 +76,7 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit
} }
@Override @Override
public CommandProcessingResult createMeeting(JsonCommand command) { public CommandProcessingResult createMeeting(final JsonCommand command) {
this.meetingDataValidator.validateForCreate(command); this.meetingDataValidator.validateForCreate(command);
@@ -87,13 +92,13 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit
newMeeting.associateClientsAttendance(clientsAttendance); newMeeting.associateClientsAttendance(clientsAttendance);
} }
// save meeting details // save meeting details
this.meetingRepository.save(newMeeting); this.meetingRepositoryWrapper.save(newMeeting);
final Long groupId = newMeeting.isGroupEntity() ? newMeeting.entityId() : null; final Long groupId = newMeeting.isGroupEntity() ? newMeeting.entityId() : null;
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withEntityId(newMeeting.getId()) // .withEntityId(newMeeting.getId()) //
.withGroupId(groupId).build(); .withGroupId(groupId).build();
} catch (DataIntegrityViolationException dve) { } catch (final DataIntegrityViolationException dve) {
handleMeetingDataIntegrityIssues(meetingDate, dve); handleMeetingDataIntegrityIssues(meetingDate, dve);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.build(); .build();
@@ -107,11 +112,12 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit
if (calendarForUpdate == null) { throw new CalendarNotFoundException(calendarId); } if (calendarForUpdate == null) { throw new CalendarNotFoundException(calendarId); }
final Integer entityTypeId = CalendarEntityType.valueOf(command.getSupportedEntityType().toUpperCase()).getValue(); final Integer entityTypeId = CalendarEntityType.valueOf(command.getSupportedEntityType().toUpperCase()).getValue();
final CalendarInstance calendarInstance = calendarInstanceRepository.findByCalendarIdAndEntityIdAndEntityTypeId( final CalendarInstance calendarInstance = this.calendarInstanceRepository.findByCalendarIdAndEntityIdAndEntityTypeId(
calendarForUpdate.getId(), entityId, entityTypeId); calendarForUpdate.getId(), entityId, entityTypeId);
if(calendarInstance == null) { if (calendarInstance == null) {
final String postFix = "for." + command.getSupportedEntityType() + "not.found"; 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); throw new CalendarInstanceNotFoundException(postFix, defaultUserMessage, entityId, calendarId);
} }
return calendarInstance; return calendarInstance;
@@ -144,16 +150,17 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit
} else if (meeting.isCenterEntity()) { } else if (meeting.isCenterEntity()) {
if (childGroups != null && !childGroups.isEmpty()) { if (childGroups != null && !childGroups.isEmpty()) {
boolean isChildClient = false; boolean isChildClient = false;
for (Group group : childGroups) { for (final Group group : childGroups) {
if (group.isChildClient(clientId)){ if (group.isChildClient(clientId)) {
isChildClient = true; isChildClient = true;
break; break;
} }
} }
if(!isChildClient){ if (!isChildClient) {
final String defaultUserMessage = "Client with identifier " + clientId + " is not in center " final String defaultUserMessage = "Client with identifier " + clientId + " is not in center "
+ meeting.entityId(); + 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 @Override
public CommandProcessingResult updateMeeting(JsonCommand command) { public CommandProcessingResult updateMeeting(final JsonCommand command) {
this.meetingDataValidator.validateForUpdate(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); final Map<String, Object> changes = meetingForUpdate.update(command);
try { try {
if (!changes.isEmpty()) { if (!changes.isEmpty()) {
this.meetingRepository.saveAndFlush(meetingForUpdate); this.meetingRepositoryWrapper.saveAndFlush(meetingForUpdate);
} }
} catch (DataIntegrityViolationException dve) { } catch (final DataIntegrityViolationException dve) {
handleMeetingDataIntegrityIssues(meetingForUpdate.getMeetingDate(), dve); handleMeetingDataIntegrityIssues(meetingForUpdate.getMeetingDate(), dve);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.build(); .build();
@@ -191,23 +198,23 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit
} }
@Override @Override
public CommandProcessingResult deleteMeeting(Long meetingId) { public CommandProcessingResult deleteMeeting(final Long meetingId) {
final Meeting meetingForDelete = this.meetingRepository.findOneWithNotFoundDetection(meetingId); final Meeting meetingForDelete = this.meetingRepositoryWrapper.findOneWithNotFoundDetection(meetingId);
this.meetingRepository.delete(meetingForDelete); this.meetingRepositoryWrapper.delete(meetingForDelete);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withEntityId(meetingId) // .withEntityId(meetingId) //
.build(); .build();
} }
@Override @Override
public CommandProcessingResult saveOrUpdateAttendance(JsonCommand command) { public CommandProcessingResult saveOrUpdateAttendance(final JsonCommand command) {
this.meetingDataValidator.validateForUpdateAttendance(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 Collection<ClientAttendance> clientsAttendance = getClientsAttendance(meetingForUpdate, command);
final Map<String, Object> changes = meetingForUpdate.updateAttendance(clientsAttendance); final Map<String, Object> changes = meetingForUpdate.updateAttendance(clientsAttendance);
this.meetingRepository.saveAndFlush(meetingForUpdate); this.meetingRepositoryWrapper.saveAndFlush(meetingForUpdate);
final Long groupId = meetingForUpdate.isGroupEntity() ? meetingForUpdate.entityId() : null; final Long groupId = meetingForUpdate.isGroupEntity() ? meetingForUpdate.entityId() : null;
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withEntityId(meetingForUpdate.getId()) // .withEntityId(meetingForUpdate.getId()) //
@@ -219,11 +226,35 @@ public class MeetingWritePlatformServiceJpaRepositoryImpl implements MeetingWrit
private void handleMeetingDataIntegrityIssues(final Date meetingDate, final DataIntegrityViolationException dve) { private void handleMeetingDataIntegrityIssues(final Date meetingDate, final DataIntegrityViolationException dve) {
final Throwable realCause = dve.getMostSpecificCause(); final Throwable realCause = dve.getMostSpecificCause();
if (realCause.getMessage().contains("unique_calendar_instance_id_meeting_date")) { if (realCause.getMessage().contains("unique_calendar_instance_id_meeting_date")) {
final LocalDate meetingDateLocal = LocalDate.fromDateFields(meetingDate);
throw new PlatformDataIntegrityException("error.msg.meeting.duplicate", "A meeting with date '" + meetingDate + "' already exists", throw new PlatformDataIntegrityException("error.msg.meeting.duplicate", "A meeting with date '" + meetingDateLocal + "' already exists",
meetingDateParamName, meetingDate); } meetingDateParamName, meetingDateLocal); }
throw new PlatformDataIntegrityException("error.msg.meeting.unknown.data.integrity.issue", throw new PlatformDataIntegrityException("error.msg.meeting.unknown.data.integrity.issue",
"Unknown data integrity issue with resource: " + realCause.getMessage()); "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);
}
}
} }