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.text.ParseException;
020    import java.util.ArrayList;
021    import java.util.HashMap;
022    import java.util.List;
023    import java.util.Map;
024    
025    import org.kuali.kfs.coa.document.validation.impl.MaintenancePreRulesBase;
026    import org.kuali.kfs.module.endow.EndowParameterKeyConstants;
027    import org.kuali.kfs.module.endow.businessobject.KEMID;
028    import org.kuali.kfs.module.endow.businessobject.KemidAgreement;
029    import org.kuali.kfs.module.endow.businessobject.KemidAuthorizations;
030    import org.kuali.kfs.module.endow.businessobject.KemidBenefittingOrganization;
031    import org.kuali.kfs.module.endow.businessobject.KemidCombineDonorStatement;
032    import org.kuali.kfs.module.endow.businessobject.KemidDonorStatement;
033    import org.kuali.kfs.module.endow.businessobject.KemidFee;
034    import org.kuali.kfs.module.endow.businessobject.KemidPayoutInstruction;
035    import org.kuali.kfs.module.endow.businessobject.KemidReportGroup;
036    import org.kuali.kfs.module.endow.businessobject.KemidSourceOfFunds;
037    import org.kuali.kfs.module.endow.businessobject.KemidSpecialInstruction;
038    import org.kuali.kfs.module.endow.businessobject.KemidUseCriteria;
039    import org.kuali.kfs.module.endow.document.service.KEMService;
040    import org.kuali.kfs.sys.context.SpringContext;
041    import org.kuali.rice.kns.document.MaintenanceDocument;
042    import org.kuali.rice.kns.service.DateTimeService;
043    import org.kuali.rice.kns.service.ParameterService;
044    import org.kuali.rice.kns.util.KNSConstants;
045    import org.kuali.rice.kns.util.KualiInteger;
046    import org.kuali.rice.kns.util.ObjectUtils;
047    
048    /**
049     * This KemidPreRule class implements the pre rules for the Kemid BO.
050     */
051    public class KemidPreRule extends MaintenancePreRulesBase {
052    
053        private KEMID oldKemid;
054        private KEMID newKemid;
055    
056        /**
057         * @see org.kuali.kfs.coa.document.validation.impl.MaintenancePreRulesBase#doCustomPreRules(org.kuali.rice.kns.document.MaintenanceDocument)
058         */
059        protected boolean doCustomPreRules(MaintenanceDocument maintenanceDocument) {
060            boolean preRulesOK = true;
061            ParameterService parameterService = SpringContext.getBean(ParameterService.class);
062    
063            String kemidValueSystemParam = parameterService.getParameterValue(KEMID.class, EndowParameterKeyConstants.KEMID_VALUE);
064    
065            setupConvenienceObjects(maintenanceDocument);
066    
067            setAgreementsIds();
068            setSourceOfFundsSeq();
069            updateBenefittingOrgs(maintenanceDocument);
070            updateAuthorizations(maintenanceDocument);
071            setPayoutInstructionsSeq();
072            setUseCriteriaSeq();
073            setFeeMethodSequence();
074            setReportGroupSequence();
075            setSpecialInstructionSeq();
076            setDonorStatementsSeq();
077            setCombineDonorSeq();
078    
079            return preRulesOK;
080        }
081    
082        /**
083         * Sets the ID for all the new agreements as the next sequencial number.
084         */
085        private void setAgreementsIds() {
086            List<KemidAgreement> oldAgreements = new ArrayList<KemidAgreement>();
087            List<KemidAgreement> newAgreements = new ArrayList<KemidAgreement>();
088    
089    
090            for (KemidAgreement kemidAgreement : newKemid.getKemidAgreements()) {
091                if (kemidAgreement.isNewCollectionRecord()) {
092                    newAgreements.add(kemidAgreement);
093                }
094                else {
095                    oldAgreements.add(kemidAgreement);
096                }
097            }
098    
099            int sequenceStart = oldAgreements.size();
100    
101            for (KemidAgreement agreement : newAgreements) {
102                agreement.setAgreementId(new KualiInteger(++sequenceStart));
103            }
104    
105        }
106    
107        /**
108         * Sets the source of fund sequence number for all the new sources of funds.
109         */
110        private void setSourceOfFundsSeq() {
111            List<KemidSourceOfFunds> oldKemidSourcesOfFunds = new ArrayList<KemidSourceOfFunds>();
112            List<KemidSourceOfFunds> newKemidSourcesOfFunds = new ArrayList<KemidSourceOfFunds>();
113    
114    
115            for (KemidSourceOfFunds kemidSourceOfFunds : newKemid.getKemidSourcesOfFunds()) {
116                if (kemidSourceOfFunds.isNewCollectionRecord()) {
117                    newKemidSourcesOfFunds.add(kemidSourceOfFunds);
118                }
119                else {
120                    oldKemidSourcesOfFunds.add(kemidSourceOfFunds);
121                }
122            }
123    
124            int sequenceStart = oldKemidSourcesOfFunds.size();
125    
126            for (KemidSourceOfFunds kemidSourceOfFunds : newKemidSourcesOfFunds) {
127                kemidSourceOfFunds.setKemidFundSourceSequenceNumber(new KualiInteger(++sequenceStart));
128            }
129    
130        }
131    
132        /**
133         * Sets the benefitting organization sequence number for all the new benefitting organizations.
134         */
135        private void setBenefittingOrgsSeq() {
136            List<KemidBenefittingOrganization> oldKemidBenefittingOrgs = new ArrayList<KemidBenefittingOrganization>();
137            List<KemidBenefittingOrganization> newKemidBenefittingOrgs = new ArrayList<KemidBenefittingOrganization>();
138    
139    
140            for (KemidBenefittingOrganization kemidBenefittingOrg : newKemid.getKemidBenefittingOrganizations()) {
141                if (kemidBenefittingOrg.isNewCollectionRecord()) {
142                    newKemidBenefittingOrgs.add(kemidBenefittingOrg);
143                }
144                else {
145                    oldKemidBenefittingOrgs.add(kemidBenefittingOrg);
146                }
147            }
148    
149            int sequenceStart = oldKemidBenefittingOrgs.size();
150    
151            for (KemidBenefittingOrganization kemidBenefittingOrg : newKemidBenefittingOrgs) {
152                kemidBenefittingOrg.setBenefittingOrgSeqNumber(new KualiInteger(++sequenceStart));
153            }
154    
155        }
156    
157        /**
158         * Sets the benefitting organization last change date to the current date if the benefit percent changed. This method should
159         * only be called after the setBenefittingOrgsSeq method is called.
160         * 
161         * @param maintenanceDocument
162         */
163        private void setBenefittingOrgsLastChangeDate(MaintenanceDocument maintenanceDocument) {
164    
165            KEMService kemService = SpringContext.getBean(KEMService.class);
166            DateTimeService dateTimeService = SpringContext.getBean(DateTimeService.class);
167    
168            if (KNSConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceDocument.getNewMaintainableObject().getMaintenanceAction())) {
169                if (newKemid.getKemidBenefittingOrganizations().size() != 0) {
170    
171                    Map<KualiInteger, KemidBenefittingOrganization> oldKemidBenefittingOrganizations = new HashMap<KualiInteger, KemidBenefittingOrganization>();
172    
173                    if (oldKemid.getKemidBenefittingOrganizations().size() != 0) {
174                        for (KemidBenefittingOrganization benefittingOrganization : oldKemid.getKemidBenefittingOrganizations()) {
175                            oldKemidBenefittingOrganizations.put(benefittingOrganization.getBenefittingOrgSeqNumber(), benefittingOrganization);
176                        }
177    
178                    }
179    
180                    for (KemidBenefittingOrganization benefittingOrganization : newKemid.getKemidBenefittingOrganizations()) {
181                        KemidBenefittingOrganization oldBenefittingOrg = oldKemidBenefittingOrganizations.get(benefittingOrganization.getBenefittingOrgSeqNumber());
182    
183                        boolean isBenefitPctChanged = false;
184                        if (ObjectUtils.isNotNull(oldBenefittingOrg)) {
185                            isBenefitPctChanged = (benefittingOrganization.getBenefitPrecent() == null && oldBenefittingOrg.getBenefitPrecent() != null) || (benefittingOrganization.getBenefitPrecent() != null && oldBenefittingOrg.getBenefitPrecent() == null) || (benefittingOrganization.getBenefitPrecent() != null && oldBenefittingOrg.getBenefitPrecent() != null && benefittingOrganization.getBenefitPrecent().compareTo(oldBenefittingOrg.getBenefitPrecent()) != 0);
186    
187    
188                        }
189    
190                        if (isBenefitPctChanged || benefittingOrganization.isNewCollectionRecord()) {
191                            Date lastChangeDate;
192                            try {
193                                lastChangeDate = dateTimeService.convertToSqlDate(kemService.getCurrentSystemProcessDate());
194                                benefittingOrganization.setLastChangeDate(lastChangeDate);
195                            }
196                            catch (ParseException ex) {
197                                // do nothing
198                            }
199    
200                        }
201                    }
202                }
203            }
204    
205        }
206    
207        /**
208         * Updates the necessary fields on the Benefitting organizations like the sequence numbers and the last change date.
209         * 
210         * @param maintenanceDocument
211         */
212        private void updateBenefittingOrgs(MaintenanceDocument maintenanceDocument) {
213            // the order in which these methods are called should be preserved
214            setBenefittingOrgsSeq();
215            setBenefittingOrgsLastChangeDate(maintenanceDocument);
216        }
217    
218        /**
219         * Sets the Authorizations sequence number for all the new Authorizations.
220         */
221        private void setAuthorizationsSeqNbr() {
222            List<KemidAuthorizations> oldKemidAuthorizations = new ArrayList<KemidAuthorizations>();
223            List<KemidAuthorizations> newKemidAuthorizations = new ArrayList<KemidAuthorizations>();
224    
225    
226            for (KemidAuthorizations kemidAuthorizations : newKemid.getKemidAuthorizations()) {
227                if (kemidAuthorizations.isNewCollectionRecord()) {
228                    newKemidAuthorizations.add(kemidAuthorizations);
229                }
230                else {
231                    oldKemidAuthorizations.add(kemidAuthorizations);
232                }
233            }
234    
235            int sequenceStart = oldKemidAuthorizations.size();
236    
237            for (KemidAuthorizations kemidAuthorizations : newKemidAuthorizations) {
238                kemidAuthorizations.setRoleSequenceNumber(new KualiInteger(++sequenceStart));
239            }
240    
241        }
242    
243        /**
244         * Updates the necessary fields on the Authorizations like the sequence numbers and the role termination date.
245         * 
246         * @param maintenanceDocument
247         */
248        private void updateAuthorizations(MaintenanceDocument maintenanceDocument) {
249            // the order in which these methods are called should be preserved
250            setAuthorizationsSeqNbr();
251            setAuthorizationsTerminationDate(maintenanceDocument);
252        }
253    
254        /**
255         * Sets the role termination date to current date if authorization has been inactivated.
256         * 
257         * @param maintenanceDocument
258         */
259        private void setAuthorizationsTerminationDate(MaintenanceDocument maintenanceDocument) {
260            KEMService kemService = SpringContext.getBean(KEMService.class);
261            DateTimeService dateTimeService = SpringContext.getBean(DateTimeService.class);
262    
263            if (KNSConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceDocument.getNewMaintainableObject().getMaintenanceAction())) {
264                if (newKemid.getKemidAuthorizations().size() != 0) {
265    
266                    Map<KualiInteger, KemidAuthorizations> oldKemidAuthorizations = new HashMap<KualiInteger, KemidAuthorizations>();
267    
268                    if (oldKemid.getKemidAuthorizations().size() != 0) {
269                        for (KemidAuthorizations authorization : oldKemid.getKemidAuthorizations()) {
270                            oldKemidAuthorizations.put(authorization.getRoleSequenceNumber(), authorization);
271                        }
272                    }
273    
274                    for (KemidAuthorizations authorization : newKemid.getKemidAuthorizations()) {
275                        KemidAuthorizations oldAuthorization = oldKemidAuthorizations.get(authorization.getRoleSequenceNumber());
276    
277                        boolean isActiveIndChanged = false;
278                        if (ObjectUtils.isNotNull(oldAuthorization)) {
279                            isActiveIndChanged = (!authorization.isActive() && oldAuthorization.isActive());
280    
281                        }
282    
283                        if (isActiveIndChanged) {
284                            authorization.setRoleTerminationDate(kemService.getCurrentDate());
285                        }
286                    }
287                }
288            }
289        }
290    
291        /**
292         * Sets the payout instructions sequence number for all the new payout instructions.
293         */
294        private void setPayoutInstructionsSeq() {
295            List<KemidPayoutInstruction> oldKemidPayoutInstructions = new ArrayList<KemidPayoutInstruction>();
296            List<KemidPayoutInstruction> newKemidPayoutInstructions = new ArrayList<KemidPayoutInstruction>();
297    
298    
299            for (KemidPayoutInstruction kemidPayoutInstruction : newKemid.getKemidPayoutInstructions()) {
300                if (kemidPayoutInstruction.isNewCollectionRecord()) {
301                    newKemidPayoutInstructions.add(kemidPayoutInstruction);
302                }
303                else {
304                    oldKemidPayoutInstructions.add(kemidPayoutInstruction);
305                }
306            }
307    
308            int sequenceStart = oldKemidPayoutInstructions.size();
309    
310            for (KemidPayoutInstruction kemidPayoutInstruction : newKemidPayoutInstructions) {
311                kemidPayoutInstruction.setPayoutIncomeSequenceNumber(new KualiInteger(++sequenceStart));
312            }
313    
314        }
315    
316        /**
317         * Sets the use criteria sequence number for all the new sources of funds.
318         */
319        private void setUseCriteriaSeq() {
320            List<KemidUseCriteria> oldKemidUseCriteria = new ArrayList<KemidUseCriteria>();
321            List<KemidUseCriteria> newKemidUseCriteria = new ArrayList<KemidUseCriteria>();
322    
323    
324            for (KemidUseCriteria useCriteria : newKemid.getKemidUseCriteria()) {
325                if (useCriteria.isNewCollectionRecord()) {
326                    newKemidUseCriteria.add(useCriteria);
327                }
328                else {
329                    oldKemidUseCriteria.add(useCriteria);
330                }
331            }
332    
333            int sequenceStart = oldKemidUseCriteria.size();
334    
335            for (KemidUseCriteria useCriteria : newKemidUseCriteria) {
336                useCriteria.setUseCriteriaSeq(new KualiInteger(++sequenceStart));
337            }
338    
339        }
340    
341        /**
342         * Sets the fee method sequence for all the new fees as the next sequencial number.
343         */
344        private void setFeeMethodSequence() {
345            List<KemidFee> oldFees = new ArrayList<KemidFee>();
346            List<KemidFee> newFees = new ArrayList<KemidFee>();
347    
348    
349            for (KemidFee kemidFee : newKemid.getKemidFees()) {
350                if (kemidFee.isNewCollectionRecord()) {
351                    newFees.add(kemidFee);
352                }
353                else {
354                    oldFees.add(kemidFee);
355                }
356            }
357    
358            int sequenceStart = oldFees.size();
359    
360            for (KemidFee fee : newFees) {
361                fee.setFeeMethodSeq(new KualiInteger(++sequenceStart));
362            }
363    
364        }
365    
366        /**
367         * Sets the fee method sequence for all the new fees as the next sequencial number.
368         */
369        private void setReportGroupSequence() {
370            List<KemidReportGroup> oldReportGroups = new ArrayList<KemidReportGroup>();
371            List<KemidReportGroup> newReportGroups = new ArrayList<KemidReportGroup>();
372    
373    
374            for (KemidReportGroup kemidReportGroup : newKemid.getKemidReportGroups()) {
375                if (kemidReportGroup.isNewCollectionRecord()) {
376                    newReportGroups.add(kemidReportGroup);
377                }
378                else {
379                    oldReportGroups.add(kemidReportGroup);
380                }
381            }
382    
383            int sequenceStart = oldReportGroups.size();
384    
385            for (KemidReportGroup reportGroup : newReportGroups) {
386                reportGroup.setCombineGroupSeq(new KualiInteger(++sequenceStart));
387            }
388    
389        }
390    
391        /**
392         * Sets the special instruction sequence for all the new special instructions as the next sequencial number.
393         */
394        private void setSpecialInstructionSeq() {
395            List<KemidSpecialInstruction> oldSpecialInstructions = new ArrayList<KemidSpecialInstruction>();
396            List<KemidSpecialInstruction> newSpecialInstructions = new ArrayList<KemidSpecialInstruction>();
397    
398    
399            for (KemidSpecialInstruction kemidSpecialInstruction : newKemid.getKemidSpecialInstructions()) {
400                if (kemidSpecialInstruction.isNewCollectionRecord()) {
401                    newSpecialInstructions.add(kemidSpecialInstruction);
402                }
403                else {
404                    oldSpecialInstructions.add(kemidSpecialInstruction);
405                }
406            }
407    
408            int sequenceStart = oldSpecialInstructions.size();
409    
410            for (KemidSpecialInstruction specialInstruction : newSpecialInstructions) {
411                specialInstruction.setInstructionSeq(new KualiInteger(++sequenceStart));
412            }
413    
414        }
415    
416        /**
417         * Sets the donor sequence for all the new donor statements as the next sequencial number.
418         */
419        private void setDonorStatementsSeq() {
420            List<KemidDonorStatement> oldDonorStatement = new ArrayList<KemidDonorStatement>();
421            List<KemidDonorStatement> newDonorStatement = new ArrayList<KemidDonorStatement>();
422    
423    
424            for (KemidDonorStatement donorStatement : newKemid.getKemidDonorStatements()) {
425                if (donorStatement.isNewCollectionRecord()) {
426                    newDonorStatement.add(donorStatement);
427                }
428                else {
429                    oldDonorStatement.add(donorStatement);
430                }
431            }
432    
433            int sequenceStart = oldDonorStatement.size();
434    
435            for (KemidDonorStatement donorStatement : newDonorStatement) {
436                donorStatement.setDonorSeq(new KualiInteger(++sequenceStart));
437            }
438    
439        }
440    
441        /**
442         * Sets the combine donor sequence for all the new combine donor statements as the next sequencial number.
443         */
444        private void setCombineDonorSeq() {
445            List<KemidCombineDonorStatement> oldCombineDonorStatement = new ArrayList<KemidCombineDonorStatement>();
446            List<KemidCombineDonorStatement> newCombineDonorStatement = new ArrayList<KemidCombineDonorStatement>();
447    
448    
449            for (KemidCombineDonorStatement combineDonorStatement : newKemid.getKemidCombineDonorStatements()) {
450                if (combineDonorStatement.isNewCollectionRecord()) {
451                    newCombineDonorStatement.add(combineDonorStatement);
452                }
453                else {
454                    oldCombineDonorStatement.add(combineDonorStatement);
455                }
456            }
457    
458            int sequenceStart = oldCombineDonorStatement.size();
459    
460            for (KemidCombineDonorStatement combineDonorStatement : newCombineDonorStatement) {
461                combineDonorStatement.setCombineDonorSeq(new KualiInteger(++sequenceStart));
462            }
463    
464        }
465    
466        /**
467         * Sets the old and new Kemid values.
468         * 
469         * @param document
470         */
471        private void setupConvenienceObjects(MaintenanceDocument document) {
472    
473            // setup newSecurity convenience objects, make sure all possible sub-objects are populated
474            newKemid = (KEMID) document.getNewMaintainableObject().getBusinessObject();
475            oldKemid = (KEMID) document.getOldMaintainableObject().getBusinessObject();
476            newKemid.refreshNonUpdateableReferences();
477        }
478    
479    }