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 }