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.fp.document.service.impl;
017    
018    import java.util.ArrayList;
019    import java.util.Collection;
020    import java.util.Iterator;
021    import java.util.List;
022    
023    import org.kuali.kfs.fp.businessobject.BudgetAdjustmentAccountingLine;
024    import org.kuali.kfs.fp.document.BudgetAdjustmentDocument;
025    import org.kuali.kfs.fp.document.service.BudgetAdjustmentLaborBenefitsService;
026    import org.kuali.kfs.integration.ld.LaborLedgerBenefitsCalculation;
027    import org.kuali.kfs.integration.ld.LaborLedgerPositionObjectBenefit;
028    import org.kuali.kfs.integration.ld.LaborModuleService;
029    import org.kuali.kfs.sys.businessobject.AccountingLine;
030    import org.kuali.kfs.sys.businessobject.SourceAccountingLine;
031    import org.kuali.kfs.sys.businessobject.TargetAccountingLine;
032    import org.kuali.kfs.sys.context.SpringContext;
033    import org.kuali.rice.kns.service.BusinessObjectService;
034    import org.kuali.rice.kns.util.KualiDecimal;
035    import org.kuali.rice.kns.util.KualiInteger;
036    
037    /**
038     * This is the default implementation of the methods defined by the BudgetAdjustmentLaborBenefitsService. These service performs
039     * methods related to the generation of labor benefit accounting lines for the budget adjustment document.
040     */
041    public class BudgetAdjustmentLaborBenefitsServiceImpl implements BudgetAdjustmentLaborBenefitsService {
042        private BusinessObjectService businessObjectService;
043    
044        /**
045         * This method generated labor benefit accounting lines to be added to the BudgetDocument provided.
046         * 
047         * @param budgetDocument The BudgetDocument to have the new labor benefit accounting lines added to.
048         * @see org.kuali.kfs.fp.document.service.BudgetAdjustmentLaborBenefitsService#generateLaborBenefitsAccountingLines(org.kuali.kfs.fp.document.BudgetAdjustmentDocument)
049         */
050        public void generateLaborBenefitsAccountingLines(BudgetAdjustmentDocument budgetDocument) {
051            Integer fiscalYear = budgetDocument.getPostingYear();
052    
053            List accountingLines = new ArrayList();
054            accountingLines.addAll(budgetDocument.getSourceAccountingLines());
055            accountingLines.addAll(budgetDocument.getTargetAccountingLines());
056    
057            /*
058             * find lines that have labor object codes, then retrieve the benefit calculation records for the object code. Finally, for
059             * each benefit record, create an accounting line with properties set from the original line, but substituted with the
060             * benefit object code and calculated current and base amount.
061             */
062            for (Iterator iter = accountingLines.iterator(); iter.hasNext();) {
063                BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
064    
065                // check if the line was previousely generated benefit line, if so delete and skip
066                if (line.isFringeBenefitIndicator()) {
067                    if (line.isSourceAccountingLine()) {
068                        budgetDocument.getSourceAccountingLines().remove(line);
069                    }
070                    else {
071                        budgetDocument.getTargetAccountingLines().remove(line);
072                    }
073                    continue;
074                }
075    
076                List<BudgetAdjustmentAccountingLine> benefitLines = generateBenefitLines(fiscalYear, line, budgetDocument);
077    
078                for (BudgetAdjustmentAccountingLine benefitLine : benefitLines) {
079                    if (benefitLine.isSourceAccountingLine()) {
080                        budgetDocument.addSourceAccountingLine((SourceAccountingLine) benefitLine);
081                    }
082                    else {
083                        budgetDocument.addTargetAccountingLine((TargetAccountingLine) benefitLine);
084                    }
085                }
086            }
087        }
088    
089        /**
090         * Given a budget adjustment accounting line, generates appropriate fringe benefit lines for the line
091         * 
092         * @param line a line to generate fringe benefit lines for
093         * @return a List of BudgetAdjustmentAccountingLines to add to the document as fringe benefit lines
094         */
095        protected List<BudgetAdjustmentAccountingLine> generateBenefitLines(Integer fiscalYear, BudgetAdjustmentAccountingLine line, BudgetAdjustmentDocument document) {
096            List<BudgetAdjustmentAccountingLine> fringeLines = new ArrayList<BudgetAdjustmentAccountingLine>();
097    
098            try {
099                Collection<LaborLedgerPositionObjectBenefit> objectBenefits = SpringContext.getBean(LaborModuleService.class).retrieveLaborPositionObjectBenefits(fiscalYear, line.getChartOfAccountsCode(), line.getFinancialObjectCode());
100                if (objectBenefits != null) {
101                    for (LaborLedgerPositionObjectBenefit fringeBenefitInformation : objectBenefits) {
102                        // now create and set properties for the benefit line
103                        BudgetAdjustmentAccountingLine benefitLine = null;
104                        if (line.isSourceAccountingLine()) {
105                            benefitLine = (BudgetAdjustmentAccountingLine) document.getSourceAccountingLineClass().newInstance();
106                        }
107                        else {
108                            benefitLine = (BudgetAdjustmentAccountingLine) document.getTargetAccountingLineClass().newInstance();
109                        }
110    
111                        LaborLedgerBenefitsCalculation benefitsCalculation = fringeBenefitInformation.getLaborLedgerBenefitsCalculation();
112    
113                        benefitLine.copyFrom(line);
114                        benefitLine.setFinancialObjectCode(benefitsCalculation.getPositionFringeBenefitObjectCode());
115                        benefitLine.refreshNonUpdateableReferences();
116                        
117                        //convert whole percentage to decimal value (5% to .05)
118                        KualiDecimal fringeBenefitPercent = formatPercentageForMultiplication(benefitsCalculation.getPositionFringeBenefitPercent());
119                        
120                        KualiDecimal benefitCurrentAmount = line.getCurrentBudgetAdjustmentAmount().multiply(fringeBenefitPercent);
121                        benefitLine.setCurrentBudgetAdjustmentAmount(benefitCurrentAmount);
122    
123                        KualiInteger benefitBaseAmount = line.getBaseBudgetAdjustmentAmount().multiply(fringeBenefitPercent);
124                        benefitLine.setBaseBudgetAdjustmentAmount(benefitBaseAmount);
125    
126                        // clear monthly lines per KULEDOCS-1606
127                        benefitLine.clearFinancialDocumentMonthLineAmounts();
128    
129                        // set flag on line so we know it was a generated benefit line and can clear it out later if needed
130                        benefitLine.setFringeBenefitIndicator(true);
131    
132                        fringeLines.add(benefitLine);
133                    }
134                }
135            }
136            catch (InstantiationException ie) {
137                // it's doubtful this catch block or the catch block below are ever accessible, as accounting lines should already have
138                // been generated
139                // for the document. But we can still make it somebody else's problem
140                throw new RuntimeException(ie);
141            }
142            catch (IllegalAccessException iae) {
143                // with some luck we'll pass the buck now sez some other dev "This sucks!" Get your Runtime on!
144                // but really...we'll never make it this far. I promise.
145                throw new RuntimeException(iae);
146            }
147    
148            return fringeLines;
149        }
150    
151    
152        /**
153         * @param budgetDocument
154         * @return
155         * @see org.kuali.kfs.fp.document.service.BudgetAdjustmentLaborBenefitsService#hasLaborObjectCodes(org.kuali.kfs.fp.document.BudgetAdjustmentDocument)
156         */
157        public boolean hasLaborObjectCodes(BudgetAdjustmentDocument budgetDocument) {
158            boolean hasLaborObjectCodes = false;
159    
160            List<AccountingLine> accountingLines = new ArrayList<AccountingLine>();
161            accountingLines.addAll(budgetDocument.getSourceAccountingLines());
162            accountingLines.addAll(budgetDocument.getTargetAccountingLines());
163    
164            Integer fiscalYear = budgetDocument.getPostingYear();
165            LaborModuleService laborModuleService = SpringContext.getBean(LaborModuleService.class);
166    
167            for (AccountingLine line : accountingLines) {
168                if (laborModuleService.hasFringeBenefitProducingObjectCodes(fiscalYear, line.getChartOfAccountsCode(), line.getFinancialObjectCode())) {
169                    hasLaborObjectCodes = true;
170                    break;
171                }
172            }
173    
174            return hasLaborObjectCodes;
175        }
176    
177        
178        protected KualiDecimal formatPercentageForMultiplication(KualiDecimal percent) {
179            return percent.divide(new KualiDecimal(100));
180        }
181    
182        /**
183         * Gets the businessObjectService attribute.
184         * 
185         * @return Returns the businessObjectService.
186         */
187        public BusinessObjectService getBusinessObjectService() {
188            return businessObjectService;
189        }
190    
191        /**
192         * Sets the businessObjectService attribute value.
193         * 
194         * @param businessObjectService The businessObjectService to set.
195         */
196        public void setBusinessObjectService(BusinessObjectService businessObjectService) {
197            this.businessObjectService = businessObjectService;
198        }
199    
200    
201    }