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.ar.document.web.struts;
017    
018    import java.util.ArrayList;
019    import java.util.Collection;
020    import java.util.HashMap;
021    import java.util.Iterator;
022    import java.util.List;
023    import java.util.Map;
024    
025    import javax.servlet.ServletRequest;
026    import javax.servlet.http.HttpServletRequest;
027    
028    import org.apache.commons.lang.StringUtils;
029    import org.apache.log4j.Logger;
030    import org.apache.struts.action.ActionMapping;
031    import org.kuali.kfs.module.ar.businessobject.AccountsReceivableDocumentHeader;
032    import org.kuali.kfs.module.ar.businessobject.InvoicePaidApplied;
033    import org.kuali.kfs.module.ar.businessobject.NonAppliedHolding;
034    import org.kuali.kfs.module.ar.businessobject.NonInvoiced;
035    import org.kuali.kfs.module.ar.businessobject.NonInvoicedDistribution;
036    import org.kuali.kfs.module.ar.document.CashControlDocument;
037    import org.kuali.kfs.module.ar.document.CustomerInvoiceDocument;
038    import org.kuali.kfs.module.ar.document.PaymentApplicationDocument;
039    import org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService;
040    import org.kuali.kfs.sys.KFSConstants;
041    import org.kuali.kfs.sys.context.SpringContext;
042    import org.kuali.kfs.sys.document.web.struts.FinancialSystemTransactionalDocumentFormBase;
043    import org.kuali.rice.kew.exception.WorkflowException;
044    import org.kuali.rice.kim.util.KimConstants;
045    import org.kuali.rice.kns.document.Document;
046    import org.kuali.rice.kns.service.DocumentService;
047    import org.kuali.rice.kns.util.KualiDecimal;
048    import org.kuali.rice.kns.util.ObjectUtils;
049    
050    public class PaymentApplicationDocumentForm extends FinancialSystemTransactionalDocumentFormBase {
051        protected static Logger LOG = org.apache.log4j.Logger.getLogger(PaymentApplicationDocumentForm.class);;
052    
053        protected String selectedInvoiceDocumentNumber;
054        protected String enteredInvoiceDocumentNumber;
055        protected String selectedCustomerNumber;
056        protected KualiDecimal unappliedCustomerAmount;
057        protected PaymentApplicationInvoiceApply selectedInvoiceApplication;
058        protected NonInvoiced nonInvoicedAddLine;
059        protected Integer nextNonInvoicedLineNumber;
060        protected KualiDecimal nonAppliedHoldingAmount;
061        protected String nonAppliedHoldingCustomerNumber;
062    
063        protected List<PaymentApplicationInvoiceApply> invoiceApplications;
064        protected List<CustomerInvoiceDocument> invoices;
065        
066        //  used for non-cash-control pay app docs
067        protected List<PaymentApplicationDocument> nonAppliedControlDocs;
068        protected List<NonAppliedHolding> nonAppliedControlHoldings;
069        protected Map<String,KualiDecimal> nonAppliedControlAllocations;
070        protected Map<String,KualiDecimal> distributionsFromControlDocs;
071        
072        /**
073         * Constructs a PaymentApplicationDocumentForm.java.
074         */
075        @SuppressWarnings("unchecked")
076        public PaymentApplicationDocumentForm() {
077            super();
078            nonInvoicedAddLine = new NonInvoiced();
079            invoices = new ArrayList<CustomerInvoiceDocument>();
080            selectedInvoiceApplication = null;
081            invoiceApplications = new ArrayList<PaymentApplicationInvoiceApply>();
082            nonAppliedControlDocs = new ArrayList<PaymentApplicationDocument>();
083            nonAppliedControlHoldings = new ArrayList<NonAppliedHolding>();
084            nonAppliedControlAllocations = new HashMap<String,KualiDecimal>();
085            distributionsFromControlDocs = new HashMap<String,KualiDecimal>();
086        }
087    
088        @Override
089        protected String getDefaultDocumentTypeName() {
090            return "APP";
091        }
092        
093        @Override
094        public void reset(ActionMapping mapping, ServletRequest request) {
095            super.reset(mapping, request);
096            for (PaymentApplicationInvoiceApply application : invoiceApplications) {
097                application.setQuickApply(false);
098            }
099        }
100    
101        @Override
102        public void populate(HttpServletRequest request) {
103            super.populate(request);
104            
105            // Set the next non-invoiced line number
106            PaymentApplicationDocument paymentApplicationDocument = getPaymentApplicationDocument();
107            if (ObjectUtils.isNotNull(paymentApplicationDocument.getNonInvoicedDistributions())) {
108                for (NonInvoicedDistribution u : paymentApplicationDocument.getNonInvoicedDistributions()) {
109                    if (null == getNextNonInvoicedLineNumber()) {
110                        setNextNonInvoicedLineNumber(u.getFinancialDocumentLineNumber());
111                    } else if (u.getFinancialDocumentLineNumber() > getNextNonInvoicedLineNumber()) {
112                        setNextNonInvoicedLineNumber(u.getFinancialDocumentLineNumber());
113                    }
114                }
115            }
116            
117            if (null == getNextNonInvoicedLineNumber()) {
118                setNextNonInvoicedLineNumber(1);
119            }
120            
121            // This step doesn't affect anything persisted to the database. It allows proper calculation
122            // of amounts for the display.
123            String customerNumber = null;
124            String docId = getDocument().getDocumentNumber();
125            if(ObjectUtils.isNotNull(request.getParameter(KFSConstants.PARAMETER_DOC_ID)) && ObjectUtils.isNull(getDocument().getDocumentNumber())) {
126                // The document hasn't yet been set on the form. Let's look it up manually so that we can get the customer number.
127                docId = request.getParameter(KFSConstants.PARAMETER_DOC_ID).trim();
128                DocumentService documentService = SpringContext.getBean(DocumentService.class);
129                Document d;
130                try {
131                    d = documentService.getByDocumentHeaderId(docId);
132                }
133                catch (WorkflowException e) {
134                    throw new RuntimeException("WorkflowException thrown when trying to load docId [" + docId + "]", e);
135                }
136                PaymentApplicationDocument pDocument = (PaymentApplicationDocument) d;
137                AccountsReceivableDocumentHeader arHeader = pDocument.getAccountsReceivableDocumentHeader();
138                if(ObjectUtils.isNotNull(arHeader)) {
139                    customerNumber = arHeader.getCustomerNumber();
140                }
141            }
142            
143            if(ObjectUtils.isNull(getSelectedInvoiceApplication())) {
144                if(ObjectUtils.isNull(invoices) || invoices.isEmpty()) {
145                    if(ObjectUtils.isNotNull(customerNumber)) {
146                        // get open invoices for the current customer
147                        CustomerInvoiceDocumentService customerInvoiceDocumentService = SpringContext.getBean(CustomerInvoiceDocumentService.class);
148                        Collection<CustomerInvoiceDocument> openInvoicesForCustomer = customerInvoiceDocumentService.getOpenInvoiceDocumentsByCustomerNumber(customerNumber);
149                        setInvoices(new ArrayList<CustomerInvoiceDocument>(openInvoicesForCustomer));
150                        if (invoices != null && !invoices.isEmpty()) {
151                            setSelectedInvoiceDocumentNumber(invoices.get(0).getDocumentNumber());
152                        }
153                        setupInvoiceWrappers(docId);
154                    }
155                }
156            }
157        }
158    
159        protected void setupInvoiceWrappers(String payAppDocNumber) {
160            if (StringUtils.isBlank(payAppDocNumber)) {
161                throw new IllegalArgumentException("The payAppDocNumber parameter passed in was null or blank.");
162            }
163    
164            //  clear any existing
165            invoiceApplications.clear();
166            
167            if (invoices == null || invoices.isEmpty()) {
168                return;
169            }
170            
171            for (CustomerInvoiceDocument invoice : invoices) {
172                PaymentApplicationInvoiceApply invoiceApplication = new PaymentApplicationInvoiceApply(payAppDocNumber, invoice);
173                addInvoiceApplication(invoiceApplication);
174            }
175        }
176    
177        public Map<String,PaymentApplicationInvoiceApply> getInvoiceApplicationsByDocumentNumber() {
178            Map<String,PaymentApplicationInvoiceApply> m = new HashMap<String,PaymentApplicationInvoiceApply>();
179            for (PaymentApplicationInvoiceApply i : invoiceApplications) {
180                m.put(i.getDocumentNumber(),i);
181            }
182            return m;
183        }
184        
185        public Integer getNextNonInvoicedLineNumber() {
186            return nextNonInvoicedLineNumber;
187        }
188    
189        public void setNextNonInvoicedLineNumber(Integer nextNonInvoicedLineNumber) {
190            this.nextNonInvoicedLineNumber = nextNonInvoicedLineNumber;
191        }
192    
193        /**
194         * @return
195         */
196        public KualiDecimal getNonArTotal() {
197            return null == getPaymentApplicationDocument() ? KualiDecimal.ZERO : getPaymentApplicationDocument().getNonArTotal();
198        }
199    
200        /**
201         * This method gets the payment application document
202         * 
203         * @return the payment application document
204         */
205        public PaymentApplicationDocument getPaymentApplicationDocument() {
206            return (PaymentApplicationDocument) getDocument();
207        }
208    
209        /**
210         * For a given invoiceDocNumber and invoiceItemNumber, this method will return any paidApplieds 
211         * that match those two fields, if any exists.  Otherwise it will return null.
212         */
213        public InvoicePaidApplied getPaidAppliedForInvoiceDetail(String invoiceDocNumber, Integer invoiceItemNumber) {
214            if (StringUtils.isBlank(invoiceDocNumber)) {
215                throw new IllegalArgumentException("The parameter [invoiceDocNumber] passed in was blank or null.");
216            }
217            if (invoiceItemNumber == null || invoiceItemNumber.intValue() < 1) {
218                throw new IllegalArgumentException("The parameter [invoiceItemNumber] passed in was blank, zero or negative.");
219            }
220            PaymentApplicationDocument payAppDoc = getPaymentApplicationDocument();
221            List<InvoicePaidApplied> paidApplieds = payAppDoc.getInvoicePaidApplieds();
222            for (InvoicePaidApplied paidApplied : paidApplieds) {
223                if (invoiceDocNumber.equalsIgnoreCase(paidApplied.getFinancialDocumentReferenceInvoiceNumber())) {
224                    if (invoiceItemNumber.equals(paidApplied.getInvoiceItemNumber())) {
225                        return paidApplied;
226                    }
227                }
228            }
229            return null;
230        }
231        
232        public String getSelectedInvoiceDocumentNumber() {
233            return selectedInvoiceDocumentNumber;
234        }
235    
236        public void setSelectedInvoiceDocumentNumber(String selectedInvoiceDocumentNumber) {
237            this.selectedInvoiceDocumentNumber = selectedInvoiceDocumentNumber;
238        }
239    
240        public KualiDecimal getUnappliedCustomerAmount() {
241            return unappliedCustomerAmount;
242        }
243    
244        public void setUnappliedCustomerAmount(KualiDecimal unappliedCustomerAmount) {
245            this.unappliedCustomerAmount = unappliedCustomerAmount;
246        }
247    
248        public List<PaymentApplicationInvoiceDetailApply> getSelectedInvoiceDetailApplications() {
249            PaymentApplicationInvoiceApply invoiceApplication = getSelectedInvoiceApplication();
250            List<PaymentApplicationInvoiceDetailApply> detailApplications = null;
251            if (ObjectUtils.isNotNull(invoiceApplication)) {
252                detailApplications = invoiceApplication.getDetailApplications();
253                if (null == detailApplications) {
254                    detailApplications = new ArrayList<PaymentApplicationInvoiceDetailApply>();
255                }
256            }
257            return detailApplications; 
258        }
259    
260        public List<PaymentApplicationInvoiceApply> getNonSelectedInvoiceApplications() {
261            String selectedInvoiceNumber = getSelectedInvoiceApplication().getDocumentNumber();
262            
263            List<PaymentApplicationInvoiceApply> nonSelectedInvoiceApplications = new ArrayList<PaymentApplicationInvoiceApply>();
264            for (PaymentApplicationInvoiceApply invoiceApplication : invoiceApplications) {
265                if (!invoiceApplication.getDocumentNumber().equalsIgnoreCase(selectedInvoiceNumber)) {
266                    nonSelectedInvoiceApplications.add(invoiceApplication);
267                }
268            }
269            return nonSelectedInvoiceApplications; 
270        }
271    
272        public List<PaymentApplicationInvoiceApply> getInvoiceApplications() {
273            return invoiceApplications;
274        }
275    
276        public PaymentApplicationInvoiceApply getSelectedInvoiceApplication() {
277            String docNumber = getSelectedInvoiceDocumentNumber();
278            if(ObjectUtils.isNotNull(docNumber)) {
279                return getInvoiceApplicationsByDocumentNumber().get(docNumber);
280            } else {
281                List<PaymentApplicationInvoiceApply> i = invoiceApplications;
282                if (i.isEmpty()) {
283                    return null;
284                } else {
285                    return invoiceApplications.get(0);
286                }
287            }
288        }
289    
290        public List<CustomerInvoiceDocument> getInvoices() {
291            return invoices;
292        }
293        
294        public void setInvoices(ArrayList<CustomerInvoiceDocument> invoices) {
295            this.invoices = invoices;
296        }
297    
298        public String getEnteredInvoiceDocumentNumber() {
299            return enteredInvoiceDocumentNumber;
300        }
301    
302        public void setEnteredInvoiceDocumentNumber(String enteredInvoiceDocumentNumber) {
303            this.enteredInvoiceDocumentNumber = enteredInvoiceDocumentNumber;
304        }
305    
306        /**
307         * 
308         * This special casing for negative applieds is a display issue.  We basically dont 
309         * want to ever display that they applied a negative amount, even while they may 
310         * have an unsaved document with negative applications that are failing validations.
311         * 
312         * @return
313         */
314        public KualiDecimal getTotalApplied() {
315            KualiDecimal totalApplied = getPaymentApplicationDocument().getTotalApplied();
316            if (totalApplied.isPositive()) {
317                return totalApplied;
318            }
319            else {
320                return KualiDecimal.ZERO;
321            }
322        }
323        
324        public KualiDecimal getUnallocatedBalance() {
325            return getTotalFromControl().subtract(getTotalApplied());
326        }
327        
328        /**
329         * 
330         * Returns the control total available for this document, whether its 
331         * a cash-control style payapp, or a nonapplied style payapp.
332         * 
333         * @return
334         */
335        public KualiDecimal getTotalFromControl() {
336            PaymentApplicationDocument payAppDoc = (PaymentApplicationDocument) getDocument();
337            if (payAppDoc.hasCashControlDetail()) {
338                return payAppDoc.getTotalFromControl();
339            }
340            else {
341                return getNonAppliedControlAvailableUnappliedAmount();
342            }
343        }
344        
345        /**
346         * This method retrieves a specific customer invoice detail from the list, by array index
347         * 
348         * @param index the index of the customer invoice detail to retrieve
349         * @return a CustomerInvoiceDetail
350         */
351        public PaymentApplicationInvoiceDetailApply getInvoiceDetailApplication(int index) {
352            List<PaymentApplicationInvoiceDetailApply> details = getSelectedInvoiceDetailApplications();
353            return details.get(index);
354        }
355    
356        /**
357         * This method retrieves a specific customer invoice from the list, by array index
358         * 
359         * @param index the index of the customer invoice to retrieve
360         * @return a CustomerInvoiceDocument
361         */
362        public PaymentApplicationInvoiceApply getInvoiceApplication(int index) {
363            return (PaymentApplicationInvoiceApply) invoiceApplications.get(index);
364        }
365    
366        @SuppressWarnings("unchecked")
367        public void setInvoiceDetailApplication(int key, PaymentApplicationInvoiceDetailApply value) {
368            getSelectedInvoiceDetailApplications().set(key, value);
369        }
370    
371        public KualiDecimal getSelectedInvoiceBalance() {
372            PaymentApplicationInvoiceApply invoiceApplication = getSelectedInvoiceApplication();
373            return invoiceApplication.getOpenAmount();
374        }
375    
376        public KualiDecimal getSelectedInvoiceTotalAmount() {
377            PaymentApplicationInvoiceApply invoiceApplication = getSelectedInvoiceApplication();
378            return invoiceApplication.getInvoice().getSourceTotal();
379        }
380    
381        public KualiDecimal getAmountAppliedDirectlyToInvoice() {
382            PaymentApplicationInvoiceApply invoiceApplicationToFind = getSelectedInvoiceApplication();
383            KualiDecimal amount = new KualiDecimal(0);
384            for (PaymentApplicationInvoiceApply invoiceApplication : invoiceApplications) {
385                if (invoiceApplicationToFind.getDocumentNumber().equalsIgnoreCase(invoiceApplication.getDocumentNumber())) {
386                    amount = amount.add(invoiceApplication.getAmountToApply());
387                }
388            }
389            return amount;
390        }
391    
392        /**
393         * This method gets the previous invoice document number
394         * 
395         * @return the previous invoice document number
396         */
397        public String getPreviousInvoiceDocumentNumber() {
398            CustomerInvoiceDocument _previousInvoiceDocument = null;
399    
400            PaymentApplicationInvoiceApply invoiceApplication = getSelectedInvoiceApplication(); 
401            CustomerInvoiceDocument selectedInvoiceDocument = invoiceApplication == null ? null : invoiceApplication.getInvoice();
402            if (null == selectedInvoiceDocument || 2 > invoices.size()) {
403                _previousInvoiceDocument = null;
404            } else {
405                Iterator<CustomerInvoiceDocument> iterator = invoices.iterator();
406                CustomerInvoiceDocument previousInvoiceDocument = iterator.next();
407                String selectedInvoiceDocumentNumber = selectedInvoiceDocument.getDocumentNumber();
408                if (null != selectedInvoiceDocumentNumber && selectedInvoiceDocumentNumber.equals(previousInvoiceDocument.getDocumentNumber())) {
409                    _previousInvoiceDocument = null;
410                } else {
411                    while (iterator.hasNext()) {
412                        CustomerInvoiceDocument currentInvoiceDocument = iterator.next();
413                        String currentInvoiceDocumentNumber = currentInvoiceDocument.getDocumentNumber();
414                        if (null != currentInvoiceDocumentNumber && currentInvoiceDocumentNumber.equals(selectedInvoiceDocument.getDocumentNumber())) {
415                            _previousInvoiceDocument = previousInvoiceDocument;
416                        } else {
417                            previousInvoiceDocument = currentInvoiceDocument;
418                        }
419                    }
420                }
421            }
422    
423            return null == _previousInvoiceDocument ? "" : _previousInvoiceDocument.getDocumentNumber();
424        }
425    
426        /**
427         * This method gets the next invoice document number
428         * 
429         * @return the next invoice document number
430         */
431        public String getNextInvoiceDocumentNumber() {
432            CustomerInvoiceDocument _nextInvoiceDocument = null;
433    
434            PaymentApplicationInvoiceApply invoiceApplication = getSelectedInvoiceApplication(); 
435            CustomerInvoiceDocument selectedInvoiceDocument = invoiceApplication == null ? null : invoiceApplication.getInvoice();
436            if (null == selectedInvoiceDocument || 2 > invoices.size()) {
437                _nextInvoiceDocument = null;
438            } else {
439                Iterator<CustomerInvoiceDocument> iterator = invoices.iterator();
440                while (iterator.hasNext()) {
441                    CustomerInvoiceDocument currentInvoiceDocument = iterator.next();
442                    String currentInvoiceDocumentNumber = currentInvoiceDocument.getDocumentNumber();
443                    if (currentInvoiceDocumentNumber.equals(selectedInvoiceDocument.getDocumentNumber())) {
444                        if (iterator.hasNext()) {
445                            _nextInvoiceDocument = iterator.next();
446                        } else {
447                            _nextInvoiceDocument = null;
448                        }
449                    }
450                }
451            }
452    
453            return null == _nextInvoiceDocument ? "" : _nextInvoiceDocument.getDocumentNumber();
454        }
455    
456        /**
457         * This method gets the Cash Control document for the payment application document
458         * 
459         * @return the cash control document
460         */
461        public CashControlDocument getCashControlDocument() {
462            return getPaymentApplicationDocument().getCashControlDocument();
463        }
464    
465        public NonInvoiced getNonInvoicedAddLine() {
466            return nonInvoicedAddLine;
467        }
468    
469        public void setNonInvoicedAddLine(NonInvoiced nonInvoicedAddLine) {
470            this.nonInvoicedAddLine = nonInvoicedAddLine;
471        }
472    
473        public Integer getNonInvoicedAddLineItemNumber() {
474            Integer number = new Integer(0);
475            if (null != getPaymentApplicationDocument()) {
476                Collection<NonInvoiced> items = getPaymentApplicationDocument().getNonInvoiceds();
477                for (NonInvoiced item : items) {
478                    Integer i = item.getFinancialDocumentLineNumber();
479                    if (i > number) {
480                        number = i;
481                    }
482                }
483            }
484            return number + 1;
485        }
486    
487        public PaymentApplicationInvoiceApply getInvoiceApplication(String documentNumber) {
488            if (StringUtils.isBlank(documentNumber)) {
489                throw new RuntimeException("The parameter passed in [documentNumber] was null or blank.");
490            }
491            for (PaymentApplicationInvoiceApply invoiceApplication : invoiceApplications) {
492                if (documentNumber.equalsIgnoreCase(invoiceApplication.getDocumentNumber())) {
493                    return invoiceApplication;
494                }
495            }
496            return null;
497        }
498        
499        public void addInvoiceApplication(PaymentApplicationInvoiceApply invoiceApplicationToAdd) {
500            if (invoiceApplicationToAdd == null) {
501                throw new RuntimeException("The parameter passed in [invoiceApplicationToAdd] was null.");
502            }
503            for (int i = 0; i < invoiceApplications.size(); i++) {
504                PaymentApplicationInvoiceApply invoiceApplication = invoiceApplications.get(i);
505                if (invoiceApplicationToAdd.getDocumentNumber().equalsIgnoreCase(invoiceApplication.getDocumentNumber())) {
506                    invoiceApplications.set(i, invoiceApplicationToAdd);
507                }
508            }
509            invoiceApplications.add(invoiceApplicationToAdd);
510        }
511    
512        public String getSelectedCustomerNumber() {
513            return selectedCustomerNumber;
514        }
515    
516        public void setSelectedCustomerNumber(String selectedCustomerNumber) {
517            this.selectedCustomerNumber = StringUtils.isBlank(selectedCustomerNumber) ? null : selectedCustomerNumber.toUpperCase();
518        }
519    
520        public KualiDecimal getNonAppliedHoldingAmount() {
521            return nonAppliedHoldingAmount;
522        }
523    
524        public void setNonAppliedHoldingAmount(KualiDecimal nonAppliedHoldingAmount) {
525            this.nonAppliedHoldingAmount = nonAppliedHoldingAmount;
526        }
527    
528        public String getNonAppliedHoldingCustomerNumber() {
529            return nonAppliedHoldingCustomerNumber;
530        }
531    
532        public void setNonAppliedHoldingCustomerNumber(String nonAppliedHoldingCustomerNumber) {
533            this.nonAppliedHoldingCustomerNumber = nonAppliedHoldingCustomerNumber;
534        }
535    
536        public List<PaymentApplicationDocument> getNonAppliedControlDocs() {
537            return nonAppliedControlDocs;
538        }
539    
540        public void setNonAppliedControlDocs(List<PaymentApplicationDocument> nonAppliedControlDocs) {
541            this.nonAppliedControlDocs = nonAppliedControlDocs;
542        }
543    
544        /**
545         * 
546         * Returns the total amount of previously NonApplied funds available 
547         * to apply to invoices and other applications on this document.
548         * 
549         * @return
550         */
551        public KualiDecimal getNonAppliedControlAvailableUnappliedAmount() {
552            KualiDecimal amount = KualiDecimal.ZERO;
553            for (NonAppliedHolding nonAppliedHolding : nonAppliedControlHoldings) {
554                amount = amount.add(nonAppliedHolding.getAvailableUnappliedAmount());
555            }
556            return amount;
557        }
558        
559        public List<NonAppliedHolding> getNonAppliedControlHoldings() {
560            return nonAppliedControlHoldings;
561        }
562    
563        public void setNonAppliedControlHoldings(List<NonAppliedHolding> nonAppliedControlHoldings) {
564            this.nonAppliedControlHoldings = nonAppliedControlHoldings;
565        }
566        
567        /**
568         * 
569         * Used for when the doc is final, to show the control docs section.
570         * @return
571         */
572        public Map<String,KualiDecimal> getDistributionsFromControlDocs() {
573            if (distributionsFromControlDocs == null || distributionsFromControlDocs.isEmpty()) {
574                distributionsFromControlDocs = getPaymentApplicationDocument().getDistributionsFromControlDocuments();
575            }
576            return distributionsFromControlDocs;
577        }
578        
579        /**
580         * 
581         * Used for when the doc is live, to show the control docs section.
582         * @return
583         */
584        public Map<String,KualiDecimal> getNonAppliedControlAllocations() {
585            if (nonAppliedControlAllocations == null || nonAppliedControlAllocations.isEmpty()) {
586                nonAppliedControlAllocations = getPaymentApplicationDocument().allocateFundsFromUnappliedControls(nonAppliedControlHoldings, getTotalApplied());
587            }
588            return nonAppliedControlAllocations;
589        }
590        
591        public void setNonAppliedControlAllocations(Map<String, KualiDecimal> nonAppliedControlAllocations) {
592            this.nonAppliedControlAllocations = nonAppliedControlAllocations;
593        }
594    
595        public KualiDecimal getNonAppliedControlAllocation(String documentNumber) {
596            if (!getNonAppliedControlAllocations().containsKey(documentNumber)) {
597                return KualiDecimal.ZERO;
598            }
599            return getNonAppliedControlAllocations().get(documentNumber);
600        }
601    
602        /**
603         * @see org.kuali.rice.kns.web.struts.form.KualiTransactionalDocumentFormBase#populateFalseCheckboxes(javax.servlet.http.HttpServletRequest)
604         */
605        @Override
606        protected void populateFalseCheckboxes(HttpServletRequest request) {
607            Map<String, String[]> parameterMap = request.getParameterMap();
608            if (parameterMap.get("checkboxToReset") != null) {
609                final String[] checkboxesToReset = request.getParameterValues("checkboxToReset");
610                if(checkboxesToReset != null && checkboxesToReset.length > 0) {
611                    for (int i = 0; i < checkboxesToReset.length; i++) {
612                        String propertyName = (String) checkboxesToReset[i];
613                        if ( !StringUtils.isBlank(propertyName) && parameterMap.get(propertyName) == null ) {
614                            try {
615                                populateForProperty(propertyName, KimConstants.KIM_ATTRIBUTE_BOOLEAN_FALSE_STR_VALUE_DISPLAY, parameterMap);
616                            } catch (RuntimeException ex) {
617                                
618                            }
619                        }  
620                        else if ( !StringUtils.isBlank(propertyName) && parameterMap.get(propertyName) != null && parameterMap.get(propertyName).length >= 1 && parameterMap.get(propertyName)[0].equalsIgnoreCase("on") ) {
621                            try {
622                                populateForProperty(propertyName, KimConstants.KIM_ATTRIBUTE_BOOLEAN_TRUE_STR_VALUE_DISPLAY, parameterMap); 
623                            } catch (RuntimeException ex) {
624                                
625                            }
626                        }
627                    }
628                }
629            }    }
630        
631    }