Merge pull request #650 from ashok-conflux/MIFOSX-682

Added validation for meeting frequency, repeats on day and start date for Calendar
This commit is contained in:
Keith Woodlock
2013-10-30 06:43:55 -07:00
15 changed files with 505 additions and 141 deletions
@@ -14,7 +14,7 @@ public class CalendarConstants {
CALENDAR_ID("id"), ENTITY_TYPE("entityType"), ENTITY_ID("entityId"), TITLE("title"), DESCRIPTION("description"), LOCATION(
"location"), START_DATE("startDate"), END_DATE("endDate"), CREATED_DATE("createdDate"), DURATION("duration"), TYPE_ID(
"typeId"), REPEATING("repeating"), REMIND_BY_ID("remindById"), FIRST_REMINDER("firstReminder"), SECOND_REMINDER(
"secondReminder"), LOCALE("locale"), DATE_FORMAT("dateFormat"), REPEATS("repeats"), REPEATS_EVERY("repeatsEvery"), REPEATS_ON_DAY(
"secondReminder"), LOCALE("locale"), DATE_FORMAT("dateFormat"), FREQUENCY("frequency"), INTERVAL("interval"), REPEATS_ON_DAY(
"repeatsOnDay");
private final String value;
@@ -54,10 +54,12 @@ public class CalendarsApiResource {
/**
* The set of parameters that are supported in response for {@link Calendar}
*/
private final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "entityId", "entityType", "title",
"description", "location", "startDate", "endDate", "duration", "type", "repeating", "recurrence", "remindBy", "firstReminder",
"secondReminder", "humanReadable", "createdDate", "lastUpdatedDate", "createdByUserId", "createdByUsername",
"lastUpdatedByUserId", "lastUpdatedByUsername", "recurringDates", "nextTenRecurringDates"));
private final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<String>(
Arrays.asList("id", "entityId", "entityType", "title", "description", "location", "startDate", "endDate", "duration", "type",
"repeating", "recurrence", "frequency", "interval", "repeatsOnDay", "remindBy", "firstReminder", "secondReminder",
"humanReadable", "createdDate", "lastUpdatedDate", "createdByUserId", "createdByUsername", "lastUpdatedByUserId",
"lastUpdatedByUsername", "recurringDates", "nextTenRecurringDates", "entityTypeOptions", "calendarTypeOptions",
"remindByOptions", "frequencyOptions", "repeatsOnDayOptions"));
private final String resourceNameForPermissions = "CALENDAR";
private final PlatformSecurityContext context;
@@ -188,7 +190,7 @@ public class CalendarsApiResource {
@Path("{calendarId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteGLAccount(@PathParam("entityType") final String entityType, @PathParam("entityId") final Long entityId,
public String deleteCalendar(@PathParam("entityType") final String entityType, @PathParam("entityId") final Long entityId,
@PathParam("calendarId") final Long calendarId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteCalendar(entityType, entityId, calendarId).build();
@@ -202,7 +204,10 @@ public class CalendarsApiResource {
final List<EnumOptionData> entityTypeOptions = this.dropdownReadPlatformService.retrieveCalendarEntityTypeOptions();
final List<EnumOptionData> calendarTypeOptions = this.dropdownReadPlatformService.retrieveCalendarTypeOptions();
final List<EnumOptionData> remindByOptions = this.dropdownReadPlatformService.retrieveCalendarRemindByOptions();
return new CalendarData(calendarData, entityTypeOptions, calendarTypeOptions, remindByOptions);
final List<EnumOptionData> frequencyOptions = this.dropdownReadPlatformService.retrieveCalendarFrequencyTypeOptions();
final List<EnumOptionData> repeatsOnDayOptions = this.dropdownReadPlatformService.retrieveCalendarWeekDaysTypeOptions();
return CalendarData.withTemplateOptions(calendarData, entityTypeOptions, calendarTypeOptions, remindByOptions, frequencyOptions,
repeatsOnDayOptions);
}
}
@@ -10,8 +10,10 @@ import java.util.List;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.portfolio.calendar.domain.CalendarFrequencyType;
import org.mifosplatform.portfolio.calendar.domain.CalendarRemindBy;
import org.mifosplatform.portfolio.calendar.domain.CalendarType;
import org.mifosplatform.portfolio.calendar.domain.CalendarWeekDaysType;
import org.mifosplatform.portfolio.calendar.service.CalendarEnumerations;
/**
@@ -31,6 +33,9 @@ public class CalendarData {
private final EnumOptionData type;
private final boolean repeating;
private final String recurrence;
private final EnumOptionData frequency;
private final Integer interval;
private final EnumOptionData repeatsOnDay;
private final EnumOptionData remindBy;
private final Integer firstReminder;
private final Integer secondReminder;
@@ -50,108 +55,44 @@ public class CalendarData {
final List<EnumOptionData> entityTypeOptions;
final List<EnumOptionData> calendarTypeOptions;
final List<EnumOptionData> remindByOptions;
final List<EnumOptionData> frequencyOptions;
final List<EnumOptionData> repeatsOnDayOptions;
public CalendarData(final Long id, final Long entityId, final EnumOptionData entityType, final String title, final String description,
final String location, final LocalDate startDate, final LocalDate endDate, final Integer duration, final EnumOptionData type,
final boolean repeating, final String recurrence, final EnumOptionData remindBy, final Integer firstReminder,
final Integer secondReminder, final String humanReadable, final LocalDate recentEligibleMeetingDate,
final LocalDate createdDate, final LocalDate lastUpdatedDate, final Long createdByUserId, final String createdByUsername,
final Long lastUpdatedByUserId, final String lastUpdatedByUsername) {
public static CalendarData instance(final Long id, final Long entityId, final EnumOptionData entityType, final String title,
final String description, final String location, final LocalDate startDate, final LocalDate endDate, final Integer duration,
final EnumOptionData type, final boolean repeating, final String recurrence, final EnumOptionData frequency,
final Integer interval, final EnumOptionData repeatsOnDay, final EnumOptionData remindBy, final Integer firstReminder,
final Integer secondReminder, final String humanReadable, final LocalDate createdDate, final LocalDate lastUpdatedDate,
final Long createdByUserId, final String createdByUsername, final Long lastUpdatedByUserId, final String lastUpdatedByUsername) {
this.id = id;
this.entityId = entityId;
this.entityType = entityType;
this.title = title;
this.description = description;
this.location = location;
this.startDate = startDate;
this.endDate = endDate;
this.duration = duration;
this.type = type;
this.repeating = repeating;
this.recurrence = recurrence;
this.remindBy = remindBy;
this.firstReminder = firstReminder;
this.secondReminder = secondReminder;
this.entityTypeOptions = null;
this.calendarTypeOptions = null;
this.remindByOptions = null;
this.recurringDates = null;
this.nextTenRecurringDates = null;
this.humanReadable = humanReadable;
this.recentEligibleMeetingDate = recentEligibleMeetingDate;
final Collection<LocalDate> recurringDates = null;
final Collection<LocalDate> nextTenRecurringDates = null;
final LocalDate recentEligibleMeetingDate = null;
this.createdDate = createdDate;
this.lastUpdatedDate = lastUpdatedDate;
this.createdByUserId = createdByUserId;
this.createdByUsername = createdByUsername;
this.lastUpdatedByUserId = lastUpdatedByUserId;
this.lastUpdatedByUsername = lastUpdatedByUsername;
final List<EnumOptionData> entityTypeOptions = null;
final List<EnumOptionData> calendarTypeOptions = null;
final List<EnumOptionData> remindByOptions = null;
final List<EnumOptionData> frequencyOptions = null;
final List<EnumOptionData> repeatsOnDayOptions = null;
return new CalendarData(id, entityId, entityType, title, description, location, startDate, endDate, duration, type, repeating,
recurrence, frequency, interval, repeatsOnDay, remindBy, firstReminder, secondReminder, recurringDates,
nextTenRecurringDates, humanReadable, recentEligibleMeetingDate, createdDate, lastUpdatedDate, createdByUserId,
createdByUsername, lastUpdatedByUserId, lastUpdatedByUsername, entityTypeOptions, calendarTypeOptions, remindByOptions,
frequencyOptions, repeatsOnDayOptions);
}
public CalendarData(final CalendarData calendarData, final List<EnumOptionData> entityTypeOptions,
final List<EnumOptionData> calendarTypeOptions, final List<EnumOptionData> remindByOptions) {
this.id = calendarData.id;
this.entityId = calendarData.entityId;
this.entityType = calendarData.entityType;
this.title = calendarData.title;
this.description = calendarData.description;
this.location = calendarData.location;
this.startDate = calendarData.startDate;
this.endDate = calendarData.endDate;
this.duration = calendarData.duration;
this.type = calendarData.type;
this.repeating = calendarData.repeating;
this.recurrence = calendarData.recurrence;
this.remindBy = calendarData.remindBy;
this.firstReminder = calendarData.firstReminder;
this.secondReminder = calendarData.secondReminder;
this.entityTypeOptions = entityTypeOptions;
this.calendarTypeOptions = calendarTypeOptions;
this.remindByOptions = remindByOptions;
this.recurringDates = calendarData.recurringDates;
this.nextTenRecurringDates = calendarData.nextTenRecurringDates;
this.humanReadable = calendarData.humanReadable;
this.recentEligibleMeetingDate = calendarData.recentEligibleMeetingDate;
this.createdDate = calendarData.createdDate;
this.lastUpdatedDate = calendarData.lastUpdatedDate;
this.createdByUserId = calendarData.createdByUserId;
this.createdByUsername = calendarData.createdByUsername;
this.lastUpdatedByUserId = calendarData.lastUpdatedByUserId;
this.lastUpdatedByUsername = calendarData.lastUpdatedByUsername;
}
public CalendarData(final CalendarData calendarData, final Collection<LocalDate> recurringDates,
public static CalendarData withRecurringDates(final CalendarData calendarData, final Collection<LocalDate> recurringDates,
final Collection<LocalDate> nextTenRecurringDates, final LocalDate recentEligibleMeetingDate) {
this.id = calendarData.id;
this.entityId = calendarData.entityId;
this.entityType = calendarData.entityType;
this.title = calendarData.title;
this.description = calendarData.description;
this.location = calendarData.location;
this.startDate = calendarData.startDate;
this.endDate = calendarData.endDate;
this.duration = calendarData.duration;
this.type = calendarData.type;
this.repeating = calendarData.repeating;
this.recurrence = calendarData.recurrence;
this.remindBy = calendarData.remindBy;
this.firstReminder = calendarData.firstReminder;
this.secondReminder = calendarData.secondReminder;
this.entityTypeOptions = null;
this.calendarTypeOptions = null;
this.remindByOptions = null;
this.recurringDates = recurringDates;
this.nextTenRecurringDates = nextTenRecurringDates;
this.humanReadable = calendarData.humanReadable;
this.recentEligibleMeetingDate = recentEligibleMeetingDate;
this.createdDate = calendarData.createdDate;
this.lastUpdatedDate = calendarData.lastUpdatedDate;
this.createdByUserId = calendarData.createdByUserId;
this.createdByUsername = calendarData.createdByUsername;
this.lastUpdatedByUserId = calendarData.lastUpdatedByUserId;
this.lastUpdatedByUsername = calendarData.lastUpdatedByUsername;
return new CalendarData(calendarData.id, calendarData.entityId, calendarData.entityType, calendarData.title,
calendarData.description, calendarData.location, calendarData.startDate, calendarData.endDate, calendarData.duration,
calendarData.type, calendarData.repeating, calendarData.recurrence, calendarData.frequency, calendarData.interval,
calendarData.repeatsOnDay, calendarData.remindBy, calendarData.firstReminder, calendarData.secondReminder, recurringDates,
nextTenRecurringDates, calendarData.humanReadable, recentEligibleMeetingDate, calendarData.createdDate,
calendarData.lastUpdatedDate, calendarData.createdByUserId, calendarData.createdByUsername,
calendarData.lastUpdatedByUserId, calendarData.lastUpdatedByUsername, calendarData.entityTypeOptions,
calendarData.calendarTypeOptions, calendarData.remindByOptions, calendarData.frequencyOptions,
calendarData.repeatsOnDayOptions);
}
public static CalendarData sensibleDefaultsForNewCalendarCreation() {
@@ -167,12 +108,23 @@ public class CalendarData {
final EnumOptionData type = CalendarEnumerations.calendarType(CalendarType.COLLECTION);
final boolean repeating = false;
final String recurrence = null;
final EnumOptionData frequency = CalendarEnumerations.calendarFrequencyType(CalendarFrequencyType.DAILY);
final Integer interval = new Integer(1);
final EnumOptionData repeatsOnDay = CalendarEnumerations.calendarWeekDaysType(CalendarWeekDaysType.MO);
final EnumOptionData remindBy = CalendarEnumerations.calendarRemindBy(CalendarRemindBy.EMAIL);
final Integer firstReminder = new Integer(0);
final Integer secondReminder = new Integer(0);
final String humanReadable = null;
final Collection<LocalDate> recurringDates = null;
final Collection<LocalDate> nextTenRecurringDates = null;
final LocalDate recentEligibleMeetingDate = null;
final List<EnumOptionData> entityTypeOptions = null;
final List<EnumOptionData> calendarTypeOptions = null;
final List<EnumOptionData> remindByOptions = null;
final List<EnumOptionData> frequencyOptions = null;
final List<EnumOptionData> repeatsOnDayOptions = null;
final LocalDate createdDate = null;
final LocalDate lastUpdatedDate = null;
final Long createdByUserId = null;
@@ -181,8 +133,69 @@ public class CalendarData {
final String lastUpdatedByUsername = null;
return new CalendarData(id, entityId, entityType, title, description, location, startDate, endDate, duration, type, repeating,
recurrence, remindBy, firstReminder, secondReminder, humanReadable, recentEligibleMeetingDate, createdDate,
lastUpdatedDate, createdByUserId, createdByUsername, lastUpdatedByUserId, lastUpdatedByUsername);
recurrence, frequency, interval, repeatsOnDay, remindBy, firstReminder, secondReminder, recurringDates,
nextTenRecurringDates, humanReadable, recentEligibleMeetingDate, createdDate, lastUpdatedDate, createdByUserId,
createdByUsername, lastUpdatedByUserId, lastUpdatedByUsername, entityTypeOptions, calendarTypeOptions, remindByOptions,
frequencyOptions, repeatsOnDayOptions);
}
public static CalendarData withTemplateOptions(final CalendarData calendarData, final List<EnumOptionData> entityTypeOptions,
final List<EnumOptionData> calendarTypeOptions, final List<EnumOptionData> remindByOptions,
final List<EnumOptionData> repeatsOptions, final List<EnumOptionData> repeatsOnDayOptions) {
return new CalendarData(calendarData.id, calendarData.entityId, calendarData.entityType, calendarData.title,
calendarData.description, calendarData.location, calendarData.startDate, calendarData.endDate, calendarData.duration,
calendarData.type, calendarData.repeating, calendarData.recurrence, calendarData.frequency, calendarData.interval,
calendarData.repeatsOnDay, calendarData.remindBy, calendarData.firstReminder, calendarData.secondReminder,
calendarData.recurringDates, calendarData.nextTenRecurringDates, calendarData.humanReadable,
calendarData.recentEligibleMeetingDate, calendarData.createdDate, calendarData.lastUpdatedDate,
calendarData.createdByUserId, calendarData.createdByUsername, calendarData.lastUpdatedByUserId, calendarData.lastUpdatedByUsername,
entityTypeOptions, calendarTypeOptions, remindByOptions, repeatsOptions, repeatsOnDayOptions);
}
private CalendarData(final Long id, final Long entityId, final EnumOptionData entityType, final String title, final String description,
final String location, final LocalDate startDate, final LocalDate endDate, final Integer duration, final EnumOptionData type,
final boolean repeating, final String recurrence, final EnumOptionData frequency, final Integer interval,
final EnumOptionData repeatsOnDay, final EnumOptionData remindBy, final Integer firstReminder, final Integer secondReminder,
final Collection<LocalDate> recurringDates, final Collection<LocalDate> nextTenRecurringDates, 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 List<EnumOptionData> entityTypeOptions, final List<EnumOptionData> calendarTypeOptions,
final List<EnumOptionData> remindByOptions, final List<EnumOptionData> repeatsOptions,
final List<EnumOptionData> repeatsOnDayOptions) {
this.id = id;
this.entityId = entityId;
this.entityType = entityType;
this.title = title;
this.description = description;
this.location = location;
this.startDate = startDate;
this.endDate = endDate;
this.duration = duration;
this.type = type;
this.repeating = repeating;
this.recurrence = recurrence;
this.frequency = frequency;
this.interval = interval;
this.repeatsOnDay = repeatsOnDay;
this.remindBy = remindBy;
this.firstReminder = firstReminder;
this.secondReminder = secondReminder;
this.recurringDates = recurringDates;
this.nextTenRecurringDates = nextTenRecurringDates;
this.humanReadable = humanReadable;
this.recentEligibleMeetingDate = recentEligibleMeetingDate;
this.createdDate = createdDate;
this.lastUpdatedDate = lastUpdatedDate;
this.createdByUserId = createdByUserId;
this.createdByUsername = createdByUsername;
this.lastUpdatedByUserId = lastUpdatedByUserId;
this.lastUpdatedByUsername = lastUpdatedByUsername;
this.entityTypeOptions = entityTypeOptions;
this.calendarTypeOptions = calendarTypeOptions;
this.remindByOptions = remindByOptions;
this.frequencyOptions = repeatsOptions;
this.repeatsOnDayOptions = repeatsOnDayOptions;
}
public Long getId() {
@@ -337,19 +337,21 @@ public class Calendar extends AbstractAuditableCustom<AppUser, Long> {
if (repeating) {
final StringBuilder recurrenceBuilder = new StringBuilder(200);
final String repeats = command.stringValueOfParameterNamed(CALENDAR_SUPPORTED_PARAMETERS.REPEATS.getValue());
final Integer frequency = command.integerValueOfParameterNamed(CALENDAR_SUPPORTED_PARAMETERS.FREQUENCY.getValue());
final CalendarFrequencyType frequencyType = CalendarFrequencyType.fromInt(frequency);
recurrenceBuilder.append("FREQ=");
recurrenceBuilder.append(repeats.toUpperCase());
final Integer repeatsEvery = command.integerValueOfParameterNamed(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_EVERY.getValue());
if (repeatsEvery > 1) {
recurrenceBuilder.append(frequencyType.toString().toUpperCase());
final Integer interval = command.integerValueOfParameterNamed(CALENDAR_SUPPORTED_PARAMETERS.INTERVAL.getValue());
if (interval > 1) {
recurrenceBuilder.append(";INTERVAL=");
recurrenceBuilder.append(repeatsEvery);
recurrenceBuilder.append(interval);
}
if (repeats.equalsIgnoreCase("Weekly")) {
final String repeatsOnDay = command.stringValueOfParameterNamed(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_DAY.getValue());
if (repeatsOnDay != null && repeatsOnDay != "") {
if (frequencyType.isWeekly()) {
final Integer repeatsOnDay = command.integerValueOfParameterNamed(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_DAY.getValue());
final CalendarWeekDaysType weekDays = CalendarWeekDaysType.fromInt(repeatsOnDay);
if (!weekDays.isInvalid()) {
recurrenceBuilder.append(";BYDAY=");
recurrenceBuilder.append(repeatsOnDay);
recurrenceBuilder.append(weekDays.toString().toUpperCase());
}
}
return recurrenceBuilder.toString();
@@ -82,4 +82,36 @@ public enum CalendarEntityType {
public static boolean isCenter(final String name) {
return CalendarEntityType.CENTERS.name().equalsIgnoreCase(name) ? true : false;
}
public static boolean isLoan(final Integer value) {
return CalendarEntityType.LOANS.value.equals(value) ? true : false;
}
public static boolean isLoan(final String name) {
return CalendarEntityType.LOANS.name().equalsIgnoreCase(name) ? true : false;
}
public static boolean isClient(final Integer value) {
return CalendarEntityType.CLIENTS.value.equals(value) ? true : false;
}
public static boolean isClient(final String name) {
return CalendarEntityType.CLIENTS.name().equalsIgnoreCase(name) ? true : false;
}
public boolean isCenter() {
return this.value.equals(CalendarEntityType.CENTERS.getValue());
}
public boolean isGroup() {
return this.value.equals(CalendarEntityType.GROUPS.getValue());
}
public boolean isLoan() {
return this.value.equals(CalendarEntityType.LOANS.getValue());
}
public boolean isClient() {
return this.value.equals(CalendarEntityType.CLIENTS.getValue());
}
}
@@ -0,0 +1,87 @@
/**
* 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 java.util.HashMap;
import java.util.Map;
import org.springframework.util.StringUtils;
public enum CalendarFrequencyType {
INVALID(0, "calendarFrequencyType.invalid"), DAILY(1, "calendarFrequencyType.daily"), WEEKLY(2, "calendarFrequencyType.weekly"), MONTHLY(
3, "calendarFrequencyType.monthly"), YEARLY(4, "calendarFrequencyType.yearly");
private final Integer value;
private final String code;
private CalendarFrequencyType(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return this.code;
}
private static final Map<Integer, CalendarFrequencyType> intToEnumMap = new HashMap<Integer, CalendarFrequencyType>();
private static int minValue = CalendarFrequencyType.DAILY.value;
private static int maxValue = CalendarFrequencyType.YEARLY.value;
static {
for (final CalendarFrequencyType type : CalendarFrequencyType.values()) {
intToEnumMap.put(type.value, type);
}
}
public static CalendarFrequencyType fromInt(final int i) {
final CalendarFrequencyType type = intToEnumMap.get(Integer.valueOf(i));
return type;
}
public static CalendarFrequencyType fromString(final String frequencyString) {
CalendarFrequencyType frequency = CalendarFrequencyType.INVALID;
if (StringUtils.isEmpty(frequencyString)) return frequency;
if (frequencyString.equalsIgnoreCase(CalendarFrequencyType.DAILY.toString())) {
frequency = CalendarFrequencyType.DAILY;
} else if (frequencyString.equalsIgnoreCase(CalendarFrequencyType.WEEKLY.toString())) {
frequency = CalendarFrequencyType.WEEKLY;
} else if (frequencyString.equalsIgnoreCase(CalendarFrequencyType.MONTHLY.toString())) {
frequency = CalendarFrequencyType.MONTHLY;
} else if (frequencyString.equalsIgnoreCase(CalendarFrequencyType.YEARLY.toString())) {
frequency = CalendarFrequencyType.YEARLY;
}
return frequency;
}
public static int getMinValue() {
return minValue;
}
public static int getMaxValue() {
return maxValue;
}
@Override
public String toString() {
return name().toString();
}
public boolean isWeekly(){
return this.value.equals(CalendarFrequencyType.WEEKLY.value);
}
public boolean isInvalid(){
return this.value.equals(CalendarFrequencyType.INVALID.value);
}
}
@@ -0,0 +1,91 @@
/**
* 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 java.util.HashMap;
import java.util.Map;
import org.springframework.util.StringUtils;
public enum CalendarWeekDaysType {
INVALID(0, "calendarWeekDaysType.invalid"), MO(1, "calendarWeekDaysType.monday"), TU(2, "calendarWeekDaysType.tuesday"), WE(3,
"calendarWeekDaysType.wednesday"), TH(4, "calendarWeekDaysType.thursday"), FR(5, "calendarWeekDaysType.friday"), SA(6,
"calendarWeekDaysType.saturday"), SU(7, "calendarWeekDaysType.sunday");
private final Integer value;
private final String code;
private CalendarWeekDaysType(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return this.code;
}
private static final Map<Integer, CalendarWeekDaysType> intToEnumMap = new HashMap<Integer, CalendarWeekDaysType>();
private static int minValue = CalendarWeekDaysType.MO.value;
private static int maxValue = CalendarWeekDaysType.SU.value;
static {
for (final CalendarWeekDaysType type : CalendarWeekDaysType.values()) {
intToEnumMap.put(type.value, type);
}
}
public static CalendarWeekDaysType fromInt(final int i) {
final CalendarWeekDaysType type = intToEnumMap.get(Integer.valueOf(i));
return type;
}
public static int getMinValue() {
return minValue;
}
public static int getMaxValue() {
return maxValue;
}
@Override
public String toString() {
return name().toString();
}
public boolean isInvalid(){
return this.value.equals(CalendarWeekDaysType.INVALID.value);
}
public static CalendarWeekDaysType fromString(final String weekDayString) {
CalendarWeekDaysType weekDay = CalendarWeekDaysType.INVALID;
if (StringUtils.isEmpty(weekDayString)) return weekDay;
if (weekDayString.equalsIgnoreCase(CalendarWeekDaysType.MO.toString())) {
weekDay = CalendarWeekDaysType.MO;
} else if (weekDayString.equalsIgnoreCase(CalendarWeekDaysType.TU.toString())) {
weekDay = CalendarWeekDaysType.TU;
} else if (weekDayString.equalsIgnoreCase(CalendarWeekDaysType.WE.toString())) {
weekDay = CalendarWeekDaysType.WE;
} else if (weekDayString.equalsIgnoreCase(CalendarWeekDaysType.TH.toString())) {
weekDay = CalendarWeekDaysType.TH;
} else if (weekDayString.equalsIgnoreCase(CalendarWeekDaysType.FR.toString())) {
weekDay = CalendarWeekDaysType.FR;
} else if (weekDayString.equalsIgnoreCase(CalendarWeekDaysType.SA.toString())) {
weekDay = CalendarWeekDaysType.SA;
} else if (weekDayString.equalsIgnoreCase(CalendarWeekDaysType.SU.toString())) {
weekDay = CalendarWeekDaysType.SU;
}
return weekDay;
}
}
@@ -22,7 +22,9 @@ import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.portfolio.calendar.CalendarConstants.CALENDAR_SUPPORTED_PARAMETERS;
import org.mifosplatform.portfolio.calendar.command.CalendarCommand;
import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType;
import org.mifosplatform.portfolio.calendar.domain.CalendarFrequencyType;
import org.mifosplatform.portfolio.calendar.domain.CalendarRemindBy;
import org.mifosplatform.portfolio.calendar.domain.CalendarWeekDaysType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -141,22 +143,22 @@ public class CalendarCommandFromApiJsonDeserializer extends AbstractFromApiJsonD
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.REPEATING.getValue()).value(repeating).notNull();
if (repeating) {
final String repeats = this.fromApiJsonHelper.extractStringNamed(CALENDAR_SUPPORTED_PARAMETERS.REPEATS.getValue(), element);
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.REPEATS.getValue()).value(repeats).notBlank()
.notExceedingLengthOf(20);
final Integer frequency = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(
CALENDAR_SUPPORTED_PARAMETERS.FREQUENCY.getValue(), element);
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.FREQUENCY.getValue()).value(frequency).notBlank()
.inMinMaxRange(CalendarFrequencyType.getMinValue(), CalendarFrequencyType.getMaxValue());
if (this.fromApiJsonHelper.parameterExists(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_EVERY.getValue(), element)) {
final Integer repeatsEvery = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(
CALENDAR_SUPPORTED_PARAMETERS.REPEATS_EVERY.getValue(), element);
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_EVERY.getValue()).value(repeatsEvery)
if (this.fromApiJsonHelper.parameterExists(CALENDAR_SUPPORTED_PARAMETERS.INTERVAL.getValue(), element)) {
final Integer interval = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(
CALENDAR_SUPPORTED_PARAMETERS.INTERVAL.getValue(), element);
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.INTERVAL.getValue()).value(interval)
.notNull().integerGreaterThanZero();
}
if (this.fromApiJsonHelper.parameterExists(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_DAY.getValue(), element)) {
final String repeatsOnDay = this.fromApiJsonHelper.extractStringNamed(
if (CalendarFrequencyType.fromInt(frequency).isWeekly()) {
final Integer repeatsOnDay = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(
CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_DAY.getValue(), element);
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_DAY.getValue()).value(repeatsOnDay)
.notBlank().notNull();
.notBlank().inMinMaxRange(CalendarWeekDaysType.getMinValue(), CalendarWeekDaysType.getMaxValue());
}
}
}
@@ -251,22 +253,23 @@ public class CalendarCommandFromApiJsonDeserializer extends AbstractFromApiJsonD
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.REPEATING.getValue()).value(repeating).notNull();
if (repeating) {
final String repeats = this.fromApiJsonHelper.extractStringNamed(CALENDAR_SUPPORTED_PARAMETERS.REPEATS.getValue(), element);
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.REPEATS.getValue()).value(repeats).ignoreIfNull()
.notBlank().notExceedingLengthOf(20);
final Integer frequency = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(
CALENDAR_SUPPORTED_PARAMETERS.FREQUENCY.getValue(), element);
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.FREQUENCY.getValue()).value(frequency).notBlank()
.inMinMaxRange(CalendarFrequencyType.getMinValue(), CalendarFrequencyType.getMaxValue());
if (this.fromApiJsonHelper.parameterExists(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_EVERY.getValue(), element)) {
final Integer repeatsEvery = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(
CALENDAR_SUPPORTED_PARAMETERS.REPEATS_EVERY.getValue(), element);
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_EVERY.getValue()).value(repeatsEvery)
if (this.fromApiJsonHelper.parameterExists(CALENDAR_SUPPORTED_PARAMETERS.INTERVAL.getValue(), element)) {
final Integer interval = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(
CALENDAR_SUPPORTED_PARAMETERS.INTERVAL.getValue(), element);
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.INTERVAL.getValue()).value(interval)
.notNull().integerGreaterThanZero();
}
if (this.fromApiJsonHelper.parameterExists(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_DAY.getValue(), element)) {
final String repeatsOnDay = this.fromApiJsonHelper.extractStringNamed(
final Integer repeatsOnDay = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(
CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_DAY.getValue(), element);
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_DAY.getValue()).value(repeatsOnDay)
.notBlank();
.notBlank().inMinMaxRange(CalendarWeekDaysType.getMinValue(), CalendarWeekDaysType.getMaxValue());
}
}
}
@@ -16,5 +16,9 @@ public interface CalendarDropdownReadPlatformService {
List<EnumOptionData> retrieveCalendarTypeOptions();
List<EnumOptionData> retrieveCalendarRemindByOptions();
List<EnumOptionData> retrieveCalendarFrequencyTypeOptions();
List<EnumOptionData> retrieveCalendarWeekDaysTypeOptions();
}
@@ -9,8 +9,10 @@ import java.util.List;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType;
import org.mifosplatform.portfolio.calendar.domain.CalendarFrequencyType;
import org.mifosplatform.portfolio.calendar.domain.CalendarRemindBy;
import org.mifosplatform.portfolio.calendar.domain.CalendarType;
import org.mifosplatform.portfolio.calendar.domain.CalendarWeekDaysType;
import org.springframework.stereotype.Service;
@Service
@@ -31,4 +33,13 @@ public class CalendarDropdownReadPlatformServiceImpl implements CalendarDropdown
return CalendarEnumerations.calendarRemindBy(CalendarRemindBy.values());
}
@Override
public List<EnumOptionData> retrieveCalendarFrequencyTypeOptions() {
return CalendarEnumerations.calendarFrequencyType(CalendarFrequencyType.values());
}
@Override
public List<EnumOptionData> retrieveCalendarWeekDaysTypeOptions() {
return CalendarEnumerations.calendarWeekDaysType(CalendarWeekDaysType.values());
}
}
@@ -10,8 +10,10 @@ import java.util.List;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType;
import org.mifosplatform.portfolio.calendar.domain.CalendarFrequencyType;
import org.mifosplatform.portfolio.calendar.domain.CalendarRemindBy;
import org.mifosplatform.portfolio.calendar.domain.CalendarType;
import org.mifosplatform.portfolio.calendar.domain.CalendarWeekDaysType;
public class CalendarEnumerations {
@@ -65,4 +67,42 @@ public class CalendarEnumerations {
}
return optionDatas;
}
public static EnumOptionData calendarFrequencyType(final int id) {
return calendarFrequencyType(CalendarFrequencyType.fromInt(id));
}
public static EnumOptionData calendarFrequencyType(final CalendarFrequencyType calendarFrequencyType) {
final EnumOptionData optionData = new EnumOptionData(calendarFrequencyType.getValue().longValue(), calendarFrequencyType.getCode(), calendarFrequencyType.toString());
return optionData;
}
public static List<EnumOptionData> calendarFrequencyType(final CalendarFrequencyType[] calendarFrequencyTypes) {
final List<EnumOptionData> optionDatas = new ArrayList<EnumOptionData>();
for (final CalendarFrequencyType calendarFrequencyType : calendarFrequencyTypes) {
if(!calendarFrequencyType.isInvalid()){
optionDatas.add(calendarFrequencyType(calendarFrequencyType));
}
}
return optionDatas;
}
public static EnumOptionData calendarWeekDaysType(final int id) {
return calendarWeekDaysType(CalendarWeekDaysType.fromInt(id));
}
public static EnumOptionData calendarWeekDaysType(final CalendarWeekDaysType calendarWeekDaysType) {
final EnumOptionData optionData = new EnumOptionData(calendarWeekDaysType.getValue().longValue(), calendarWeekDaysType.getCode(), calendarWeekDaysType.toString());
return optionData;
}
public static List<EnumOptionData> calendarWeekDaysType(final CalendarWeekDaysType[] calendarWeekDaysTypes) {
final List<EnumOptionData> optionDatas = new ArrayList<EnumOptionData>();
for (final CalendarWeekDaysType calendarWeekDaysType : calendarWeekDaysTypes) {
if(!calendarWeekDaysType.isInvalid()){
optionDatas.add(calendarWeekDaysType(calendarWeekDaysType));
}
}
return optionDatas;
}
}
@@ -67,6 +67,9 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
final EnumOptionData type = CalendarEnumerations.calendarType(typeId);
final boolean repeating = rs.getBoolean("repeating");
final String recurrence = rs.getString("recurrence");
final EnumOptionData frequency = CalendarEnumerations.calendarFrequencyType(CalendarUtils.getFrequency(recurrence));
final Integer interval = new Integer(CalendarUtils.getInterval(recurrence));
final EnumOptionData repeatsOnDay = CalendarEnumerations.calendarWeekDaysType(CalendarUtils.getRepeatsOnDay(recurrence));
final Integer remindById = rs.getInt("remindById");
EnumOptionData remindBy = null;
if (remindById != null && remindById != 0) {
@@ -86,10 +89,8 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
final Long lastUpdatedByUserId = rs.getLong("updatingUserId");
final String lastUpdatedByUserName = rs.getString("updatingUserName");
final LocalDate recentEligibleMeetingDate = null;
return new CalendarData(id, entityId, entityType, title, description, location, startDate, endDate, duration, type, repeating,
recurrence, remindBy, firstReminder, secondReminder, humanReadable, recentEligibleMeetingDate, createdDate,
return CalendarData.instance(id, entityId, entityType, title, description, location, startDate, endDate, duration, type,
repeating, recurrence, frequency, interval, repeatsOnDay, remindBy, firstReminder, secondReminder, humanReadable, createdDate,
lastUpdatedDate, createdByUserId, createdByUserName, lastUpdatedByUserId, lastUpdatedByUserName);
}
}
@@ -216,7 +217,7 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
final Collection<LocalDate> recurringDates = CalendarUtils.getRecurringDates(rrule, seedDate, startDate, endDate, -1);
final Collection<LocalDate> nextTenRecurringDates = CalendarUtils.getRecurringDates(rrule, seedDate, endDate);
final LocalDate recentEligibleMeetingDate = CalendarUtils.getRecentEligibleMeetingDate(rrule, seedDate);
return new CalendarData(calendarData, recurringDates, nextTenRecurringDates, recentEligibleMeetingDate);
return CalendarData.withRecurringDates(calendarData, recurringDates, nextTenRecurringDates, recentEligibleMeetingDate);
}
@@ -32,6 +32,8 @@ import org.mifosplatform.infrastructure.core.service.DateUtils;
import org.mifosplatform.organisation.workingdays.domain.WorkingDays;
import org.mifosplatform.organisation.workingdays.service.WorkingDaysUtil;
import org.mifosplatform.portfolio.calendar.domain.Calendar;
import org.mifosplatform.portfolio.calendar.domain.CalendarFrequencyType;
import org.mifosplatform.portfolio.calendar.domain.CalendarWeekDaysType;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
public class CalendarUtils {
@@ -284,6 +286,20 @@ public class CalendarUtils {
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
return recur.getInterval();
}
public static CalendarFrequencyType getFrequency(final String recurringRule){
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
return CalendarFrequencyType.fromString(recur.getFrequency());
}
public static CalendarWeekDaysType getRepeatsOnDay(final String recurringRule){
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
final WeekDayList weekDays = recur.getDayList();
if(weekDays.isEmpty()) return CalendarWeekDaysType.INVALID;
//supports only one day
WeekDay weekDay = (WeekDay) weekDays.get(0);
return CalendarWeekDaysType.fromString(weekDay.getDay());
}
public static LocalDate getFirstRepaymentMeetingDate(final Calendar calendar, final LocalDate disbursementDate,
final Integer loanRepaymentInterval, final String frequency) {
@@ -5,13 +5,22 @@
*/
package org.mifosplatform.portfolio.calendar.service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.portfolio.calendar.CalendarConstants.CALENDAR_SUPPORTED_PARAMETERS;
import org.mifosplatform.portfolio.calendar.domain.Calendar;
import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType;
import org.mifosplatform.portfolio.calendar.domain.CalendarInstance;
@@ -19,6 +28,12 @@ import org.mifosplatform.portfolio.calendar.domain.CalendarInstanceRepository;
import org.mifosplatform.portfolio.calendar.domain.CalendarRepository;
import org.mifosplatform.portfolio.calendar.exception.CalendarNotFoundException;
import org.mifosplatform.portfolio.calendar.serialization.CalendarCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.group.domain.GroupRepository;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepository;
import org.mifosplatform.portfolio.loanaccount.service.LoanWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -32,17 +47,24 @@ public class CalendarWritePlatformServiceJpaRepositoryImpl implements CalendarWr
private final CalendarInstanceRepository calendarInstanceRepository;
private final LoanWritePlatformService loanWritePlatformService;
private final ConfigurationDomainService configurationDomainService;
private final GroupRepository groupRepository;
private final LoanRepository loanRepository;
private final ClientRepositoryWrapper clientRepository;
@Autowired
public CalendarWritePlatformServiceJpaRepositoryImpl(final CalendarRepository calendarRepository,
final CalendarCommandFromApiJsonDeserializer fromApiJsonDeserializer,
final CalendarInstanceRepository calendarInstanceRepository, final LoanWritePlatformService loanWritePlatformService,
final ConfigurationDomainService configurationDomainService) {
final ConfigurationDomainService configurationDomainService, final GroupRepository groupRepository,
final LoanRepository loanRepository, final ClientRepositoryWrapper clientRepository) {
this.calendarRepository = calendarRepository;
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.calendarInstanceRepository = calendarInstanceRepository;
this.loanWritePlatformService = loanWritePlatformService;
this.configurationDomainService = configurationDomainService;
this.groupRepository = groupRepository;
this.loanRepository = loanRepository;
this.clientRepository = clientRepository;
}
@Override
@@ -50,7 +72,25 @@ public class CalendarWritePlatformServiceJpaRepositoryImpl implements CalendarWr
this.fromApiJsonDeserializer.validateForCreate(command.json());
final LocalDate entityActivationDate = getEntityActivationDate(command);
final CalendarEntityType entityType = CalendarEntityType.valueOf(command.getSupportedEntityType().toUpperCase());
final Calendar newCalendar = Calendar.fromJson(command);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource("calendar");
if(entityActivationDate == null || newCalendar.getStartDateLocalDate().isBefore(entityActivationDate)){
final DateTimeFormatter formatter = DateTimeFormat.forPattern(command.dateFormat()).withLocale(command.extractLocale());
String dateAsString = "";
if(entityActivationDate != null) dateAsString = formatter.print(entityActivationDate);
final String errorMessage = "cannot.be.before." + entityType.name().toLowerCase() + ".activation.date";
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.START_DATE.getValue()).value(dateAsString)
.failWithCodeNoParameterAddedToErrorCode(errorMessage);
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
}
this.calendarRepository.save(newCalendar);
final CalendarInstance newCalendarInstance = CalendarInstance.fromJson(newCalendar, command);
@@ -63,6 +103,25 @@ public class CalendarWritePlatformServiceJpaRepositoryImpl implements CalendarWr
}
private LocalDate getEntityActivationDate(JsonCommand command) {
final Long entityId = command.getSupportedEntityId();
final CalendarEntityType entityType = CalendarEntityType.valueOf(command.getSupportedEntityType().toUpperCase());
LocalDate entityActivationDate = null;
if(entityType.isCenter() || entityType.isGroup()){
final Group centerOrGroup = this.groupRepository.findOne(entityId);
entityActivationDate = centerOrGroup.getActivationLocalDate();
} else if (entityType.isLoan()){
final Loan loan = this.loanRepository.findOne(entityId);
entityActivationDate = (loan.getApprovedOnDate() == null) ? loan.getSubmittedOnDate() : loan.getApprovedOnDate();
} else if (entityType.isLoan()){
final Client client = this.clientRepository.findOneWithNotFoundDetection(entityId);
entityActivationDate = client.getActivationLocalDate();
}
return entityActivationDate;
}
@Override
public CommandProcessingResult updateCalendar(final JsonCommand command) {
@@ -2238,7 +2238,7 @@ public class Loan extends AbstractPersistable<Long> {
return (LocalDate) ObjectUtils.defaultIfNull(new LocalDate(this.submittedOnDate), null);
}
private LocalDate getApprovedOnDate() {
public LocalDate getApprovedOnDate() {
LocalDate date = null;
if (this.approvedOnDate != null) {
date = new LocalDate(this.approvedOnDate);