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.web.struts;
017    
018    import java.util.ArrayList;
019    import java.util.List;
020    import java.util.Map;
021    
022    import javax.servlet.http.HttpServletRequest;
023    
024    import org.apache.commons.lang.StringUtils;
025    import org.kuali.kfs.coa.businessobject.BalanceType;
026    import org.kuali.kfs.coa.service.BalanceTypeService;
027    import org.kuali.kfs.fp.document.JournalVoucherDocument;
028    import org.kuali.kfs.sys.KFSConstants;
029    import org.kuali.kfs.sys.businessobject.SourceAccountingLine;
030    import org.kuali.kfs.sys.context.SpringContext;
031    import org.kuali.rice.kns.util.ObjectUtils;
032    
033    /**
034     * This class is the Struts specific form object that works in conjunction with the pojo utilities to build the UI for the Journal
035     * Voucher Document. This class is unique in that it leverages a helper data structure called the VoucherAccountingLineHelper
036     * because the Journal Voucher, under certain conditions, presents the user with a debit and credit column for amount entry. In
037     * addition, this form class must keep track of the changes between the old and new balance type selection so that the corresponding
038     * action class and make decisions based upon the differences. New accounting lines use specific credit and debit amount fields b/c
039     * the new line is explicitly known; however, already existing accounting lines need to exist within a list with ordering that
040     * matches the accounting lines source list.
041     */
042    public class JournalVoucherForm extends VoucherForm {
043        protected List balanceTypes;
044        protected String originalBalanceType;
045        protected BalanceType selectedBalanceType;
046    
047        /**
048         * Constructs a JournalVoucherForm instance.
049         */
050        public JournalVoucherForm() {
051            super();
052            selectedBalanceType = new BalanceType(KFSConstants.BALANCE_TYPE_ACTUAL);
053            originalBalanceType = "";
054        }
055    
056        @Override
057        protected String getDefaultDocumentTypeName() {
058            return "JV";
059        }
060        
061        /**
062         * Overrides the parent to call super.populate and then to call the two methods that are specific to loading the two select
063         * lists on the page. In addition, this also makes sure that the credit and debit amounts are filled in for situations where
064         * validation errors occur and the page reposts.
065         * 
066         * @see org.kuali.rice.kns.web.struts.pojo.PojoForm#populate(javax.servlet.http.HttpServletRequest)
067         */
068        @Override
069        public void populate(HttpServletRequest request) {
070            super.populate(request);
071            populateBalanceTypeListForRendering();
072        }
073    
074        /**
075         * Override the parent, to push the chosen accounting period and balance type down into the source accounting line object. In
076         * addition, check the balance type to see if it's the "External Encumbrance" balance and alter the encumbrance update code on
077         * the accounting line appropriately.
078         * 
079         * @see org.kuali.rice.kns.web.struts.form.KualiTransactionalDocumentFormBase#populateSourceAccountingLine(org.kuali.rice.kns.bo.SourceAccountingLine)
080         */
081        @Override
082        public void populateSourceAccountingLine(SourceAccountingLine sourceLine, String accountingLinePropertyName, Map parameterMap) {
083            super.populateSourceAccountingLine(sourceLine, accountingLinePropertyName, parameterMap);
084            populateSourceAccountingLineEncumbranceCode(sourceLine);
085        }
086    
087        /**
088         * Sets the encumbrance code of the line based on the balance type.
089         * 
090         * @param sourceLine - line to set code on
091         */
092        protected void populateSourceAccountingLineEncumbranceCode(SourceAccountingLine sourceLine) {
093            BalanceType selectedBalanceType = getSelectedBalanceType();
094            if (ObjectUtils.isNotNull(selectedBalanceType) && StringUtils.isNotBlank(selectedBalanceType.getCode())) {
095                sourceLine.setBalanceTyp(selectedBalanceType);
096                sourceLine.setBalanceTypeCode(selectedBalanceType.getCode());
097    
098                // set the encumbrance update code appropriately
099                if (KFSConstants.BALANCE_TYPE_EXTERNAL_ENCUMBRANCE.equals(selectedBalanceType.getCode())) {
100                    sourceLine.setEncumbranceUpdateCode(KFSConstants.JOURNAL_VOUCHER_ENCUMBRANCE_UPDATE_CODE_BALANCE_TYPE_EXTERNAL_ENCUMBRANCE);
101                }
102                else {
103                    sourceLine.setEncumbranceUpdateCode(null);
104                }
105            }
106            else {
107                // it's the first time in, the form will be empty the first time in
108                // set up default selection value
109                selectedBalanceType = SpringContext.getBean(BalanceTypeService.class).getBalanceTypeByCode(KFSConstants.BALANCE_TYPE_ACTUAL);
110                setSelectedBalanceType(selectedBalanceType);
111                setOriginalBalanceType(selectedBalanceType.getCode());
112    
113                sourceLine.setEncumbranceUpdateCode(null);
114            }
115        }
116    
117        /**
118         * This method retrieves the list of valid balance types to display.
119         * 
120         * @return List
121         */
122        public List getBalanceTypes() {
123            return balanceTypes;
124        }
125    
126        /**
127         * This method sets the selected balance type.
128         * 
129         * @return BalanceTyp
130         */
131        public BalanceType getSelectedBalanceType() {
132            return selectedBalanceType;
133        }
134    
135        /**
136         * This method retrieves the selected balance type.
137         * 
138         * @param selectedBalanceType
139         */
140        public void setSelectedBalanceType(BalanceType selectedBalanceType) {
141            this.selectedBalanceType = selectedBalanceType;
142        }
143    
144        /**
145         * This method sets the list of valid balance types to display.
146         * 
147         * @param balanceTypes
148         */
149        public void setBalanceTypes(List balanceTypes) {
150            this.balanceTypes = balanceTypes;
151        }
152    
153        /**
154         * This method returns the journal voucher document associated with this form.
155         * 
156         * @return Returns the journalVoucherDocument.
157         */
158        public JournalVoucherDocument getJournalVoucherDocument() {
159            return (JournalVoucherDocument) getTransactionalDocument();
160        }
161    
162        /**
163         * This method sets the journal voucher document associated with this form.
164         * 
165         * @param journalVoucherDocument The journalVoucherDocument to set.
166         */
167        public void setJournalVoucherDocument(JournalVoucherDocument journalVoucherDocument) {
168            setDocument(journalVoucherDocument);
169        }
170    
171        /**
172         * This method retrieves the originalBalanceType attribute.
173         * 
174         * @return String
175         */
176        public String getOriginalBalanceType() {
177            return originalBalanceType;
178        }
179    
180        /**
181         * This method sets the originalBalanceType attribute.
182         * 
183         * @param changedBalanceType
184         */
185        public void setOriginalBalanceType(String changedBalanceType) {
186            this.originalBalanceType = changedBalanceType;
187        }
188    
189        /**
190         * This method retrieves all of the balance types in the system and prepares them to be rendered in a dropdown UI component.
191         */
192        protected void populateBalanceTypeListForRendering() {
193            // grab the list of valid balance types
194            ArrayList balanceTypes = new ArrayList(SpringContext.getBean(BalanceTypeService.class).getAllBalanceTypes());
195    
196            // set into the form for rendering
197            this.setBalanceTypes(balanceTypes);
198    
199            String selectedBalanceTypeCode = getSelectedBalanceType().getCode();
200            if (StringUtils.isBlank(selectedBalanceTypeCode)) {
201                selectedBalanceTypeCode = KFSConstants.BALANCE_TYPE_ACTUAL;
202            }
203    
204            setSelectedBalanceType(getPopulatedBalanceTypeInstance(selectedBalanceTypeCode));
205            getJournalVoucherDocument().setBalanceTypeCode(selectedBalanceTypeCode);
206        }
207    
208        /**
209         * This method will fully populate a balance type given the passed in code, by calling the business object service that
210         * retrieves the rest of the instances' information.
211         * 
212         * @param balanceTypeCode
213         * @return BalanceTyp
214         */
215        protected BalanceType getPopulatedBalanceTypeInstance(String balanceTypeCode) {
216            // now we have to get the code and the name of the original and new balance types
217            BalanceTypeService bts = SpringContext.getBean(BalanceTypeService.class);
218            return bts.getBalanceTypeByCode(balanceTypeCode);
219        }
220    
221        /**
222         * If the balance type is an offset generation balance type, then the user is able to enter the amount as either a debit or a
223         * credit, otherwise, they only need to deal with the amount field in this case we always need to update the underlying bo so
224         * that the debit/credit code along with the amount, is properly set.
225         */
226        protected void populateCreditAndDebitAmounts() {
227            if (isSelectedBalanceTypeFinancialOffsetGenerationIndicator()) {
228                super.populateCreditAndDebitAmounts();
229            }
230        }
231    
232        /**
233         * This is a convenience helper method that is used several times throughout this action class to determine if the selected
234         * balance type contained within the form instance is a financial offset generation balance type or not.
235         * 
236         * @return boolean True if it is an offset generation balance type, false otherwise.
237         */
238        protected boolean isSelectedBalanceTypeFinancialOffsetGenerationIndicator() {
239            return getPopulatedBalanceTypeInstance(getSelectedBalanceType().getCode()).isFinancialOffsetGenerationIndicator();
240        }
241    }