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.ld.service.impl;
017    
018    import java.util.Collection;
019    import java.util.Iterator;
020    import java.util.Map;
021    
022    import org.apache.commons.lang.StringUtils;
023    import org.kuali.kfs.gl.Constant;
024    import org.kuali.kfs.module.ld.businessobject.AccountStatusCurrentFunds;
025    import org.kuali.kfs.module.ld.businessobject.LaborLedgerPendingEntry;
026    import org.kuali.kfs.module.ld.businessobject.LedgerBalance;
027    import org.kuali.kfs.module.ld.businessobject.LedgerEntry;
028    import org.kuali.kfs.module.ld.service.LaborInquiryOptionsService;
029    import org.kuali.kfs.module.ld.service.LaborLedgerBalanceService;
030    import org.kuali.kfs.module.ld.service.LaborLedgerPendingEntryService;
031    import org.kuali.kfs.sys.KFSPropertyConstants;
032    import org.kuali.kfs.sys.ObjectUtil;
033    import org.kuali.rice.kns.web.ui.Field;
034    import org.kuali.rice.kns.web.ui.Row;
035    
036    /**
037     * The LaborInquiryOptionsService class is a service that will generate Pending Ledger and Consilidation options for balance
038     * inquiries.
039     */
040    public class LaborInquiryOptionsServiceImpl implements LaborInquiryOptionsService {
041        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(LaborInquiryOptionsServiceImpl.class);
042    
043        private LaborLedgerPendingEntryService laborLedgerPendingEntryService;
044        private LaborLedgerBalanceService laborLedgerBalanceService;
045    
046        /**
047         * @see org.kuali.kfs.module.ld.service.LaborInquiryOptionsService#getConsolidationFieldName()
048         */
049        public String getConsolidationFieldName() {
050            return Constant.CONSOLIDATION_OPTION;
051        }
052    
053        /**
054         * @see org.kuali.kfs.module.ld.service.LaborInquiryOptionsService#getConsolidationField(java.util.Collection)
055         */
056        public Field getConsolidationField(Collection<Row> rows) {
057            for (Row row : rows) {
058                for (Field field : ((Collection<Field>) row.getFields())) {
059                    if (field.getPropertyName().equals(getConsolidationFieldName())) {
060                        return field;
061                    }
062                }
063            }
064            return null;
065        }
066    
067        /**
068         * @see org.kuali.kfs.module.ld.service.LaborInquiryOptionsService#getSelectedPendingEntryOption(java.util.Map)
069         */
070        public String getSelectedPendingEntryOption(Map fieldValues) {
071            // truncate the non-property filed
072            String pendingEntryOption = (String) fieldValues.get(Constant.PENDING_ENTRY_OPTION);
073            fieldValues.remove(Constant.PENDING_ENTRY_OPTION);
074    
075            return pendingEntryOption;
076        }
077    
078        /**
079         * @see org.kuali.kfs.module.ld.service.LaborInquiryOptionsService#getConsolidationOption(java.util.Map)
080         */
081        public String getConsolidationOption(Map fieldValues) {
082            String consolidationOption = (String) fieldValues.get(getConsolidationFieldName());
083            // truncate the non-property filed
084            fieldValues.remove(getConsolidationFieldName());
085            return consolidationOption;
086        }
087    
088        /**
089         * @see org.kuali.kfs.module.ld.service.LaborInquiryOptionsService#isConsolidationSelected(java.util.Map, java.util.Collection)
090         */
091        public boolean isConsolidationSelected(Map fieldValues, Collection<Row> rows) {
092            boolean isConsolidationSelected = isConsolidationSelected(fieldValues);
093    
094            if (!isConsolidationSelected) {
095                Field consolidationField = getConsolidationField(rows);
096                consolidationField.setPropertyValue(Constant.DETAIL);
097            }
098            return isConsolidationSelected;
099        }
100    
101        /**
102         * @see org.kuali.kfs.module.ld.service.LaborInquiryOptionsService#isConsolidationSelected(java.util.Map)
103         */
104        public boolean isConsolidationSelected(Map fieldValues) {
105            String consolidationOption = getConsolidationOption(fieldValues);
106    
107            // detail option would be used
108            if (Constant.DETAIL.equals(consolidationOption)) {
109                return false;
110            }
111    
112            // if the subAccountNumber is specified, detail option could be used
113            // if the subObjectCode is specified, detail option could be used
114            // if the objectTypeCode is specified, detail option could be used
115            if (isDetailDefaultFieldUsed(fieldValues, KFSPropertyConstants.SUB_ACCOUNT_NUMBER) || isDetailDefaultFieldUsed(fieldValues, KFSPropertyConstants.SUB_OBJECT_CODE) || isDetailDefaultFieldUsed(fieldValues, KFSPropertyConstants.OBJECT_TYPE_CODE)) {
116                return false;
117            }
118            return true;
119        }
120    
121        /**
122         * @see org.kuali.kfs.module.ld.service.LaborInquiryOptionsService#updateLedgerBalanceByPendingLedgerEntry(java.util.Collection,
123         *      java.util.Map, java.lang.String, boolean)
124         */
125        public void updateLedgerBalanceByPendingLedgerEntry(Collection<LedgerBalance> balanceCollection, Map fieldValues, String pendingEntryOption, boolean isConsolidated) {
126            // determine if search results need to be updated by pending ledger entries
127            if (Constant.ALL_PENDING_ENTRY.equals(pendingEntryOption)) {
128                updateCollection(balanceCollection, fieldValues, false, isConsolidated, LedgerBalance.class);
129            }
130            else if (Constant.APPROVED_PENDING_ENTRY.equals(pendingEntryOption)) {
131                updateCollection(balanceCollection, fieldValues, true, isConsolidated, LedgerBalance.class);
132            }
133        }
134    
135        /**
136         * @see org.kuali.kfs.module.ld.service.LaborInquiryOptionsService#updateCurrentFundsByPendingLedgerEntry(java.util.Collection,
137         *      java.util.Map, java.lang.String, boolean)
138         */
139        public void updateCurrentFundsByPendingLedgerEntry(Collection<AccountStatusCurrentFunds> balanceCollection, Map fieldValues, String pendingEntryOption, boolean isConsolidated) {
140            // determine if search results need to be updated by pending ledger entries
141            if (Constant.ALL_PENDING_ENTRY.equals(pendingEntryOption)) {
142                updateCollection(balanceCollection, fieldValues, false, isConsolidated, AccountStatusCurrentFunds.class);
143            }
144            else if (Constant.APPROVED_PENDING_ENTRY.equals(pendingEntryOption)) {
145                updateCollection(balanceCollection, fieldValues, true, isConsolidated, AccountStatusCurrentFunds.class);
146            }
147        }
148    
149        /**
150         * @see org.kuali.kfs.module.ld.service.LaborInquiryOptionsService#updateByPendingLedgerEntry(java.util.Collection,
151         *      java.util.Map, java.lang.String, boolean)
152         */
153        public void updateLedgerEntryByPendingLedgerEntry(Collection<LedgerEntry> entryCollection, Map fieldValues, String pendingEntryOption) {
154            // determine if search results need to be updated by pending ledger entries
155            if (Constant.ALL_PENDING_ENTRY.equals(pendingEntryOption)) {
156                updateCollection(entryCollection, fieldValues, false, false, LedgerEntry.class);
157            }
158            else if (Constant.APPROVED_PENDING_ENTRY.equals(pendingEntryOption)) {
159                updateCollection(entryCollection, fieldValues, true, false, LedgerEntry.class);
160            }
161        }
162    
163        /**
164         * update a given collection entry with the pending entry obtained from the given field values and isApproved
165         * 
166         * @param entryCollection the given entry collection
167         * @param fieldValues the given field values
168         * @param isApproved indicate if the resulting pending entry has been approved
169         * @param isConsolidated indicate if the collection entries have been consolidated
170         */
171        protected void updateCollection(Collection entryCollection, Map fieldValues, boolean isApproved, boolean isConsolidated, Class clazz) {
172            // go through the pending entries to update the balance collection
173            Iterator<LaborLedgerPendingEntry> pendingEntryIterator = laborLedgerPendingEntryService.findPendingLedgerEntriesForLedgerBalance(fieldValues, isApproved);
174    
175            while (pendingEntryIterator.hasNext()) {
176                LaborLedgerPendingEntry pendingEntry = pendingEntryIterator.next();
177    
178                // if consolidated, change the following fields into the default values for consolidation
179                if (isConsolidated) {
180                    pendingEntry.setSubAccountNumber(Constant.CONSOLIDATED_SUB_ACCOUNT_NUMBER);
181                    pendingEntry.setFinancialSubObjectCode(Constant.CONSOLIDATED_SUB_OBJECT_CODE);
182                    pendingEntry.setFinancialObjectTypeCode(Constant.CONSOLIDATED_OBJECT_TYPE_CODE);
183                }
184    
185                if (LedgerBalance.class.isAssignableFrom(clazz)) {
186                    try {
187                        LedgerBalance ledgerBalance = laborLedgerBalanceService.findLedgerBalance(entryCollection, pendingEntry);
188                        if (ledgerBalance == null) {
189    
190                            Object newLedgerBalance = clazz.newInstance();
191                            ObjectUtil.buildObject(newLedgerBalance, pendingEntry);
192    
193                            ledgerBalance = (LedgerBalance) newLedgerBalance;
194                            entryCollection.add(ledgerBalance);
195                        }
196                        laborLedgerBalanceService.updateLedgerBalance(ledgerBalance, pendingEntry);
197                        ledgerBalance.getDummyBusinessObject().setConsolidationOption(isConsolidated ? Constant.CONSOLIDATION : Constant.DETAIL);
198                        ledgerBalance.getDummyBusinessObject().setPendingEntryOption(isApproved ? Constant.APPROVED_PENDING_ENTRY : Constant.ALL_PENDING_ENTRY);
199                    }
200                    catch (Exception e) {
201                        LOG.error("cannot create a new object of type: " + clazz.getName() + "/n" + e);
202                    }
203                }
204                else if (LedgerEntry.class.isAssignableFrom(clazz)) {
205                    LedgerEntry ledgerEntry = new LedgerEntry();
206                    ObjectUtil.buildObject(ledgerEntry, pendingEntry);
207    
208                    ledgerEntry.getDummyBusinessObject().setConsolidationOption(isConsolidated ? Constant.CONSOLIDATION : Constant.DETAIL);
209                    ledgerEntry.getDummyBusinessObject().setPendingEntryOption(isApproved ? Constant.APPROVED_PENDING_ENTRY : Constant.ALL_PENDING_ENTRY);
210    
211                    entryCollection.add(ledgerEntry);
212                }
213                else {
214                    LOG.warn("The class, " + clazz.getName() + ", is unregistered with the method.");
215                    return;
216                }
217            }
218        }
219    
220        /**
221         * Determines if any of the fields that require a detail view are used
222         * 
223         * @param fieldValues
224         * @param fieldName
225         */
226        protected boolean isDetailDefaultFieldUsed(Map fieldValues, String fieldName) {
227            return StringUtils.isNotBlank((String) fieldValues.get(fieldName));
228        }
229    
230        /**
231         * Sets the laborLedgerBalanceService attribute value.
232         * 
233         * @param laborLedgerBalanceService The laborLedgerBalanceService to set.
234         */
235        public void setLaborLedgerBalanceService(LaborLedgerBalanceService laborLedgerBalanceService) {
236            this.laborLedgerBalanceService = laborLedgerBalanceService;
237        }
238    
239        /**
240         * Sets the laborLedgerPendingEntryService attribute value.
241         * 
242         * @param laborLedgerPendingEntryService The laborLedgerPendingEntryService to set.
243         */
244        public void setLaborLedgerPendingEntryService(LaborLedgerPendingEntryService laborLedgerPendingEntryService) {
245            this.laborLedgerPendingEntryService = laborLedgerPendingEntryService;
246        }
247    }