001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.kfs.module.ar.document.validation.impl; 017 018 import java.sql.Date; 019 import java.sql.Timestamp; 020 import java.util.Calendar; 021 import java.util.HashMap; 022 import java.util.List; 023 import java.util.Map; 024 025 import org.apache.commons.lang.StringUtils; 026 import org.apache.log4j.Logger; 027 import org.kuali.kfs.module.ar.ArConstants; 028 import org.kuali.kfs.module.ar.ArKeyConstants; 029 import org.kuali.kfs.module.ar.ArPropertyConstants; 030 import org.kuali.kfs.module.ar.businessobject.InvoiceRecurrence; 031 import org.kuali.kfs.module.ar.document.CustomerInvoiceDocument; 032 import org.kuali.kfs.module.ar.document.service.InvoiceRecurrenceDocumentService; 033 import org.kuali.kfs.sys.context.SpringContext; 034 import org.kuali.rice.kew.exception.WorkflowException; 035 import org.kuali.rice.kns.document.MaintenanceDocument; 036 import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase; 037 import org.kuali.rice.kns.service.BusinessObjectService; 038 import org.kuali.rice.kns.service.DateTimeService; 039 import org.kuali.rice.kns.service.DocumentService; 040 import org.kuali.rice.kns.service.ParameterService; 041 import org.kuali.rice.kns.util.DateUtils; 042 import org.kuali.rice.kns.util.ObjectUtils; 043 import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument; 044 045 public class InvoiceRecurrenceRule extends MaintenanceDocumentRuleBase { 046 protected static Logger LOG = org.apache.log4j.Logger.getLogger(InvoiceRecurrenceRule.class); 047 protected InvoiceRecurrence oldInvoiceRecurrence; 048 protected InvoiceRecurrence newInvoiceRecurrence; 049 050 protected DateTimeService dateTimeService; 051 052 @Override 053 public void setupConvenienceObjects() { 054 oldInvoiceRecurrence = (InvoiceRecurrence) super.getOldBo(); 055 newInvoiceRecurrence = (InvoiceRecurrence) super.getNewBo(); 056 } 057 058 @Override 059 protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) { 060 061 boolean success; 062 java.sql.Date today = getDateTimeService().getCurrentSqlDateMidnight(); 063 Date currentDate = getDateTimeService().getCurrentSqlDate(); 064 065 066 success = checkIfInvoiceIsApproved(newInvoiceRecurrence.getInvoiceNumber()); 067 /* 068 success &= checkIfRecurrenceMaintenanceAlreadyExists(newInvoiceRecurrence); 069 success &= validateDocumentRecurrenceBeginDate(newInvoiceRecurrence); 070 */ 071 success &= validateDocumentRecurrenceEndDate(newInvoiceRecurrence.getDocumentRecurrenceBeginDate(), 072 newInvoiceRecurrence.getDocumentRecurrenceEndDate()); 073 success &= validateIfBothEndDateAndTotalRecurrenceNumberAreEntered(newInvoiceRecurrence.getDocumentRecurrenceBeginDate(), 074 newInvoiceRecurrence.getDocumentRecurrenceEndDate(), 075 newInvoiceRecurrence.getDocumentTotalRecurrenceNumber(), 076 newInvoiceRecurrence.getDocumentRecurrenceIntervalCode()); 077 success &= validateEndDateOrTotalNumberofRecurrences(newInvoiceRecurrence.getDocumentRecurrenceEndDate(), 078 newInvoiceRecurrence.getDocumentTotalRecurrenceNumber()); 079 success &= validateMaximumNumberOfRecurrences(newInvoiceRecurrence.getDocumentTotalRecurrenceNumber(), 080 newInvoiceRecurrence.getDocumentRecurrenceIntervalCode()); 081 return success; 082 } 083 084 @Override 085 protected boolean processCustomSaveDocumentBusinessRules(MaintenanceDocument document) { 086 // always return true even if there are business rule failures. 087 processCustomRouteDocumentBusinessRules(document); 088 return true; 089 } 090 091 /** 092 * Check if an Invoice Recurrence Maintenance document already exists. 093 */ 094 protected boolean checkIfRecurrenceMaintenanceAlreadyExists(InvoiceRecurrence newInvoiceRecurrence) { 095 boolean success = true; 096 Map<String, String> criteria = new HashMap<String, String>(); 097 criteria.put("invoiceNumber", newInvoiceRecurrence.getInvoiceNumber()); 098 InvoiceRecurrence invoiceRecurrence = (InvoiceRecurrence) SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(InvoiceRecurrence.class, criteria); 099 if (ObjectUtils.isNotNull(invoiceRecurrence) && !(oldInvoiceRecurrence.equals(invoiceRecurrence))) { 100 putFieldError(ArPropertyConstants.InvoiceRecurrenceFields.RECURRING_INVOICE_NUMBER, ArKeyConstants.ERROR_MAINTENANCE_DOCUMENT_ALREADY_EXISTS); 101 success = false; 102 } 103 return success; 104 } 105 /** 106 * Validate if the invoice has an approved status. 107 */ 108 protected boolean checkIfInvoiceIsApproved(String recurrenceInvoiceNumber) { 109 boolean success = true; 110 111 if (ObjectUtils.isNull(recurrenceInvoiceNumber)) { 112 return success; 113 } 114 115 CustomerInvoiceDocument customerInvoiceDocument = null; 116 if (!SpringContext.getBean(DocumentService.class).documentExists(recurrenceInvoiceNumber)) { 117 putFieldError(ArPropertyConstants.InvoiceRecurrenceFields.RECURRING_INVOICE_NUMBER, ArKeyConstants.ERROR_INVOICE_DOES_NOT_EXIST); 118 success = false; 119 } 120 else { 121 try { 122 customerInvoiceDocument = (CustomerInvoiceDocument)SpringContext.getBean(DocumentService.class).getByDocumentHeaderId(recurrenceInvoiceNumber); 123 } catch (WorkflowException e){ 124 } 125 if (ObjectUtils.isNotNull(customerInvoiceDocument)) { 126 KualiWorkflowDocument workflowDocument = customerInvoiceDocument.getDocumentHeader().getWorkflowDocument(); 127 if (!(workflowDocument.stateIsApproved())) { 128 putFieldError(ArPropertyConstants.InvoiceRecurrenceFields.RECURRING_INVOICE_NUMBER, ArKeyConstants.ERROR_RECURRING_INVOICE_NUMBER_MUST_BE_APPROVED); 129 success = false; 130 } 131 } 132 } 133 return success; 134 } 135 /** 136 * Validate Begin Date. 137 */ 138 protected boolean validateDocumentRecurrenceBeginDate(InvoiceRecurrence newInvoiceRecurrence) { 139 boolean success = true; 140 if (ObjectUtils.isNull(newInvoiceRecurrence.getDocumentRecurrenceBeginDate())) { 141 return success; 142 } 143 Timestamp currentDate = new Timestamp(getDateTimeService().getCurrentDate().getTime()); 144 Timestamp beginDateTimestamp = new Timestamp(newInvoiceRecurrence.getDocumentRecurrenceBeginDate().getTime()); 145 if (beginDateTimestamp.before(currentDate) || beginDateTimestamp.equals(currentDate)) { 146 putFieldError(ArPropertyConstants.InvoiceRecurrenceFields.INVOICE_RECURRENCE_BEGIN_DATE, ArKeyConstants.ERROR_INVOICE_RECURRENCE_BEGIN_DATE_EARLIER_THAN_TODAY); 147 return false; 148 } 149 return success; 150 } 151 /** 152 * Validate End Date. 153 */ 154 public boolean validateDocumentRecurrenceEndDate(Date newInvoiceRecurrenceBeginDate, Date newInvoiceRecurrenceEndDate) { 155 boolean success = true; 156 if (!SpringContext.getBean(InvoiceRecurrenceDocumentService.class).isValidRecurrenceEndDate(newInvoiceRecurrenceBeginDate, newInvoiceRecurrenceEndDate)) { 157 putFieldError(ArPropertyConstants.InvoiceRecurrenceFields.INVOICE_RECURRENCE_END_DATE, ArKeyConstants.ERROR_END_DATE_EARLIER_THAN_BEGIN_DATE); 158 return false; 159 } 160 return success; 161 } 162 /** 163 * This method checks that End Date and Total Recurrence Number are valid when both are entered. 164 * 165 * @param document the maintenance document 166 * @return 167 */ 168 protected boolean validateIfBothEndDateAndTotalRecurrenceNumberAreEntered(Date recurrenceBeginDate, Date recurrenceEndDate, Integer totalRecurrenceNumber, String recurrenceIntervalCode) { 169 170 if (ObjectUtils.isNull(recurrenceBeginDate) || 171 ObjectUtils.isNull(recurrenceIntervalCode) || 172 ObjectUtils.isNull(recurrenceEndDate) || 173 ObjectUtils.isNull(totalRecurrenceNumber)) { 174 return true; 175 } 176 177 Calendar beginCalendar = Calendar.getInstance(); 178 beginCalendar.setTime(recurrenceBeginDate); 179 Date beginDate = recurrenceBeginDate; 180 Calendar endCalendar = Calendar.getInstance(); 181 endCalendar.setTime(recurrenceEndDate); 182 Date endDate = recurrenceEndDate; 183 Calendar nextCalendar = Calendar.getInstance(); 184 Date nextDate = beginDate; 185 186 int totalRecurrences = 0; 187 int addCounter = 0; 188 String intervalCode = recurrenceIntervalCode; 189 if (intervalCode.equals("M")) { 190 addCounter = 1; 191 } 192 if (intervalCode.equals("Q")) { 193 addCounter = 3; 194 } 195 /* perform this loop while begin_date is less than or equal to end_date */ 196 while (!(beginDate.after(endDate))){ 197 beginCalendar.setTime(beginDate); 198 beginCalendar.add(Calendar.MONTH, addCounter); 199 beginDate = DateUtils.convertToSqlDate(beginCalendar.getTime()); 200 totalRecurrences++; 201 202 nextDate = beginDate; 203 nextCalendar.setTime(nextDate); 204 nextCalendar.add(Calendar.MONTH, addCounter); 205 nextDate = DateUtils.convertToSqlDate(nextCalendar.getTime()); 206 if (endDate.after(beginDate) && endDate.before(nextDate)) { 207 totalRecurrences++; 208 break; 209 } 210 } 211 if (totalRecurrences != totalRecurrenceNumber.intValue()) { 212 putFieldError(ArPropertyConstants.InvoiceRecurrenceFields.INVOICE_RECURRENCE_END_DATE, ArKeyConstants.ERROR_END_DATE_AND_TOTAL_NUMBER_OF_RECURRENCES_NOT_VALID); 213 return false; 214 } 215 216 return true; 217 } 218 /** 219 * Validate that either End Date or Total Number of Recurrences must be entered. 220 */ 221 protected boolean validateEndDateOrTotalNumberofRecurrences(Date recurrenceEndDate, Integer totalRecurrenceNumber) { 222 boolean success = true; 223 if (ObjectUtils.isNull(recurrenceEndDate) && ObjectUtils.isNull(totalRecurrenceNumber)) { 224 putFieldError(ArPropertyConstants.InvoiceRecurrenceFields.INVOICE_RECURRENCE_END_DATE, ArKeyConstants.ERROR_END_DATE_OR_TOTAL_NUMBER_OF_RECURRENCES); 225 return false; 226 } 227 return success; 228 } 229 230 /** 231 * Total number of recurrences may not be greater than the number defined in system parameter MAXIMUM_RECURRENCES_BY_INTERVAL. 232 */ 233 protected boolean validateMaximumNumberOfRecurrences(Integer totalRecurrenceNumber, String recurrenceIntervalCode) { 234 235 if (ObjectUtils.isNull(recurrenceIntervalCode) || 236 ObjectUtils.isNull(totalRecurrenceNumber)) { 237 return true; 238 } 239 boolean success = true; 240 Integer maximumRecurrencesByInterval; 241 if (ObjectUtils.isNotNull(recurrenceIntervalCode)) { 242 List<String> maximumRecurrences = SpringContext.getBean(ParameterService.class).getParameterValues(InvoiceRecurrence.class, ArConstants.MAXIMUM_RECURRENCES_BY_INTERVAL, recurrenceIntervalCode); 243 if (maximumRecurrences.size() > 0 && StringUtils.isNotBlank(maximumRecurrences.get(0))) { 244 maximumRecurrencesByInterval = Integer.valueOf(maximumRecurrences.get(0)); 245 if (totalRecurrenceNumber > maximumRecurrencesByInterval) { 246 putFieldError(ArPropertyConstants.InvoiceRecurrenceFields.INVOICE_RECURRENCE_TOTAL_RECURRENCE_NUMBER, ArKeyConstants.ERROR_TOTAL_NUMBER_OF_RECURRENCES_GREATER_THAN_ALLOWED, maximumRecurrences.get(0)); 247 return false; 248 } 249 } 250 } 251 return success; 252 } 253 254 }