Merge remote-tracking branch 'ashok/MIFOSX-256'
This commit is contained in:
+1
-1
@@ -365,7 +365,7 @@ public class DataValidatorBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public DataValidatorBuilder isValidateRecurringRule(final String recurringRule) {
|
||||
public DataValidatorBuilder isValidRecurringRule(final String recurringRule) {
|
||||
if (StringUtils.isNotBlank(recurringRule)) {
|
||||
try {
|
||||
RRule rRule = new RRule(recurringRule);
|
||||
|
||||
+25
-25
@@ -40,7 +40,7 @@ import org.mifosplatform.portfolio.calendar.domain.Calendar;
|
||||
import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType;
|
||||
import org.mifosplatform.portfolio.calendar.service.CalendarDropdownReadPlatformService;
|
||||
import org.mifosplatform.portfolio.calendar.service.CalendarReadPlatformService;
|
||||
import org.mifosplatform.portfolio.calendar.service.CalendarWrapperService;
|
||||
import org.mifosplatform.portfolio.calendar.service.CalendarHelper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -54,9 +54,9 @@ 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"));
|
||||
"description", "location", "startDate", "endDate", "duration", "type", "repeating", "recurrence", "remindBy", "firstReminder",
|
||||
"secondReminder", "humanReadable", "createdDate", "lastUpdatedDate", "createdByUserId", "createdByUsername",
|
||||
"lastUpdatedByUserId", "lastUpdatedByUsername", "recurringDates"));
|
||||
private final String resourceNameForPermissions = "CALENDAR";
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
@@ -65,38 +65,37 @@ public class CalendarsApiResource {
|
||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final CalendarDropdownReadPlatformService dropdownReadPlatformService;
|
||||
private final CalendarWrapperService calendarWrapperService;
|
||||
|
||||
@Autowired
|
||||
public CalendarsApiResource(final PlatformSecurityContext context, final CalendarReadPlatformService readPlatformService,
|
||||
final DefaultToApiJsonSerializer<CalendarData> toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper,
|
||||
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
|
||||
final CalendarDropdownReadPlatformService dropdownReadPlatformService, final CalendarWrapperService calendarWrapperService) {
|
||||
final CalendarDropdownReadPlatformService dropdownReadPlatformService) {
|
||||
this.context = context;
|
||||
this.readPlatformService = readPlatformService;
|
||||
this.toApiJsonSerializer = toApiJsonSerializer;
|
||||
this.apiRequestParameterHelper = apiRequestParameterHelper;
|
||||
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
|
||||
this.dropdownReadPlatformService = dropdownReadPlatformService;
|
||||
this.calendarWrapperService = calendarWrapperService;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{calendarId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveCalendar(@PathParam("calendarId") final Long calendarId, @PathParam("entityType") final String entityType, @PathParam("entityId") final Long entityId, @Context final UriInfo uriInfo) {
|
||||
public String retrieveCalendar(@PathParam("calendarId") final Long calendarId, @PathParam("entityType") final String entityType,
|
||||
@PathParam("entityId") final Long entityId, @Context final UriInfo uriInfo) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
|
||||
final Integer entityTypeId = CalendarEntityType.valueOf(entityType.toUpperCase()).getValue();
|
||||
CalendarData calendarData = this.readPlatformService.retrieveCalendar(calendarId, entityId, entityTypeId);
|
||||
|
||||
//Include recurring date details
|
||||
calendarData = handleRecurringDate(calendarData);
|
||||
|
||||
// Include recurring date details
|
||||
calendarData = handleRecurringDate(calendarData);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
if(settings.isTemplate()){
|
||||
calendarData = handleTemplate(calendarData);
|
||||
if (settings.isTemplate()) {
|
||||
calendarData = handleTemplate(calendarData);
|
||||
}
|
||||
return this.toApiJsonSerializer.serialize(settings, calendarData, this.RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
@@ -108,11 +107,11 @@ public class CalendarsApiResource {
|
||||
@Context final UriInfo uriInfo) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
|
||||
|
||||
|
||||
final Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
|
||||
|
||||
|
||||
Collection<CalendarData> calendarsData = new ArrayList<CalendarData>();
|
||||
|
||||
|
||||
if (!associationParameters.isEmpty()) {
|
||||
if (associationParameters.contains("parentCalendars")) {
|
||||
calendarsData.addAll(this.readPlatformService.retrieveParentCalendarsByEntity(entityId,
|
||||
@@ -120,12 +119,12 @@ public class CalendarsApiResource {
|
||||
}
|
||||
}
|
||||
|
||||
calendarsData.addAll(this.readPlatformService.retrieveCalendarsByEntity(entityId, CalendarEntityType.valueOf(entityType.toUpperCase())
|
||||
.getValue()));
|
||||
calendarsData.addAll(this.readPlatformService.retrieveCalendarsByEntity(entityId,
|
||||
CalendarEntityType.valueOf(entityType.toUpperCase()).getValue()));
|
||||
|
||||
//Add recurring dates
|
||||
// Add recurring dates
|
||||
calendarsData = handleRecurringDates(calendarsData);
|
||||
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, calendarsData, this.RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
@@ -198,17 +197,18 @@ public class CalendarsApiResource {
|
||||
|
||||
private CalendarData handleRecurringDate(final CalendarData calendarData){
|
||||
if(!calendarData.isRepeating()) return calendarData;
|
||||
final Collection<LocalDate> recurringDates = this.calendarWrapperService.getNextRecurrencesList(calendarData);
|
||||
|
||||
final Collection<LocalDate> recurringDates = CalendarHelper.getRecurringDates(calendarData.getRecurrence(), calendarData.getStartDate(), calendarData.getEndDate());
|
||||
return new CalendarData(calendarData, recurringDates);
|
||||
}
|
||||
|
||||
private Collection<CalendarData> handleRecurringDates(final Collection<CalendarData> calendarsData){
|
||||
|
||||
private Collection<CalendarData> handleRecurringDates(final Collection<CalendarData> calendarsData) {
|
||||
Collection<CalendarData> recuCalendarsData = new ArrayList<CalendarData>();
|
||||
|
||||
|
||||
for (CalendarData calendarData : calendarsData) {
|
||||
recuCalendarsData.add(handleRecurringDate(calendarData));
|
||||
}
|
||||
|
||||
|
||||
return recuCalendarsData;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -267,7 +267,7 @@ public class Calendar extends AbstractAuditableCustom<AppUser, Long> {
|
||||
return this.secondReminder;
|
||||
}
|
||||
|
||||
private LocalDate getStartDateLocalDate() {
|
||||
public LocalDate getStartDateLocalDate() {
|
||||
LocalDate startDateLocalDate = null;
|
||||
if (this.startDate != null) {
|
||||
startDateLocalDate = LocalDate.fromDateFields(this.startDate);
|
||||
@@ -275,7 +275,7 @@ public class Calendar extends AbstractAuditableCustom<AppUser, Long> {
|
||||
return startDateLocalDate;
|
||||
}
|
||||
|
||||
private LocalDate getEndDateLocalDate() {
|
||||
public LocalDate getEndDateLocalDate() {
|
||||
LocalDate endDateLocalDate = null;
|
||||
if (this.endDate != null) {
|
||||
endDateLocalDate = LocalDate.fromDateFields(this.endDate);
|
||||
|
||||
+8
@@ -29,12 +29,20 @@ public class CalendarInstance extends AbstractPersistable<Long> {
|
||||
this.entityTypeId = entityTypeId;
|
||||
}
|
||||
|
||||
protected CalendarInstance(){
|
||||
|
||||
}
|
||||
|
||||
public static CalendarInstance fromJson(final Calendar calendar, final JsonCommand command) {
|
||||
final Long entityId = command.getSupportedEntityId();
|
||||
final Integer entityTypeId = CalendarEntityType.valueOf(command.getSupportedEntityType().toUpperCase()).getValue();
|
||||
return new CalendarInstance(calendar, entityId, entityTypeId);
|
||||
}
|
||||
|
||||
public void updateCalendar(final Calendar calendar){
|
||||
this.calendar = calendar;
|
||||
}
|
||||
|
||||
public Calendar getCalendar() {
|
||||
return this.calendar;
|
||||
}
|
||||
|
||||
+4
@@ -1,5 +1,7 @@
|
||||
package org.mifosplatform.portfolio.calendar.domain;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
@@ -7,4 +9,6 @@ public interface CalendarInstanceRepository extends JpaRepository<CalendarInstan
|
||||
|
||||
CalendarInstance findByCalendarAndEntityIdAndEntityTypeId(Long calendarId, Long entityId, Integer entityTypeId);
|
||||
|
||||
Collection<CalendarInstance> findByEntityIdAndEntityTypeId(Long entityId, Integer entityTypeId);
|
||||
|
||||
}
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 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.exception;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException} thrown when Calendar resources are not found.
|
||||
*/
|
||||
public class NotValidRecurringDateException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public NotValidRecurringDateException(String postFix, String defaultUserMessage, Object... defaultUserMessageArgs) {
|
||||
super("error.msg.calendar." + postFix + ".not.valid.recurring.date", defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -142,7 +142,7 @@ public class CalendarCommandFromApiJsonDeserializer extends AbstractFromApiJsonD
|
||||
if(repeating){
|
||||
final String recurrence = this.fromApiJsonHelper.extractStringNamed(CALENDAR_SUPPORTED_PARAMETERS.RECURRENCE.getValue(), element);
|
||||
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.RECURRENCE.getValue()).value(recurrence).notNull()
|
||||
.notExceedingLengthOf(100).isValidateRecurringRule(recurrence);
|
||||
.notExceedingLengthOf(100).isValidRecurringRule(recurrence);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ public class CalendarCommandFromApiJsonDeserializer extends AbstractFromApiJsonD
|
||||
if(repeating){
|
||||
final String recurrence = this.fromApiJsonHelper.extractStringNamed(CALENDAR_SUPPORTED_PARAMETERS.RECURRENCE.getValue(), element);
|
||||
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.RECURRENCE.getValue()).value(recurrence).notNull()
|
||||
.notExceedingLengthOf(100).isValidateRecurringRule(recurrence);
|
||||
.notExceedingLengthOf(100).isValidRecurringRule(recurrence);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+178
@@ -0,0 +1,178 @@
|
||||
package org.mifosplatform.portfolio.calendar.service;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import net.fortuna.ical4j.model.Date;
|
||||
import net.fortuna.ical4j.model.DateList;
|
||||
import net.fortuna.ical4j.model.DateTime;
|
||||
import net.fortuna.ical4j.model.Recur;
|
||||
import net.fortuna.ical4j.model.ValidationException;
|
||||
import net.fortuna.ical4j.model.WeekDay;
|
||||
import net.fortuna.ical4j.model.WeekDayList;
|
||||
import net.fortuna.ical4j.model.parameter.Value;
|
||||
import net.fortuna.ical4j.model.property.RRule;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.mifosplatform.infrastructure.core.service.DateUtils;
|
||||
|
||||
public class CalendarHelper {
|
||||
|
||||
public static LocalDate getNextRecurringDate(final String recurringRule, final LocalDate seedDate, final LocalDate startDate) {
|
||||
|
||||
final Recur recur = CalendarHelper.getICalRecur(recurringRule);
|
||||
|
||||
if (recur == null) { return null; }
|
||||
|
||||
final Date nextRecDate = recur.getNextDate(new Date(seedDate.toDate()), new Date(startDate.toDate()));
|
||||
return nextRecDate == null ? null : new LocalDate(nextRecDate);
|
||||
}
|
||||
|
||||
public static Collection<LocalDate> getRecurringDates(final String recurringRule, final LocalDate seedDate, final LocalDate endDate) {
|
||||
|
||||
final LocalDate periodStartDate = DateUtils.getLocalDateOfTenant();
|
||||
final LocalDate periodEndDate = (endDate == null) ? DateUtils.getLocalDateOfTenant().plusYears(5) : endDate;
|
||||
return getRecurringDates(recurringRule, seedDate, periodStartDate, periodEndDate);
|
||||
}
|
||||
|
||||
public static Collection<LocalDate> getRecurringDates(final String recurringRule, final LocalDate seedDate,
|
||||
final LocalDate periodStartDate, final LocalDate periodEndDate) {
|
||||
final int maxCount = 15;// Default number of recurring dates
|
||||
return getRecurringDates(recurringRule, seedDate, periodStartDate, periodEndDate, maxCount);
|
||||
}
|
||||
|
||||
public static Collection<LocalDate> getRecurringDates(final String recurringRule, final LocalDate seedDate,
|
||||
final LocalDate periodStartDate, final LocalDate periodEndDate, final int maxCount) {
|
||||
|
||||
final Recur recur = CalendarHelper.getICalRecur(recurringRule);
|
||||
|
||||
if (recur == null) { return null; }
|
||||
|
||||
final Date seed = new Date(seedDate.toDate());
|
||||
final DateTime periodStart = new DateTime(periodStartDate.toDate());
|
||||
final DateTime periodEnd = new DateTime(periodEndDate.toDate());
|
||||
|
||||
final Value value = new Value(Value.DATE.getValue());
|
||||
final DateList recurringDates = recur.getDates(seed, periodStart, periodEnd, value, maxCount);
|
||||
return convertToLocalDateList(recurringDates);
|
||||
}
|
||||
|
||||
private static Collection<LocalDate> convertToLocalDateList(final DateList dates) {
|
||||
|
||||
final Collection<LocalDate> recurringDates = new ArrayList<LocalDate>();
|
||||
|
||||
for (@SuppressWarnings("rawtypes")
|
||||
final Iterator iterator = dates.iterator(); iterator.hasNext();) {
|
||||
final Date date = (Date) iterator.next();
|
||||
recurringDates.add(new LocalDate(date));
|
||||
}
|
||||
|
||||
return recurringDates;
|
||||
}
|
||||
|
||||
public static Recur getICalRecur(final String recurringRule) {
|
||||
|
||||
// Construct RRule
|
||||
try {
|
||||
final RRule rrule = new RRule(recurringRule);
|
||||
rrule.validate();
|
||||
|
||||
final Recur recur = rrule.getRecur();
|
||||
|
||||
return recur;
|
||||
} catch (final ParseException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (final ValidationException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getRRuleReadable(final LocalDate startDate, final String recurringRule) {
|
||||
|
||||
String humanReadable = "";
|
||||
|
||||
RRule rrule;
|
||||
Recur recur = null;
|
||||
try {
|
||||
rrule = new RRule(recurringRule);
|
||||
rrule.validate();
|
||||
recur = rrule.getRecur();
|
||||
} catch (final ValidationException e) {
|
||||
throw new PlatformDataIntegrityException("error.msg.invalid.recurring.rule", "The Recurring Rule value: " + recurringRule
|
||||
+ " is not valid.", "recurrence", recurringRule);
|
||||
} catch (final ParseException e) {
|
||||
throw new PlatformDataIntegrityException("error.msg.recurring.rule.parsing.error",
|
||||
"Error in pasring the Recurring Rule value: " + recurringRule, "recurrence", recurringRule);
|
||||
}
|
||||
|
||||
if (recur == null) { return humanReadable; }
|
||||
|
||||
if (recur.getFrequency().equals(Recur.DAILY)) {
|
||||
if (recur.getInterval() == 1) {
|
||||
humanReadable = "Daily";
|
||||
} else {
|
||||
humanReadable = "Every " + recur.getInterval() + " days";
|
||||
}
|
||||
} else if (recur.getFrequency().equals(Recur.WEEKLY)) {
|
||||
if (recur.getInterval() == 1 || recur.getInterval() == -1) {
|
||||
humanReadable = "Weekly";
|
||||
} else {
|
||||
humanReadable = "Every " + recur.getInterval() + " weeks";
|
||||
}
|
||||
|
||||
humanReadable += " on ";
|
||||
final WeekDayList weekDayList = recur.getDayList();
|
||||
|
||||
for (@SuppressWarnings("rawtypes")
|
||||
final Iterator iterator = weekDayList.iterator(); iterator.hasNext();) {
|
||||
final WeekDay weekDay = (WeekDay) iterator.next();
|
||||
humanReadable += weekDay.getDay();
|
||||
}
|
||||
|
||||
} else if (recur.getFrequency().equals(Recur.MONTHLY)) {
|
||||
if (recur.getInterval() == 1) {
|
||||
humanReadable = "Monthly on day " + startDate.getDayOfMonth();
|
||||
} else {
|
||||
humanReadable = "Every " + recur.getInterval() + " months on day " + startDate.getDayOfMonth();
|
||||
}
|
||||
} else if (recur.getFrequency().equals(Recur.YEARLY)) {
|
||||
if (recur.getInterval() == 1) {
|
||||
humanReadable = "Annually on " + startDate.toString("MMM") + " " + startDate.getDayOfMonth();
|
||||
} else {
|
||||
humanReadable = "Every " + recur.getInterval() + " years on " + startDate.toString("MMM") + " " + startDate.getDayOfMonth();
|
||||
}
|
||||
}
|
||||
|
||||
if (recur.getCount() > 0) {
|
||||
if (recur.getCount() == 1) {
|
||||
humanReadable = "Once";
|
||||
}
|
||||
humanReadable += ", " + recur.getCount() + " times";
|
||||
}
|
||||
|
||||
final Date endDate = recur.getUntil();
|
||||
final LocalDate date = new LocalDate(endDate);
|
||||
final DateTimeFormatter fmt = DateTimeFormat.forPattern("dd MMMM YY");
|
||||
final String formattedDate = date.toString(fmt);
|
||||
if (endDate != null) {
|
||||
humanReadable += ", until " + formattedDate;
|
||||
}
|
||||
|
||||
return humanReadable;
|
||||
}
|
||||
|
||||
public static boolean isValidRedurringDate(final String recurringRule, final LocalDate seedDate, final LocalDate date){
|
||||
|
||||
final Collection<LocalDate> recurDate = getRecurringDates(recurringRule, seedDate, date, date.plusDays(1), 1);
|
||||
return (recurDate == null || recurDate.isEmpty()) ? false : true;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -67,7 +67,7 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
|
||||
if(remindById != null) remindBy = CalendarEnumerations.calendarRemindBy(remindById);
|
||||
final Integer firstReminder = rs.getInt("firstReminder");
|
||||
final Integer secondReminder = rs.getInt("secondReminder");
|
||||
final String humanReadable = CalendarWrapperService.getRRuleReadable(startDate, recurrence);
|
||||
final String humanReadable = CalendarHelper.getRRuleReadable(startDate, recurrence);
|
||||
|
||||
final LocalDate createdDate = JdbcSupport.getLocalDate(rs, "createdDate");
|
||||
final LocalDate lastUpdatedDate = JdbcSupport.getLocalDate(rs, "updatedDate");
|
||||
|
||||
-187
@@ -1,187 +0,0 @@
|
||||
package org.mifosplatform.portfolio.calendar.service;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import net.fortuna.ical4j.model.Date;
|
||||
import net.fortuna.ical4j.model.DateList;
|
||||
import net.fortuna.ical4j.model.DateTime;
|
||||
import net.fortuna.ical4j.model.Recur;
|
||||
import net.fortuna.ical4j.model.ValidationException;
|
||||
import net.fortuna.ical4j.model.WeekDay;
|
||||
import net.fortuna.ical4j.model.WeekDayList;
|
||||
import net.fortuna.ical4j.model.parameter.Value;
|
||||
import net.fortuna.ical4j.model.property.RRule;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.mifosplatform.portfolio.calendar.data.CalendarData;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class CalendarWrapperService {
|
||||
|
||||
public CalendarWrapperService() {
|
||||
|
||||
}
|
||||
|
||||
public LocalDate getNextRecurrence(final CalendarData calendar) {
|
||||
|
||||
final Recur recur = getRecur(calendar);
|
||||
|
||||
if (recur == null) { return null; }
|
||||
|
||||
final Date nextRecDate = recur.getNextDate(new Date(calendar.getStartDate().toDate()), new Date(calendar.getStartDate().toDate()));
|
||||
final LocalDate lNextRecDate = new LocalDate(nextRecDate);
|
||||
return lNextRecDate;
|
||||
}
|
||||
|
||||
public Collection<LocalDate> getNextRecurrencesList(final CalendarData calendarData) {
|
||||
int maxCount = 10;//Default number of recurring dates
|
||||
LocalDate periodStartDate = new LocalDate(Calendar.getInstance().getTime());
|
||||
return getNextRecurrencesList(calendarData, maxCount, periodStartDate);
|
||||
}
|
||||
|
||||
public Collection<LocalDate> getNextRecurrencesList(final CalendarData calendarData, int maxCount, final LocalDate psDate) {
|
||||
final Recur recur = getRecur(calendarData);
|
||||
|
||||
if (recur == null) { return null; }
|
||||
|
||||
final Date seed = new Date(calendarData.getStartDate().toDate());
|
||||
final DateTime periodStart = new DateTime(psDate.toDate());
|
||||
|
||||
Calendar endDate = Calendar.getInstance();
|
||||
endDate.setTime(calendarData.getStartDate().toDate());
|
||||
|
||||
if(calendarData.getEndDate() != null){
|
||||
endDate.setTime(calendarData.getEndDate().toDate());
|
||||
}else{
|
||||
endDate.add(Calendar.YEAR, 5);
|
||||
}
|
||||
|
||||
final DateTime periodEnd = new DateTime(endDate.getTime());
|
||||
|
||||
final Value value = new Value(Value.DATE.getValue());
|
||||
|
||||
return getRecurringDates(recur.getDates(seed, periodStart, periodEnd, value, maxCount));
|
||||
}
|
||||
|
||||
private Collection<LocalDate> getRecurringDates(final DateList dates) {
|
||||
|
||||
Collection<LocalDate> recurringDates = new ArrayList<LocalDate>();
|
||||
|
||||
for (@SuppressWarnings("rawtypes")
|
||||
final Iterator iterator = dates.iterator(); iterator.hasNext();) {
|
||||
final Date date = (Date) iterator.next();
|
||||
recurringDates.add(new LocalDate(date));
|
||||
}
|
||||
|
||||
return recurringDates;
|
||||
}
|
||||
|
||||
private Recur getRecur(final CalendarData calendar) {
|
||||
if (!calendar.isRepeating()) {
|
||||
// throw exception or return null
|
||||
// throw new CalendarNotReccuring();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Construct RRule
|
||||
try {
|
||||
final RRule rrule = new RRule(calendar.getRecurrence());
|
||||
rrule.validate();
|
||||
|
||||
final Recur recur = rrule.getRecur();
|
||||
|
||||
return recur;
|
||||
} catch (final ParseException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (final ValidationException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getRRuleReadable(final LocalDate startDate, final String recurringRule){
|
||||
|
||||
String humanReadable = "";
|
||||
|
||||
RRule rrule;
|
||||
Recur recur = null;
|
||||
try {
|
||||
rrule = new RRule(recurringRule);
|
||||
rrule.validate();
|
||||
recur = rrule.getRecur();
|
||||
} catch (ValidationException e) {
|
||||
throw new PlatformDataIntegrityException("error.msg.invalid.recurring.rule",
|
||||
"The Recurring Rule value: " + recurringRule + " is not valid.", "recurrence", recurringRule);
|
||||
} catch (ParseException e) {
|
||||
throw new PlatformDataIntegrityException("error.msg.recurring.rule.parsing.error",
|
||||
"Error in pasring the Recurring Rule value: " + recurringRule , "recurrence", recurringRule);
|
||||
}
|
||||
|
||||
if(recur == null) return humanReadable;
|
||||
|
||||
|
||||
if(recur.getFrequency().equals(Recur.DAILY)){
|
||||
if(recur.getInterval() == 1){
|
||||
humanReadable = "Daily";
|
||||
}else{
|
||||
humanReadable = "Every " + recur.getInterval() + " days";
|
||||
}
|
||||
}else if(recur.getFrequency().equals(Recur.WEEKLY)){
|
||||
if(recur.getInterval() == 1 || recur.getInterval() == -1){
|
||||
humanReadable = "Weekly";
|
||||
}else{
|
||||
humanReadable = "Every " + recur.getInterval() + " weeks";
|
||||
}
|
||||
|
||||
humanReadable += " on ";
|
||||
WeekDayList weekDayList = recur.getDayList();
|
||||
|
||||
for (@SuppressWarnings("rawtypes")
|
||||
Iterator iterator = weekDayList.iterator(); iterator.hasNext();) {
|
||||
WeekDay weekDay = (WeekDay) iterator.next();
|
||||
humanReadable += weekDay.getDay();
|
||||
}
|
||||
|
||||
}else if(recur.getFrequency().equals(Recur.MONTHLY)){
|
||||
if(recur.getInterval() == 1){
|
||||
humanReadable = "Monthly on day " + startDate.getDayOfMonth();
|
||||
}else{
|
||||
humanReadable = "Every " + recur.getInterval() + " months on day " + startDate.getDayOfMonth();
|
||||
}
|
||||
}else if(recur.getFrequency().equals(Recur.YEARLY)){
|
||||
if(recur.getInterval() == 1){
|
||||
humanReadable = "Annually on " + startDate.toString("MMM") + " " + startDate.getDayOfMonth();
|
||||
}else{
|
||||
humanReadable = "Every " + recur.getInterval() + " years on " + startDate.toString("MMM") + " " + startDate.getDayOfMonth();
|
||||
}
|
||||
}
|
||||
|
||||
if(recur.getCount() > 0){
|
||||
if(recur.getCount() == 1){
|
||||
humanReadable = "Once";
|
||||
}
|
||||
humanReadable += ", " + recur.getCount() + " times";
|
||||
}
|
||||
|
||||
Date endDate = recur.getUntil();
|
||||
LocalDate date = new LocalDate(endDate);
|
||||
DateTimeFormatter fmt = DateTimeFormat.forPattern("dd MMMM YY");
|
||||
String formattedDate = date.toString( fmt );
|
||||
if(endDate != null){
|
||||
humanReadable += ", until " + formattedDate;
|
||||
}
|
||||
|
||||
return humanReadable;
|
||||
}
|
||||
}
|
||||
+6
@@ -483,6 +483,12 @@ public final class LoanApplicationCommandFromApiJsonHelper {
|
||||
.notExceedingLengthOf(500);
|
||||
}
|
||||
|
||||
final String calendarIdParameterName = "calendarId";
|
||||
if (fromApiJsonHelper.parameterExists(calendarIdParameterName, element)) {
|
||||
final Long calendarId = fromApiJsonHelper.extractLongNamed(calendarIdParameterName, element);
|
||||
baseDataValidator.reset().parameter(calendarIdParameterName).value(calendarId).ignoreIfNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
// charges
|
||||
final String chargesParameterName = "charges";
|
||||
if (element.isJsonObject() && fromApiJsonHelper.parameterExists(chargesParameterName, element)) {
|
||||
|
||||
+84
-6
@@ -11,6 +11,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonQuery;
|
||||
@@ -20,6 +21,14 @@ import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityExce
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.mifosplatform.organisation.staff.domain.Staff;
|
||||
import org.mifosplatform.portfolio.calendar.domain.Calendar;
|
||||
import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType;
|
||||
import org.mifosplatform.portfolio.calendar.domain.CalendarInstance;
|
||||
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.exception.NotValidRecurringDateException;
|
||||
import org.mifosplatform.portfolio.calendar.service.CalendarHelper;
|
||||
import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
|
||||
import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory;
|
||||
import org.mifosplatform.portfolio.client.domain.Client;
|
||||
@@ -80,6 +89,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
private final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory;
|
||||
private final LoanSummaryWrapper loanSummaryWrapper;
|
||||
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
||||
private final CalendarRepository calendarRepository;
|
||||
private final CalendarInstanceRepository calendarInstanceRepository;
|
||||
|
||||
@Autowired
|
||||
public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final FromJsonHelper fromJsonHelper,
|
||||
@@ -90,7 +101,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
final NoteRepository noteRepository, final LoanScheduleCalculationPlatformService calculationPlatformService,
|
||||
final ClientRepository clientRepository, final LoanProductRepository loanProductRepository,
|
||||
final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory, final LoanSummaryWrapper loanSummaryWrapper,
|
||||
final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory) {
|
||||
final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
|
||||
final CalendarRepository calendarRepository, final CalendarInstanceRepository calendarInstanceRepository) {
|
||||
this.context = context;
|
||||
this.fromJsonHelper = fromJsonHelper;
|
||||
this.loanApplicationTransitionApiJsonValidator = loanApplicationTransitionApiJsonValidator;
|
||||
@@ -107,6 +119,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
this.accountIdentifierGeneratorFactory = accountIdentifierGeneratorFactory;
|
||||
this.loanSummaryWrapper = loanSummaryWrapper;
|
||||
this.loanRepaymentScheduleTransactionProcessorFactory = loanRepaymentScheduleTransactionProcessorFactory;
|
||||
this.calendarRepository = calendarRepository;
|
||||
this.calendarInstanceRepository = calendarInstanceRepository;
|
||||
}
|
||||
|
||||
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
|
||||
@@ -122,6 +136,17 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
|
||||
this.fromApiJsonDeserializer.validateForCreate(command.json());
|
||||
|
||||
|
||||
//validate dates against calendar recurring dates
|
||||
//get calendar
|
||||
final Long calendarId = command.longValueOfParameterNamed("calendarId");
|
||||
Calendar calendar = null;
|
||||
if(calendarId != null && calendarId != 0){
|
||||
calendar = this.calendarRepository.findOne(calendarId);
|
||||
if(calendar == null) { throw new CalendarNotFoundException(calendarId); }
|
||||
validateCalendarDates(command, calendar);
|
||||
}
|
||||
|
||||
final Loan newLoanApplication = loanAssembler.assembleFrom(command, currentUser);
|
||||
|
||||
this.loanRepository.save(newLoanApplication);
|
||||
@@ -138,11 +163,11 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
Note note = Note.loanNote(newLoanApplication, submittedOnNote);
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
|
||||
//get calendar
|
||||
final Long calendarId = command.longValueOfParameterNamed("calendarId");
|
||||
if(calendarId != null && calendarId != 0){
|
||||
//Save calendar instance
|
||||
|
||||
//Save calendar instance
|
||||
if(calendar != null){
|
||||
CalendarInstance calendarInstance = new CalendarInstance(calendar, newLoanApplication.getId(), CalendarEntityType.LOANS.getValue());
|
||||
this.calendarInstanceRepository.save(calendarInstance);
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
@@ -164,6 +189,14 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
|
||||
this.fromApiJsonDeserializer.validateForModify(command.json());
|
||||
|
||||
final Long calendarId = command.longValueOfParameterNamed("calendarId");
|
||||
Calendar calendar = null;
|
||||
if(calendarId != null && calendarId != 0){
|
||||
calendar = this.calendarRepository.findOne(calendarId);
|
||||
if(calendar == null) { throw new CalendarNotFoundException(calendarId); }
|
||||
validateCalendarDates(command, calendar);
|
||||
}
|
||||
|
||||
final Loan existingLoanApplication = retrieveLoanBy(loanId);
|
||||
|
||||
if (!existingLoanApplication.isSubmittedAndPendingApproval()) { throw new LoanApplicationNotInSubmittedAndPendingApprovalStateCannotBeModified(
|
||||
@@ -254,6 +287,23 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
|
||||
List<CalendarInstance> ciList = (List<CalendarInstance>) this.calendarInstanceRepository.findByEntityIdAndEntityTypeId(loanId, CalendarEntityType.LOANS.getValue());
|
||||
if(calendar != null){
|
||||
|
||||
//For loans, allow to attach only one calendar instance per loan
|
||||
if(ciList != null && !ciList.isEmpty()){
|
||||
CalendarInstance calendarInstance = ciList.get(0);
|
||||
if(calendarInstance.getCalendar().getId() != calendar.getId()){
|
||||
calendarInstance.updateCalendar(calendar);
|
||||
this.calendarInstanceRepository.saveAndFlush(calendarInstance);
|
||||
}
|
||||
}
|
||||
|
||||
}else if(ciList != null && !ciList.isEmpty()){
|
||||
CalendarInstance calendarInstance = ciList.get(0);
|
||||
this.calendarInstanceRepository.delete(calendarInstance);
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withEntityId(loanId) //
|
||||
.withOfficeId(existingLoanApplication.getOfficeId()) //
|
||||
@@ -454,4 +504,32 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
loan.setHelpers(defaultLoanLifecycleStateMachine(), this.loanSummaryWrapper, this.loanRepaymentScheduleTransactionProcessorFactory);
|
||||
return loan;
|
||||
}
|
||||
|
||||
private void validateCalendarDates(final JsonCommand command, final Calendar calendar) {
|
||||
|
||||
// Validate disbursement date and first repayment dates matches calendar
|
||||
// date
|
||||
final LocalDate edDate = command.localDateValueOfParameterNamed("expectedDisbursementDate");
|
||||
if (edDate != null) {
|
||||
|
||||
if (!CalendarHelper.isValidRedurringDate(calendar.getRecurrence(), calendar.getStartDateLocalDate(), edDate)) {
|
||||
final String errorMessage = "The expected disbursement date :" + (edDate.toString()) + " does not fall on a meeting date.";
|
||||
throw new NotValidRecurringDateException("loan.expected.disbursement.date", errorMessage, edDate.toString(),
|
||||
calendar.getTitle());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final LocalDate repStartingDate = command.localDateValueOfParameterNamed("repaymentsStartingFromDate");
|
||||
if (repStartingDate != null) {
|
||||
|
||||
if (!CalendarHelper.isValidRedurringDate(calendar.getRecurrence(), calendar.getStartDateLocalDate(), repStartingDate)) {
|
||||
final String errorMessage = "The First repayment date :" + (repStartingDate.toString()) + " do not fall a meeting date.";
|
||||
throw new NotValidRecurringDateException("loan.first.repayment.date", errorMessage, repStartingDate.toString(),
|
||||
calendar.getTitle());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user