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.endow.document.validation.impl;
017    
018    import java.sql.Date;
019    import java.sql.Timestamp;
020    
021    import org.apache.commons.lang.StringUtils;
022    import org.apache.log4j.Logger;
023    import org.kuali.kfs.module.endow.EndowKeyConstants;
024    import org.kuali.kfs.module.endow.businessobject.Tickler;
025    import org.kuali.kfs.module.endow.businessobject.TicklerRecipientGroup;
026    import org.kuali.kfs.module.endow.businessobject.TicklerRecipientPrincipal;
027    import org.kuali.kfs.module.endow.document.service.KEMService;
028    import org.kuali.kfs.module.endow.document.service.impl.FrequencyCodeServiceImpl;
029    import org.kuali.kfs.sys.context.SpringContext;
030    import org.kuali.rice.kns.document.MaintenanceDocument;
031    import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
032    import org.kuali.rice.kns.util.DateUtils;
033    import org.kuali.rice.kns.util.GlobalVariables;
034    
035    /**
036     * This TicklerRule class implements the Business rules associated with the Tickler.
037     * 
038     * @author Tapan S Mokha
039     * @version 1.0
040     */
041    public class TicklerRule extends MaintenanceDocumentRuleBase {
042    
043        private static Logger log = org.apache.log4j.Logger.getLogger(TicklerRule.class);
044        
045        private Tickler newTickler;
046        private Tickler oldTickler;
047    
048        /**
049         * This method initializes the old and new Tickler.
050         * 
051         * @param document
052         */
053        private void initializeAttributes(MaintenanceDocument document) {
054            if (newTickler == null) {
055                newTickler = (Tickler) document.getNewMaintainableObject().getBusinessObject();
056            }
057            if (oldTickler == null) {
058                oldTickler = (Tickler) document.getOldMaintainableObject().getBusinessObject();
059            }
060            
061        }
062    
063        /**
064         * This method validates the Tickler before being submitted
065         *  1. Check Frequency Or Next Due Date presence and validity.
066         *  2. Check if at-least one Principal Or Group is present and active.
067         *  3. Mark the Termination Date on DeActivation of tickler.
068         *  4. Check Termination Date if the Tickler is marked as inactive and if > Todays' Date.
069         *  
070         * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
071         */
072        @Override
073        protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document)
074        {
075            super.processCustomSaveDocumentBusinessRules(document);
076            
077            if(GlobalVariables.getMessageMap().getErrorCount() == 0)
078            {
079                //Initialize Tickler Attributes
080                initializeAttributes(document);
081                
082                //Rule 4 & 5: Ensure either Frequency or Next Tickler Date are entered.
083                checkFrequencyOrNextDueDateRequirement();
084                
085                //Rule 16 only applies is Tickler is active.
086                if(getNewTickler().isActive())
087                {
088                    //Rule 16 Ensure atleast one active Principal or Group is attached to the Tickler.
089                    checkPrincipalOrGroup();
090                }
091                
092                //Rule 9: Put Termination date as system date if tickler is deactivated.
093                markTerminationDateonDeActivation();
094    
095                //Rule 23: Check Term date is greater than today if tickler is reactivated.
096                checkTerminationDateonActivation();
097                
098                return GlobalVariables.getMessageMap().getErrorCount() == 0;
099            }
100            else
101            {
102                return false;
103            }
104        }
105        
106        /**
107         * Marks the Termination Date on DeActivation of tickler.     
108        */
109        private void markTerminationDateonDeActivation() 
110        {
111            //The tickler was deactivated
112            if( getOldTickler().isActive() && !getNewTickler().isActive())
113            {
114                //Obtain System Date
115                KEMService kemService = (KEMService) SpringContext.getBean(KEMService.class);
116                getNewTickler().setTerminationDate(kemService.getCurrentDate());
117            }
118        }
119        
120        /**
121         * Checks Termination Date if the Tickler is marked as inactive and if > Todays' Date.
122         */
123        private void checkTerminationDateonActivation() 
124        {
125            //Only if Tickler is being reactivated & termintaion field is not null
126            if( getNewTickler().isActive() && !getOldTickler().isActive() && getNewTickler().getTerminationDate() != null )
127            {
128                //Obtain System Date
129                KEMService kemService = (KEMService) SpringContext.getBean(KEMService.class);
130                
131                //Ensure Termination date is after today, non inclusive
132                if( DateUtils.getDifferenceInDays(new Timestamp(kemService.getCurrentSystemProcessDateObject().getTime()),new Timestamp(getNewTickler().getTerminationDate().getTime())) < 1 )
133                {
134                    putGlobalError(EndowKeyConstants.TicklerConstants.ERROR_TICKLER_TERMINATION_DATE_GREATER_SYSTEMDATE);
135                }
136            }
137       }
138        
139        /**
140         * Checks Tickler's Frequency Or Next Due Date presence and validity.
141         */
142        private void checkFrequencyOrNextDueDateRequirement()
143        {
144            //Check whether frequency and next due date are both missing.
145            if( (StringUtils.isEmpty(getNewTickler().getFrequencyCode()) && getNewTickler().getNextDueDate() == null) )
146            {
147                putGlobalError(EndowKeyConstants.TicklerConstants.ERROR_TICKLER_FREQUENCYORNEXTDUEDATEREQUIREMENT);
148            }
149            
150            //Check whether frequency and next due date are both present. If yes, then check if the date matches up with frequency next due date.
151            if( !StringUtils.isEmpty(getNewTickler().getFrequencyCode()) && getNewTickler().getNextDueDate() != null ) 
152            {
153                FrequencyCodeServiceImpl frequencyCodeServiceImpl = (FrequencyCodeServiceImpl) SpringContext.getBean(FrequencyCodeServiceImpl.class);
154                Date date = frequencyCodeServiceImpl.calculateProcessDate(getNewTickler().getFrequencyCode());
155                if( date.toString().compareTo((getNewTickler().getNextDueDate().toString())) != 0 )
156                {
157                    putGlobalError(EndowKeyConstants.TicklerConstants.ERROR_TICKLER_FREQUENCY_NEXTDUEDATE_MISMATCH);
158                }
159            }
160        }
161    
162        /**
163         * Checks if at-least one Principal Or Group is present and active.
164         */
165        private void checkPrincipalOrGroup()
166        {
167            //Check if atleast one principal is active.
168            boolean activePrincipal = false;
169            for(TicklerRecipientPrincipal principal : getNewTickler().getRecipientPrincipals())
170            {
171                if(principal.isActive())
172                {
173                    activePrincipal = true;
174                }
175            }
176            
177            //Check if atleast one group is active.
178            boolean activeGroup = false;
179            for(TicklerRecipientGroup group: getNewTickler().getRecipientGroups())
180            {
181                if(group.isActive())
182                {
183                    activeGroup = true;
184                }
185            }
186            
187            if( !activePrincipal && !activeGroup )
188            {
189                putGlobalError(EndowKeyConstants.TicklerConstants.ERROR_TICKLER_PRINCIPAL_GROUP_REQUIRED);
190            }
191        }
192    
193        public Tickler getNewTickler() {
194            return newTickler;
195        }
196    
197        public void setNewTickler(Tickler newTickler) {
198            this.newTickler = newTickler;
199        }
200    
201        public Tickler getOldTickler() {
202            return oldTickler;
203        }
204    
205        public void setOldTickler(Tickler oldTickler) {
206            this.oldTickler = oldTickler;
207        }
208    
209        
210        
211        
212    }