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;
017    
018    import java.sql.Date;
019    import java.sql.Timestamp;
020    import java.util.ArrayList;
021    import java.util.Calendar;
022    import java.util.HashMap;
023    import java.util.Iterator;
024    import java.util.LinkedHashMap;
025    import java.util.List;
026    import java.util.Map;
027    
028    import org.apache.commons.lang.StringUtils;
029    import org.kuali.kfs.coa.businessobject.Account;
030    import org.kuali.kfs.coa.businessobject.Chart;
031    import org.kuali.kfs.coa.businessobject.ObjectCode;
032    import org.kuali.kfs.coa.businessobject.Organization;
033    import org.kuali.kfs.coa.businessobject.ProjectCode;
034    import org.kuali.kfs.coa.businessobject.SubAccount;
035    import org.kuali.kfs.coa.businessobject.SubObjectCode;
036    import org.kuali.kfs.module.ar.ArConstants;
037    import org.kuali.kfs.module.ar.businessobject.AccountsReceivableDocumentHeader;
038    import org.kuali.kfs.module.ar.businessobject.Customer;
039    import org.kuali.kfs.module.ar.businessobject.CustomerAddress;
040    import org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail;
041    import org.kuali.kfs.module.ar.businessobject.CustomerInvoiceRecurrenceDetails;
042    import org.kuali.kfs.module.ar.businessobject.CustomerProcessingType;
043    import org.kuali.kfs.module.ar.businessobject.InvoiceRecurrence;
044    import org.kuali.kfs.module.ar.businessobject.PrintInvoiceOptions;
045    import org.kuali.kfs.module.ar.businessobject.ReceivableCustomerInvoiceDetail;
046    import org.kuali.kfs.module.ar.businessobject.SalesTaxCustomerInvoiceDetail;
047    import org.kuali.kfs.module.ar.document.service.AccountsReceivableTaxService;
048    import org.kuali.kfs.module.ar.document.service.CustomerAddressService;
049    import org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService;
050    import org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService;
051    import org.kuali.kfs.module.ar.document.service.CustomerInvoiceGLPEService;
052    import org.kuali.kfs.sys.KFSConstants;
053    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper;
054    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
055    import org.kuali.kfs.sys.businessobject.TaxDetail;
056    import org.kuali.kfs.sys.context.SpringContext;
057    import org.kuali.kfs.sys.document.AccountingDocumentBase;
058    import org.kuali.kfs.sys.document.AmountTotaling;
059    import org.kuali.kfs.sys.document.Correctable;
060    import org.kuali.kfs.sys.service.GeneralLedgerPendingEntryService;
061    import org.kuali.kfs.sys.service.TaxService;
062    import org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO;
063    import org.kuali.rice.kew.exception.WorkflowException;
064    import org.kuali.rice.kns.UserSession;
065    import org.kuali.rice.kns.document.Copyable;
066    import org.kuali.rice.kns.document.MaintenanceDocument;
067    import org.kuali.rice.kns.service.BusinessObjectService;
068    import org.kuali.rice.kns.service.DateTimeService;
069    import org.kuali.rice.kns.service.DocumentService;
070    import org.kuali.rice.kns.service.ParameterService;
071    import org.kuali.rice.kns.util.DateUtils;
072    import org.kuali.rice.kns.util.GlobalVariables;
073    import org.kuali.rice.kns.util.KualiDecimal;
074    import org.kuali.rice.kns.util.ObjectUtils;
075    import org.kuali.rice.kns.util.TypedArrayList;
076    
077    /**
078     * @author Kuali Nervous System Team (kualidev@oncourse.iu.edu)
079     */
080    public class CustomerInvoiceDocument extends AccountingDocumentBase implements AmountTotaling, Copyable, Correctable, Comparable<CustomerInvoiceDocument> {
081    
082        protected static final String HAS_RECCURENCE_NODE = "HasReccurence";
083        protected static final String BATCH_GENERATED_NODE = "BatchGenerated";
084    
085        protected String invoiceHeaderText;
086        protected String invoiceAttentionLineText;
087        protected Date invoiceDueDate;
088        protected Date billingDate;
089        protected Date closedDate;
090        protected Date billingDateForDisplay;
091        protected String invoiceTermsText;
092        protected String organizationInvoiceNumber;
093        protected String customerPurchaseOrderNumber;
094        protected String printInvoiceIndicator;
095        protected Date customerPurchaseOrderDate;
096        protected String billByChartOfAccountCode;
097        protected String billedByOrganizationCode;
098        protected Integer customerShipToAddressIdentifier;
099        protected Integer customerBillToAddressIdentifier;
100        protected String customerSpecialProcessingCode;
101        protected boolean customerRecordAttachmentIndicator;
102        protected boolean openInvoiceIndicator;
103        protected String paymentChartOfAccountsCode;
104        protected String paymentAccountNumber;
105        protected String paymentSubAccountNumber;
106        protected String paymentFinancialObjectCode;
107        protected String paymentFinancialSubObjectCode;
108        protected String paymentProjectCode;
109        protected String paymentOrganizationReferenceIdentifier;
110        protected Date printDate;
111        protected Integer age;
112        protected String customerName;
113        protected String billingAddressName;
114        protected String billingCityName;
115        protected String billingStateCode;
116        protected String billingZipCode;
117        protected String billingCountryCode;
118        protected String billingAddressInternationalProvinceName;
119        protected String billingInternationalMailCode;
120        protected String billingEmailAddress;
121        protected String billingAddressTypeCode;
122        protected String billingLine1StreetAddress;
123        protected String billingLine2StreetAddress;
124        protected String shippingLine1StreetAddress;
125        protected String shippingLine2StreetAddress;
126        protected String shippingAddressName;
127        protected String shippingCityName;
128        protected String shippingStateCode;
129        protected String shippingZipCode;
130        protected String shippingCountryCode;
131        protected String shippingAddressInternationalProvinceName;
132        protected String shippingInternationalMailCode;
133        protected String shippingEmailAddress;
134        protected String shippingAddressTypeCode;
135        protected boolean recurredInvoiceIndicator;
136        
137        protected AccountsReceivableDocumentHeader accountsReceivableDocumentHeader;
138        protected Chart billByChartOfAccount;
139        protected Organization billedByOrganization;
140        protected CustomerProcessingType customerSpecialProcessing;
141        protected Account paymentAccount;
142        protected Chart paymentChartOfAccounts;
143        protected SubAccount paymentSubAccount;
144        protected ObjectCode paymentFinancialObject;
145        protected SubObjectCode paymentFinancialSubObject;
146        protected ProjectCode paymentProject;
147        protected PrintInvoiceOptions printInvoiceOption;
148        protected CustomerAddress customerShipToAddress;
149        protected CustomerAddress customerBillToAddress;
150        protected CustomerInvoiceRecurrenceDetails customerInvoiceRecurrenceDetails;
151    
152        protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CustomerInvoiceDocument.class);
153    
154        // added for quick apply check control
155        //TODO Andrew
156        //protected boolean quickApply;
157    
158        /**
159         * Default constructor.
160         */
161        public CustomerInvoiceDocument() {
162            super();
163        }
164    
165        /**
166         * This method calculates the outstanding balance on an invoice.
167         * 
168         * @return the outstanding balance on this invoice
169         */
170        public KualiDecimal getOpenAmount() {
171            return SpringContext.getBean(CustomerInvoiceDocumentService.class).getOpenAmountForCustomerInvoiceDocument(this);
172        }
173    
174        //TODO Andrew
175    //    public void setOpenAmount(KualiDecimal openAmount) {
176    //        // do nothing
177    //    }
178    //
179    //    public void setBalance(KualiDecimal balance) {
180    //        // do nothing
181    //    }
182    //
183    //    public void setSourceTotal(KualiDecimal sourceTotal) {
184    //        // do nothing
185    //    }
186    
187        /**
188         * Gets the documentNumber attribute.
189         * 
190         * @return Returns the documentNumber
191         */
192        public String getDocumentNumber() {
193            return documentNumber;
194        }
195    
196        /**
197         * Sets the documentNumber attribute.
198         * 
199         * @param documentNumber The documentNumber to set.
200         */
201        public void setDocumentNumber(String documentNumber) {
202            this.documentNumber = documentNumber;
203        }
204    
205    
206        /**
207         * Gets the invoiceHeaderText attribute.
208         * 
209         * @return Returns the invoiceHeaderText
210         */
211        public String getInvoiceHeaderText() {
212            return invoiceHeaderText;
213        }
214    
215        /**
216         * Sets the invoiceHeaderText attribute.
217         * 
218         * @param invoiceHeaderText The invoiceHeaderText to set.
219         */
220        public void setInvoiceHeaderText(String invoiceHeaderText) {
221            this.invoiceHeaderText = invoiceHeaderText;
222        }
223    
224    
225        /**
226         * Gets the invoiceAttentionLineText attribute.
227         * 
228         * @return Returns the invoiceAttentionLineText
229         */
230        public String getInvoiceAttentionLineText() {
231            return invoiceAttentionLineText;
232        }
233    
234        /**
235         * Sets the invoiceAttentionLineText attribute.
236         * 
237         * @param invoiceAttentionLineText The invoiceAttentionLineText to set.
238         */
239        public void setInvoiceAttentionLineText(String invoiceAttentionLineText) {
240            this.invoiceAttentionLineText = invoiceAttentionLineText;
241        }
242    
243    
244        /**
245         * Gets the invoiceDueDate attribute.
246         * 
247         * @return Returns the invoiceDueDate
248         */
249        public Date getInvoiceDueDate() {
250            return invoiceDueDate;
251        }
252    
253        /**
254         * Sets the invoiceDueDate attribute.
255         * 
256         * @param invoiceDueDate The invoiceDueDate to set.
257         */
258        public void setInvoiceDueDate(Date invoiceDueDate) {
259            this.invoiceDueDate = invoiceDueDate;
260        }
261    
262    
263        /**
264         * Gets the billingDate attribute.
265         * 
266         * @return Returns the billingDate
267         */
268        public Date getBillingDate() {
269            return billingDate;
270        }
271    
272        /**
273         * This method returns the age of an invoice (i.e. current date - billing date)
274         * 
275         * @return
276         */
277        public Integer getAge() {
278            if (ObjectUtils.isNotNull(billingDate)) {
279                return (int) DateUtils.getDifferenceInDays(new Timestamp(billingDate.getTime()), SpringContext.getBean(DateTimeService.class).getCurrentTimestamp());
280            }
281            // TODO should I be throwing an exception or throwing a null?
282            return null;
283        }
284    
285        public void setAge(Integer age) {
286            this.age = age;
287        }
288    
289        /**
290         * Sets the billingDate attribute.
291         * 
292         * @param billingDate The billingDate to set.
293         */
294        public void setBillingDate(Date billingDate) {
295            this.billingDate = billingDate;
296        }
297    
298    
299        /**
300         * Gets the invoiceTermsText attribute.
301         * 
302         * @return Returns the invoiceTermsText
303         */
304        public String getInvoiceTermsText() {
305            return invoiceTermsText;
306        }
307    
308        /**
309         * Sets the invoiceTermsText attribute.
310         * 
311         * @param invoiceTermsText The invoiceTermsText to set.
312         */
313        public void setInvoiceTermsText(String invoiceTermsText) {
314            this.invoiceTermsText = invoiceTermsText;
315        }
316    
317    
318        /**
319         * Gets the organizationInvoiceNumber attribute.
320         * 
321         * @return Returns the organizationInvoiceNumber
322         */
323        public String getOrganizationInvoiceNumber() {
324            return organizationInvoiceNumber;
325        }
326    
327        /**
328         * Sets the organizationInvoiceNumber attribute.
329         * 
330         * @param organizationInvoiceNumber The organizationInvoiceNumber to set.
331         */
332        public void setOrganizationInvoiceNumber(String organizationInvoiceNumber) {
333            this.organizationInvoiceNumber = organizationInvoiceNumber;
334        }
335    
336        /**
337         * Gets the customerPurchaseOrderNumber attribute.
338         * 
339         * @return Returns the customerPurchaseOrderNumber
340         */
341        public String getCustomerPurchaseOrderNumber() {
342            return customerPurchaseOrderNumber;
343        }
344    
345        /**
346         * Sets the customerPurchaseOrderNumber attribute.
347         * 
348         * @param customerPurchaseOrderNumber The customerPurchaseOrderNumber to set.
349         */
350        public void setCustomerPurchaseOrderNumber(String customerPurchaseOrderNumber) {
351            this.customerPurchaseOrderNumber = customerPurchaseOrderNumber;
352        }
353    
354        /**
355         * Gets the printInvoiceIndicator attribute.
356         * 
357         * @return Returns the printInvoiceIndicator.
358         */
359        public String getPrintInvoiceIndicator() {
360            return printInvoiceIndicator;
361        }
362    
363        /**
364         * Sets the printInvoiceIndicator attribute value.
365         * 
366         * @param printInvoiceIndicator The printInvoiceIndicator to set.
367         */
368        public void setPrintInvoiceIndicator(String printInvoiceIndicator) {
369            this.printInvoiceIndicator = printInvoiceIndicator;
370        }
371    
372        /**
373         * Gets the customerPurchaseOrderDate attribute.
374         * 
375         * @return Returns the customerPurchaseOrderDate
376         */
377        public Date getCustomerPurchaseOrderDate() {
378            return customerPurchaseOrderDate;
379        }
380    
381        /**
382         * Sets the customerPurchaseOrderDate attribute.
383         * 
384         * @param customerPurchaseOrderDate The customerPurchaseOrderDate to set.
385         */
386        public void setCustomerPurchaseOrderDate(Date customerPurchaseOrderDate) {
387            this.customerPurchaseOrderDate = customerPurchaseOrderDate;
388        }
389    
390    
391        /**
392         * Gets the billByChartOfAccountCode attribute.
393         * 
394         * @return Returns the billByChartOfAccountCode
395         */
396        public String getBillByChartOfAccountCode() {
397            return billByChartOfAccountCode;
398        }
399    
400        /**
401         * Sets the billByChartOfAccountCode attribute.
402         * 
403         * @param billByChartOfAccountCode The billByChartOfAccountCode to set.
404         */
405        public void setBillByChartOfAccountCode(String billByChartOfAccountCode) {
406            this.billByChartOfAccountCode = billByChartOfAccountCode;
407        }
408    
409    
410        /**
411         * Gets the billedByOrganizationCode attribute.
412         * 
413         * @return Returns the billedByOrganizationCode
414         */
415        public String getBilledByOrganizationCode() {
416            return billedByOrganizationCode;
417        }
418    
419        /**
420         * Sets the billedByOrganizationCode attribute.
421         * 
422         * @param billedByOrganizationCode The billedByOrganizationCode to set.
423         */
424        public void setBilledByOrganizationCode(String billedByOrganizationCode) {
425            this.billedByOrganizationCode = billedByOrganizationCode;
426        }
427    
428    
429        /**
430         * Gets the customerShipToAddressIdentifier attribute.
431         * 
432         * @return Returns the customerShipToAddressIdentifier
433         */
434        public Integer getCustomerShipToAddressIdentifier() {
435            return customerShipToAddressIdentifier;
436        }
437    
438        /**
439         * Sets the customerShipToAddressIdentifier attribute.
440         * 
441         * @param customerShipToAddressIdentifier The customerShipToAddressIdentifier to set.
442         */
443        public void setCustomerShipToAddressIdentifier(Integer customerShipToAddressIdentifier) {
444            this.customerShipToAddressIdentifier = customerShipToAddressIdentifier;
445        }
446    
447    
448        /**
449         * Gets the customerBillToAddressIdentifier attribute.
450         * 
451         * @return Returns the customerBillToAddressIdentifier
452         */
453        public Integer getCustomerBillToAddressIdentifier() {
454            return customerBillToAddressIdentifier;
455        }
456    
457        /**
458         * Sets the customerBillToAddressIdentifier attribute.
459         * 
460         * @param customerBillToAddressIdentifier The customerBillToAddressIdentifier to set.
461         */
462        public void setCustomerBillToAddressIdentifier(Integer customerBillToAddressIdentifier) {
463            this.customerBillToAddressIdentifier = customerBillToAddressIdentifier;
464        }
465    
466    
467        /**
468         * Gets the customerSpecialProcessingCode attribute.
469         * 
470         * @return Returns the customerSpecialProcessingCode
471         */
472        public String getCustomerSpecialProcessingCode() {
473            return customerSpecialProcessingCode;
474        }
475    
476        /**
477         * Sets the customerSpecialProcessingCode attribute.
478         * 
479         * @param customerSpecialProcessingCode The customerSpecialProcessingCode to set.
480         */
481        public void setCustomerSpecialProcessingCode(String customerSpecialProcessingCode) {
482            this.customerSpecialProcessingCode = customerSpecialProcessingCode;
483        }
484    
485    
486        /**
487         * Gets the customerRecordAttachmentIndicator attribute.
488         * 
489         * @return Returns the customerRecordAttachmentIndicator
490         */
491        public boolean isCustomerRecordAttachmentIndicator() {
492            return customerRecordAttachmentIndicator;
493        }
494    
495        /**
496         * Sets the customerRecordAttachmentIndicator attribute.
497         * 
498         * @param customerRecordAttachmentIndicator The customerRecordAttachmentIndicator to set.
499         */
500        public void setCustomerRecordAttachmentIndicator(boolean customerRecordAttachmentIndicator) {
501            this.customerRecordAttachmentIndicator = customerRecordAttachmentIndicator;
502        }
503    
504    
505        /**
506         * Gets the openInvoiceIndicator attribute.
507         * 
508         * @return Returns the openInvoiceIndicator
509         */
510        public boolean isOpenInvoiceIndicator() {
511            return openInvoiceIndicator;
512        }
513    
514        /**
515         * Sets the openInvoiceIndicator attribute.
516         * 
517         * @param openInvoiceIndicator The openInvoiceIndicator to set.
518         */
519        public void setOpenInvoiceIndicator(boolean openInvoiceIndicator) {
520            this.openInvoiceIndicator = openInvoiceIndicator;
521        }
522    
523        /**
524         * Gets the paymentAccountNumber attribute.
525         * 
526         * @return Returns the paymentAccountNumber.
527         */
528        public String getPaymentAccountNumber() {
529            return paymentAccountNumber;
530        }
531    
532        /**
533         * Sets the paymentAccountNumber attribute value.
534         * 
535         * @param paymentAccountNumber The paymentAccountNumber to set.
536         */
537        public void setPaymentAccountNumber(String paymentAccountNumber) {
538            this.paymentAccountNumber = paymentAccountNumber;
539        }
540    
541        /**
542         * Gets the paymentChartOfAccountsCode attribute.
543         * 
544         * @return Returns the paymentChartOfAccountsCode.
545         */
546        public String getPaymentChartOfAccountsCode() {
547            return paymentChartOfAccountsCode;
548        }
549    
550        /**
551         * Sets the paymentChartOfAccountsCode attribute value.
552         * 
553         * @param paymentChartOfAccountsCode The paymentChartOfAccountsCode to set.
554         */
555        public void setPaymentChartOfAccountsCode(String paymentChartOfAccountsCode) {
556            this.paymentChartOfAccountsCode = paymentChartOfAccountsCode;
557        }
558    
559        /**
560         * Gets the paymentFinancialObjectCode attribute.
561         * 
562         * @return Returns the paymentFinancialObjectCode.
563         */
564        public String getPaymentFinancialObjectCode() {
565            return paymentFinancialObjectCode;
566        }
567    
568        /**
569         * Sets the paymentFinancialObjectCode attribute value.
570         * 
571         * @param paymentFinancialObjectCode The paymentFinancialObjectCode to set.
572         */
573        public void setPaymentFinancialObjectCode(String paymentFinancialObjectCode) {
574            this.paymentFinancialObjectCode = paymentFinancialObjectCode;
575        }
576    
577        /**
578         * Gets the paymentFinancialSubObjectCode attribute.
579         * 
580         * @return Returns the paymentFinancialSubObjectCode.
581         */
582        public String getPaymentFinancialSubObjectCode() {
583            return paymentFinancialSubObjectCode;
584        }
585    
586        /**
587         * Sets the paymentFinancialSubObjectCode attribute value.
588         * 
589         * @param paymentFinancialSubObjectCode The paymentFinancialSubObjectCode to set.
590         */
591        public void setPaymentFinancialSubObjectCode(String paymentFinancialSubObjectCode) {
592            this.paymentFinancialSubObjectCode = paymentFinancialSubObjectCode;
593        }
594    
595        /**
596         * Gets the paymentOrganizationReferenceIdentifier attribute.
597         * 
598         * @return Returns the paymentOrganizationReferenceIdentifier.
599         */
600        public String getPaymentOrganizationReferenceIdentifier() {
601            return paymentOrganizationReferenceIdentifier;
602        }
603    
604        /**
605         * Sets the paymentOrganizationReferenceIdentifier attribute value.
606         * 
607         * @param paymentOrganizationReferenceIdentifier The paymentOrganizationReferenceIdentifier to set.
608         */
609        public void setPaymentOrganizationReferenceIdentifier(String paymentOrganizationReferenceIdentifier) {
610            this.paymentOrganizationReferenceIdentifier = paymentOrganizationReferenceIdentifier;
611        }
612    
613        /**
614         * Gets the paymentProjectCode attribute.
615         * 
616         * @return Returns the paymentProjectCode.
617         */
618        public String getPaymentProjectCode() {
619            return paymentProjectCode;
620        }
621    
622        /**
623         * Sets the paymentProjectCode attribute value.
624         * 
625         * @param paymentProjectCode The paymentProjectCode to set.
626         */
627        public void setPaymentProjectCode(String paymentProjectCode) {
628            this.paymentProjectCode = paymentProjectCode;
629        }
630    
631        /**
632         * Gets the paymentSubAccountNumber attribute.
633         * 
634         * @return Returns the paymentSubAccountNumber.
635         */
636        public String getPaymentSubAccountNumber() {
637            return paymentSubAccountNumber;
638        }
639    
640        /**
641         * Sets the paymentSubAccountNumber attribute value.
642         * 
643         * @param paymentSubAccountNumber The paymentSubAccountNumber to set.
644         */
645        public void setPaymentSubAccountNumber(String paymentSubAccountNumber) {
646            this.paymentSubAccountNumber = paymentSubAccountNumber;
647        }
648    
649        /**
650         * Gets the printDate attribute.
651         * 
652         * @return Returns the printDate
653         */
654        public Date getPrintDate() {
655            return printDate;
656        }
657    
658        /**
659         * Sets the printDate attribute.
660         * 
661         * @param printDate The printDate to set.
662         */
663        public void setPrintDate(Date printDate) {
664            this.printDate = printDate;
665        }
666    
667        /**
668         * Gets the accountsReceivableDocumentHeader attribute.
669         * 
670         * @return Returns the accountsReceivableDocumentHeader
671         */
672        public AccountsReceivableDocumentHeader getAccountsReceivableDocumentHeader() {
673            return accountsReceivableDocumentHeader;
674        }
675    
676        /**
677         * Sets the accountsReceivableDocumentHeader attribute.
678         * 
679         * @param accountsReceivableDocumentHeader The accountsReceivableDocumentHeader to set.
680         */
681        public void setAccountsReceivableDocumentHeader(AccountsReceivableDocumentHeader accountsReceivableDocumentHeader) {
682            this.accountsReceivableDocumentHeader = accountsReceivableDocumentHeader;
683        }
684    
685        /**
686         * 
687         * This method...
688         * @return
689         */
690        public String getParentInvoiceNumber() {
691            return getAccountsReceivableDocumentHeader().getDocumentHeader().getDocumentTemplateNumber();
692        }
693        
694        /**
695         * Gets the billByChartOfAccount attribute.
696         * 
697         * @return Returns the billByChartOfAccount
698         */
699        public Chart getBillByChartOfAccount() {
700            return billByChartOfAccount;
701        }
702    
703        /**
704         * Sets the billByChartOfAccount attribute.
705         * 
706         * @param billByChartOfAccount The billByChartOfAccount to set.
707         * @deprecated
708         */
709        public void setBillByChartOfAccount(Chart billByChartOfAccount) {
710            this.billByChartOfAccount = billByChartOfAccount;
711        }
712    
713        /**
714         * Gets the billedByOrganization attribute.
715         * 
716         * @return Returns the billedByOrganization
717         */
718        public Organization getBilledByOrganization() {
719            return billedByOrganization;
720        }
721    
722        /**
723         * Sets the billedByOrganization attribute.
724         * 
725         * @param billedByOrganization The billedByOrganization to set.
726         * @deprecated
727         */
728        public void setBilledByOrganization(Organization billedByOrganization) {
729            this.billedByOrganization = billedByOrganization;
730        }
731    
732        /**
733         * Gets the customerSpecialProcessing attribute.
734         * 
735         * @return Returns the customerSpecialProcessing
736         */
737        public CustomerProcessingType getCustomerSpecialProcessing() {
738            return customerSpecialProcessing;
739        }
740    
741        /**
742         * Sets the customerSpecialProcessing attribute.
743         * 
744         * @param customerSpecialProcessing The customerSpecialProcessing to set.
745         * @deprecated
746         */
747        public void setCustomerSpecialProcessing(CustomerProcessingType customerSpecialProcessing) {
748            this.customerSpecialProcessing = customerSpecialProcessing;
749        }
750    
751        /**
752         * Gets the paymentAccount attribute.
753         * 
754         * @return Returns the paymentAccount.
755         */
756        public Account getPaymentAccount() {
757            return paymentAccount;
758        }
759    
760        /**
761         * Sets the paymentAccount attribute value.
762         * 
763         * @param paymentAccount The paymentAccount to set.
764         * @deprecated
765         */
766        public void setPaymentAccount(Account paymentAccount) {
767            this.paymentAccount = paymentAccount;
768        }
769    
770        /**
771         * Gets the paymentChartOfAccounts attribute.
772         * 
773         * @return Returns the paymentChartOfAccounts.
774         */
775        public Chart getPaymentChartOfAccounts() {
776            return paymentChartOfAccounts;
777        }
778    
779        /**
780         * Sets the paymentChartOfAccounts attribute value.
781         * 
782         * @param paymentChartOfAccounts The paymentChartOfAccounts to set.
783         * @deprecated
784         */
785        public void setPaymentChartOfAccounts(Chart paymentChartOfAccounts) {
786            this.paymentChartOfAccounts = paymentChartOfAccounts;
787        }
788    
789        /**
790         * Gets the paymentFinancialObject attribute.
791         * 
792         * @return Returns the paymentFinancialObject.
793         */
794        public ObjectCode getPaymentFinancialObject() {
795            return paymentFinancialObject;
796        }
797    
798        /**
799         * Sets the paymentFinancialObject attribute value.
800         * 
801         * @param paymentFinancialObject The paymentFinancialObject to set.
802         * @deprecated
803         */
804        public void setPaymentFinancialObject(ObjectCode paymentFinancialObject) {
805            this.paymentFinancialObject = paymentFinancialObject;
806        }
807    
808        /**
809         * Gets the paymentFinancialSubObject attribute.
810         * 
811         * @return Returns the paymentFinancialSubObject.
812         */
813        public SubObjectCode getPaymentFinancialSubObject() {
814            return paymentFinancialSubObject;
815        }
816    
817        /**
818         * Sets the paymentFinancialSubObject attribute value.
819         * 
820         * @param paymentFinancialSubObject The paymentFinancialSubObject to set.
821         * @deprecated
822         */
823        public void setPaymentFinancialSubObject(SubObjectCode paymentFinancialSubObject) {
824            this.paymentFinancialSubObject = paymentFinancialSubObject;
825        }
826    
827        /**
828         * Gets the paymentProject attribute.
829         * 
830         * @return Returns the paymentProject.
831         */
832        public ProjectCode getPaymentProject() {
833            return paymentProject;
834        }
835    
836        /**
837         * Sets the paymentProject attribute value.
838         * 
839         * @param paymentProject The paymentProject to set.
840         * @deprecated
841         */
842        public void setPaymentProject(ProjectCode paymentProject) {
843            this.paymentProject = paymentProject;
844        }
845    
846        /**
847         * Gets the paymentSubAccount attribute.
848         * 
849         * @return Returns the paymentSubAccount.
850         */
851        public SubAccount getPaymentSubAccount() {
852            return paymentSubAccount;
853        }
854    
855        /**
856         * Sets the paymentSubAccount attribute value.
857         * 
858         * @param paymentSubAccount The paymentSubAccount to set.
859         * @deprecated
860         */
861        public void setPaymentSubAccount(SubAccount paymentSubAccount) {
862            this.paymentSubAccount = paymentSubAccount;
863        }
864    
865        /**
866         * This method returns the billing date for display. If billing date hasn't been set yet, just display current date
867         * 
868         * @return
869         */
870        public Date getBillingDateForDisplay() {
871            if (ObjectUtils.isNotNull(getBillingDate())) {
872                return getBillingDate();
873            }
874            else {
875                return SpringContext.getBean(DateTimeService.class).getCurrentSqlDate();
876            }
877        }
878    
879        /**
880         * This method...
881         * 
882         * @param date
883         */
884        public void setBillingDateForDisplay(Date date) {
885            // do nothing
886        }
887    
888        public Date getClosedDate() {
889            return closedDate;
890        }
891    
892        public void setClosedDate(Date closedDate) {
893            this.closedDate = closedDate;
894        }
895    
896        /**
897         * @see org.kuali.rice.kns.bo.BusinessObjectBase#toStringMapper()
898         */
899        @SuppressWarnings("unchecked")
900        protected LinkedHashMap toStringMapper() {
901            LinkedHashMap m = new LinkedHashMap();
902            m.put("documentNumber", this.documentNumber);
903            return m;
904        }
905    
906        /**
907         * This method returns true if this document is a reversal for another document
908         * 
909         * @return
910         */
911        public boolean isInvoiceReversal() {
912            return ObjectUtils.isNotNull(getDocumentHeader().getFinancialDocumentInErrorNumber());
913        }
914    
915        /**
916         * @see org.kuali.kfs.sys.document.AccountingDocumentBase#isDebit(org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail)
917         */
918        @Override
919        public boolean isDebit(GeneralLedgerPendingEntrySourceDetail postable) {
920            return ((CustomerInvoiceDetail) postable).isDebit();
921        }
922    
923        /**
924         * @see org.kuali.kfs.sys.document.AccountingDocumentBase#getSourceAccountingLineClass()
925         */
926        @Override
927        public Class<CustomerInvoiceDetail> getSourceAccountingLineClass() {
928            return CustomerInvoiceDetail.class;
929        }
930    
931        /**
932         * Ensures that all the accounts receivable object codes are correctly updated
933         */
934        public void updateAccountReceivableObjectCodes() {
935            for (Iterator e = getSourceAccountingLines().iterator(); e.hasNext();) {
936                SpringContext.getBean(CustomerInvoiceDetailService.class).updateAccountsReceivableObjectCode(((CustomerInvoiceDetail) e.next()));
937            }
938        }
939    
940        /**
941         * This method creates the following GLPE's for the invoice 1. Debit to receivable for total line amount ( including sales tax
942         * if it exists ). 2. Credit to income based on item price * quantity. 3. Credit to state sales tax account/object code if state
943         * sales tax exists. 4. Credit to district sales tax account/object code if district sales tax exists.
944         * 
945         * @see org.kuali.kfs.service.impl.GenericGeneralLedgerPendingEntryGenerationProcessImpl#processGenerateGeneralLedgerPendingEntries(org.kuali.kfs.sys.document.GeneralLedgerPendingEntrySource,
946         *      org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail,
947         *      org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper)
948         */
949        @Override
950        public boolean generateGeneralLedgerPendingEntries(GeneralLedgerPendingEntrySourceDetail glpeSourceDetail, GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
951    
952            String receivableOffsetOption = SpringContext.getBean(ParameterService.class).getParameterValue(CustomerInvoiceDocument.class, ArConstants.GLPE_RECEIVABLE_OFFSET_GENERATION_METHOD);
953            boolean hasClaimOnCashOffset = ArConstants.GLPE_RECEIVABLE_OFFSET_GENERATION_METHOD_FAU.equals(receivableOffsetOption);
954    
955            addReceivableGLPEs(sequenceHelper, glpeSourceDetail, hasClaimOnCashOffset);
956            sequenceHelper.increment();
957            addIncomeGLPEs(sequenceHelper, glpeSourceDetail, hasClaimOnCashOffset);
958    
959            // if sales tax is enabled generate GLPEs
960            if (SpringContext.getBean(AccountsReceivableTaxService.class).isCustomerInvoiceDetailTaxable(this, (CustomerInvoiceDetail) glpeSourceDetail)) {
961                addSalesTaxGLPEs(sequenceHelper, glpeSourceDetail, hasClaimOnCashOffset);
962            }
963    
964    
965            return true;
966        }
967    
968    
969        /**
970         * This method creates the receivable GLPEs for each invoice detail line.
971         * 
972         * @param poster
973         * @param sequenceHelper
974         * @param postable
975         * @param explicitEntry
976         */
977        protected void addReceivableGLPEs(GeneralLedgerPendingEntrySequenceHelper sequenceHelper, GeneralLedgerPendingEntrySourceDetail glpeSourceDetail, boolean hasClaimOnCashOffset) {
978    
979            CustomerInvoiceDetail customerInvoiceDetail = (CustomerInvoiceDetail) glpeSourceDetail;
980            ReceivableCustomerInvoiceDetail receivableCustomerInvoiceDetail = new ReceivableCustomerInvoiceDetail(customerInvoiceDetail, this);
981            boolean isDebit = (!isInvoiceReversal() && !customerInvoiceDetail.isDiscountLine()) || (isInvoiceReversal() && customerInvoiceDetail.isDiscountLine());
982    
983            CustomerInvoiceGLPEService service = SpringContext.getBean(CustomerInvoiceGLPEService.class);
984            service.createAndAddGenericInvoiceRelatedGLPEs(this, receivableCustomerInvoiceDetail, sequenceHelper, isDebit, hasClaimOnCashOffset, customerInvoiceDetail.getInvoiceItemPreTaxAmount());
985        }
986    
987        /**
988         * This method adds pending entry with transaction ledger entry amount set to item price * quantity
989         * 
990         * @param poster
991         * @param sequenceHelper
992         * @param postable
993         * @param explicitEntry
994         */
995        protected void addIncomeGLPEs(GeneralLedgerPendingEntrySequenceHelper sequenceHelper, GeneralLedgerPendingEntrySourceDetail glpeSourceDetail, boolean hasClaimOnCashOffset) {
996    
997            CustomerInvoiceDetail customerInvoiceDetail = (CustomerInvoiceDetail) glpeSourceDetail;
998            boolean isDebit = (!isInvoiceReversal() && customerInvoiceDetail.isDiscountLine()) || (isInvoiceReversal() && !customerInvoiceDetail.isDiscountLine());
999    
1000            CustomerInvoiceGLPEService service = SpringContext.getBean(CustomerInvoiceGLPEService.class);
1001            service.createAndAddGenericInvoiceRelatedGLPEs(this, customerInvoiceDetail, sequenceHelper, isDebit, hasClaimOnCashOffset, customerInvoiceDetail.getInvoiceItemPreTaxAmount());
1002    
1003        }
1004    
1005        /**
1006         * This method add pending entries for every tax detail that exists for a particular postal code
1007         * 
1008         * @param sequenceHelper
1009         * @param glpeSourceDetail
1010         * @param hasClaimOnCashOffset
1011         */
1012        protected void addSalesTaxGLPEs(GeneralLedgerPendingEntrySequenceHelper sequenceHelper, GeneralLedgerPendingEntrySourceDetail glpeSourceDetail, boolean hasClaimOnCashOffset) {
1013    
1014            CustomerInvoiceDetail customerInvoiceDetail = (CustomerInvoiceDetail) glpeSourceDetail;
1015            boolean isDebit = (!isInvoiceReversal() && customerInvoiceDetail.isDiscountLine()) || (isInvoiceReversal() && !customerInvoiceDetail.isDiscountLine());
1016    
1017            String postalCode = SpringContext.getBean(AccountsReceivableTaxService.class).getPostalCodeForTaxation(this);
1018            Date dateOfTransaction = SpringContext.getBean(DateTimeService.class).getCurrentSqlDate();
1019    
1020            List<TaxDetail> salesTaxDetails = SpringContext.getBean(TaxService.class).getSalesTaxDetails(dateOfTransaction, postalCode, customerInvoiceDetail.getInvoiceItemPreTaxAmount());
1021    
1022            CustomerInvoiceGLPEService service = SpringContext.getBean(CustomerInvoiceGLPEService.class);
1023            SalesTaxCustomerInvoiceDetail salesTaxCustomerInvoiceDetail;
1024            ReceivableCustomerInvoiceDetail receivableCustomerInvoiceDetail;
1025            for (TaxDetail salesTaxDetail : salesTaxDetails) {
1026    
1027                salesTaxCustomerInvoiceDetail = new SalesTaxCustomerInvoiceDetail(salesTaxDetail, customerInvoiceDetail);
1028                receivableCustomerInvoiceDetail = new ReceivableCustomerInvoiceDetail(salesTaxCustomerInvoiceDetail, this);
1029    
1030                sequenceHelper.increment();
1031                service.createAndAddGenericInvoiceRelatedGLPEs(this, receivableCustomerInvoiceDetail, sequenceHelper, !isDebit, hasClaimOnCashOffset, salesTaxDetail.getTaxAmount());
1032    
1033                sequenceHelper.increment();
1034                service.createAndAddGenericInvoiceRelatedGLPEs(this, salesTaxCustomerInvoiceDetail, sequenceHelper, isDebit, hasClaimOnCashOffset, salesTaxDetail.getTaxAmount());
1035            }
1036        }
1037    
1038        /**
1039         * Returns an implementation of the GeneralLedgerPendingEntryService
1040         * 
1041         * @return an implementation of the GeneralLedgerPendingEntryService
1042         */
1043        public GeneralLedgerPendingEntryService getGeneralLedgerPendingEntryService() {
1044            return SpringContext.getBean(GeneralLedgerPendingEntryService.class);
1045        }
1046    
1047        /**
1048         * Returns a map with the primitive field names as the key and the primitive values as the map value.
1049         * 
1050         * @return Map
1051         */
1052        @SuppressWarnings("unchecked")
1053        public Map getValuesMap() {
1054            Map valuesMap = new HashMap();
1055    
1056            valuesMap.put("postingYear", getPostingYear());
1057            valuesMap.put("paymentChartOfAccountsCode", getPaymentChartOfAccountsCode());
1058            valuesMap.put("paymentAccountNumber", getPaymentAccountNumber());
1059            valuesMap.put("paymentFinancialObjectCode", getPaymentFinancialObjectCode());
1060            valuesMap.put("paymentSubAccountNumber", getPaymentSubAccountNumber());
1061            valuesMap.put("paymentFinancialSubObjectCode", getPaymentFinancialSubObjectCode());
1062            valuesMap.put("paymentProjectCode", getPaymentProjectCode());
1063            return valuesMap;
1064        }
1065    
1066        @Override
1067        public List<Long> getWorkflowEngineDocumentIdsToLock() {
1068            //  add the invoice number of the Error Corrected doc, if this is an error correction
1069            if (this.isInvoiceReversal()) {
1070                if (StringUtils.isNotBlank(getDocumentHeader().getFinancialDocumentInErrorNumber())) {
1071                    List<Long> documentIds = new ArrayList<Long>();
1072                    documentIds.add(new Long(getDocumentHeader().getFinancialDocumentInErrorNumber()));
1073                    return documentIds;
1074                }
1075            }
1076            return null;
1077        }
1078    
1079        /**
1080         * When document is processed do the following: 1) Set the billingDate to today's date if not already set 2) If there are
1081         * discounts, create corresponding invoice paid applied rows 3) If the document is a reversal, in addition to reversing paid
1082         * applied rows, update the open paid applied indicator
1083         * 
1084         * @see org.kuali.kfs.sys.document.GeneralLedgerPostingDocumentBase#doRouteStatusChange()
1085         */
1086        @Override
1087        public void doRouteStatusChange(DocumentRouteStatusChangeDTO statusChangeEvent) {
1088            super.doRouteStatusChange(statusChangeEvent);
1089            
1090            //  fast-exit if status != P
1091            if (!getDocumentHeader().getWorkflowDocument().stateIsProcessed()) {
1092                return;
1093            }
1094            
1095            //  wire up the billing date
1096            if (ObjectUtils.isNull(getBillingDate())) {
1097                setBillingDate(SpringContext.getBean(DateTimeService.class).getCurrentSqlDateMidnight());
1098            }
1099            
1100            // apply discounts
1101            CustomerInvoiceDocumentService invoiceService = SpringContext.getBean(CustomerInvoiceDocumentService.class);
1102            invoiceService.convertDiscountsToPaidApplieds(this);
1103            
1104            //  handle a Correction/Reversal document
1105            if (this.isInvoiceReversal()) {
1106                CustomerInvoiceDocument correctedCustomerInvoiceDocument;
1107                try {
1108                    correctedCustomerInvoiceDocument = (CustomerInvoiceDocument) SpringContext.getBean(DocumentService.class).getByDocumentHeaderId(this.getDocumentHeader().getFinancialDocumentInErrorNumber());
1109                }
1110                catch (WorkflowException e) {
1111                    throw new RuntimeException("Cannot find customer invoice document with id " + this.getDocumentHeader().getFinancialDocumentInErrorNumber());
1112                }
1113    
1114                // if reversal, close both this reversal invoice and the original invoice
1115                SpringContext.getBean(CustomerInvoiceDocumentService.class).closeCustomerInvoiceDocument(correctedCustomerInvoiceDocument);
1116                SpringContext.getBean(CustomerInvoiceDocumentService.class).closeCustomerInvoiceDocument(this);
1117            }
1118            
1119            //  handle Recurrence 
1120            if (ObjectUtils.isNull(this.getCustomerInvoiceRecurrenceDetails()) || 
1121                    (ObjectUtils.isNull(this.getCustomerInvoiceRecurrenceDetails().getDocumentRecurrenceBeginDate()) 
1122                    && ObjectUtils.isNull(this.getCustomerInvoiceRecurrenceDetails().getDocumentRecurrenceEndDate()) 
1123                    && ObjectUtils.isNull(this.getCustomerInvoiceRecurrenceDetails().getDocumentRecurrenceIntervalCode()) 
1124                    && ObjectUtils.isNull(this.getCustomerInvoiceRecurrenceDetails().getDocumentTotalRecurrenceNumber()) 
1125                    && ObjectUtils.isNull(this.getCustomerInvoiceRecurrenceDetails().getDocumentInitiatorUserIdentifier()))) {
1126            }
1127            else {
1128                // set new user session to recurrence initiator
1129                UserSession currentSession = GlobalVariables.getUserSession();
1130                GlobalVariables.setUserSession(new UserSession(KFSConstants.SYSTEM_USER));
1131    
1132                // populate InvoiceRecurrence business object
1133                InvoiceRecurrence newInvoiceRecurrence = new InvoiceRecurrence();
1134                newInvoiceRecurrence.setInvoiceNumber(this.getCustomerInvoiceRecurrenceDetails().getInvoiceNumber());
1135                newInvoiceRecurrence.setCustomerNumber(this.getCustomerInvoiceRecurrenceDetails().getCustomerNumber());
1136                newInvoiceRecurrence.setDocumentRecurrenceBeginDate(this.getCustomerInvoiceRecurrenceDetails().getDocumentRecurrenceBeginDate());
1137                newInvoiceRecurrence.setDocumentRecurrenceEndDate(this.getCustomerInvoiceRecurrenceDetails().getDocumentRecurrenceEndDate());
1138                newInvoiceRecurrence.setDocumentRecurrenceIntervalCode(this.getCustomerInvoiceRecurrenceDetails().getDocumentRecurrenceIntervalCode());
1139                newInvoiceRecurrence.setDocumentTotalRecurrenceNumber(this.getCustomerInvoiceRecurrenceDetails().getDocumentTotalRecurrenceNumber());
1140                newInvoiceRecurrence.setDocumentInitiatorUserIdentifier(this.getCustomerInvoiceRecurrenceDetails().getDocumentInitiatorUserIdentifier());
1141                newInvoiceRecurrence.setActive(this.getCustomerInvoiceRecurrenceDetails().isActive());
1142    
1143                // create a new InvoiceRecurrenceMaintenanceDocument
1144                MaintenanceDocument invoiceRecurrenceMaintDoc = null;
1145                try {
1146                    invoiceRecurrenceMaintDoc = (MaintenanceDocument) SpringContext.getBean(DocumentService.class).getNewDocument(getInvoiceRecurrenceMaintenanceDocumentTypeName());
1147                }
1148                catch (WorkflowException e1) {
1149                    throw new RuntimeException("Cannot create new Invoice Recurrence Maintenance Document.");
1150                }
1151                invoiceRecurrenceMaintDoc.getDocumentHeader().setDocumentDescription("Automatically created from Invoice");
1152                invoiceRecurrenceMaintDoc.getNewMaintainableObject().setBusinessObject(newInvoiceRecurrence);
1153    
1154                try {
1155                    // blanket approve the INVR, bypassing everything
1156                    //invoiceRecurrenceMaintDoc.getDocumentHeader().getWorkflowDocument().blanketApprove("Blanket Approved by the creating Invoice Document #" + getDocumentNumber());
1157                    //TODO temporarily just do regular route until we can get blanket approve perms setup for KFS
1158                    SpringContext.getBean(DocumentService.class).saveDocument(invoiceRecurrenceMaintDoc);
1159                    invoiceRecurrenceMaintDoc.getDocumentHeader().getWorkflowDocument().routeDocument("Automatically created and routed by CustomerInvoiceDocument #" + getDocumentNumber() + ".");
1160                }
1161                catch (WorkflowException e) {
1162                    throw new RuntimeException("Cannot route Invoice Recurrence Maintenance Document with id " + invoiceRecurrenceMaintDoc.getDocumentNumber() + ".");
1163                }
1164                
1165                // return the session to the original initiator
1166                GlobalVariables.setUserSession(currentSession);
1167                    
1168            }
1169        }
1170        
1171        protected String getInvoiceRecurrenceMaintenanceDocumentTypeName() {
1172            return "INVR";
1173        }
1174    
1175        /**
1176         * If this invoice is a reversal, set the open indicator to false
1177         * 
1178         * @see org.kuali.kfs.sys.document.FinancialSystemTransactionalDocumentBase#prepareForSave()
1179         */
1180        @Override
1181        public void prepareForSave() {
1182            if (this.isInvoiceReversal()) {
1183                setOpenInvoiceIndicator(false);
1184            }
1185            
1186            //  make sure the docHeader gets its doc total right.  This is here because there's an ordering 
1187            // bug in the struts classes for invoice that is preventing this from being set right.  There is 
1188            // probably a better way to fix this that can be pursued later.
1189            getDocumentHeader().setFinancialDocumentTotalAmount(getTotalDollarAmount());
1190            
1191            //  invoice recurrence stuff, if there is a recurrence object
1192            if (ObjectUtils.isNotNull(this.getCustomerInvoiceRecurrenceDetails()) && getProcessRecurrenceFlag()) {
1193    
1194                //  wire up the recurrence customer number if one exists
1195                if (ObjectUtils.isNull(this.getCustomerInvoiceRecurrenceDetails().getCustomerNumber())) {
1196                    this.getCustomerInvoiceRecurrenceDetails().setCustomerNumber(this.getAccountsReceivableDocumentHeader().getCustomerNumber());
1197                }
1198    
1199                customerInvoiceRecurrenceDetails.setInvoiceNumber(getDocumentNumber());
1200    
1201                // calc recurrence number if only end-date specified
1202                if (ObjectUtils.isNull(this.getCustomerInvoiceRecurrenceDetails().getDocumentTotalRecurrenceNumber()) && ObjectUtils.isNotNull(this.getCustomerInvoiceRecurrenceDetails().getDocumentRecurrenceEndDate())) {
1203    
1204                    Calendar beginCalendar = Calendar.getInstance();
1205                    beginCalendar.setTime(this.getCustomerInvoiceRecurrenceDetails().getDocumentRecurrenceBeginDate());
1206                    Date beginDate = this.getCustomerInvoiceRecurrenceDetails().getDocumentRecurrenceBeginDate();
1207                    Calendar endCalendar = Calendar.getInstance();
1208    
1209                    endCalendar.setTime(this.getCustomerInvoiceRecurrenceDetails().getDocumentRecurrenceEndDate());
1210                    Date endDate = this.getCustomerInvoiceRecurrenceDetails().getDocumentRecurrenceEndDate();
1211                    Calendar nextCalendar = Calendar.getInstance();
1212                    Date nextDate = beginDate;
1213    
1214                    int totalRecurrences = 0;
1215                    int addCounter = 0;
1216                    String intervalCode = this.getCustomerInvoiceRecurrenceDetails().getDocumentRecurrenceIntervalCode();
1217                    if (intervalCode.equals("M")) {
1218                        addCounter = 1;
1219                    }
1220                    if (intervalCode.equals("Q")) {
1221                        addCounter = 3;
1222                    }
1223                    /* perform this loop while begin_date is less than or equal to end_date */
1224                    while (!(beginDate.after(endDate))) {
1225                        beginCalendar.setTime(beginDate);
1226                        beginCalendar.add(Calendar.MONTH, addCounter);
1227                        beginDate = DateUtils.convertToSqlDate(beginCalendar.getTime());
1228                        totalRecurrences++;
1229    
1230                        nextDate = beginDate;
1231                        nextCalendar.setTime(nextDate);
1232                        nextCalendar.add(Calendar.MONTH, addCounter);
1233                        nextDate = DateUtils.convertToSqlDate(nextCalendar.getTime());
1234                        if (endDate.after(beginDate) && endDate.before(nextDate)) {
1235                            totalRecurrences++;
1236                            break;
1237                        }
1238                    }
1239                    if (totalRecurrences > 0) {
1240                        this.getCustomerInvoiceRecurrenceDetails().setDocumentTotalRecurrenceNumber(totalRecurrences);
1241                    }
1242                }
1243                
1244                //  calc end-date if only recurrence-number is specified
1245                if (ObjectUtils.isNotNull(this.getCustomerInvoiceRecurrenceDetails().getDocumentTotalRecurrenceNumber()) && ObjectUtils.isNull(this.getCustomerInvoiceRecurrenceDetails().getDocumentRecurrenceEndDate())) {
1246    
1247                    Calendar beginCalendar = Calendar.getInstance();
1248                    beginCalendar.setTime(new Timestamp(this.getCustomerInvoiceRecurrenceDetails().getDocumentRecurrenceBeginDate().getTime()));
1249                    Calendar endCalendar = Calendar.getInstance();
1250                    endCalendar = beginCalendar;
1251    
1252                    int addCounter = 0;
1253                    Integer documentTotalRecurrenceNumber = this.getCustomerInvoiceRecurrenceDetails().getDocumentTotalRecurrenceNumber();
1254                    String intervalCode = this.getCustomerInvoiceRecurrenceDetails().getDocumentRecurrenceIntervalCode();
1255                    if (intervalCode.equals("M")) {
1256                        addCounter = -1;
1257                        addCounter += documentTotalRecurrenceNumber * 1;
1258                    }
1259                    if (intervalCode.equals("Q")) {
1260                        addCounter = -3;
1261                        addCounter += documentTotalRecurrenceNumber * 3;
1262                    }
1263                    endCalendar.add(Calendar.MONTH, addCounter);
1264                    this.getCustomerInvoiceRecurrenceDetails().setDocumentRecurrenceEndDate(DateUtils.convertToSqlDate(endCalendar.getTime()));
1265                }
1266            }
1267            
1268            // Force upper case
1269            setBilledByOrganizationCode(getBilledByOrganizationCode().toUpperCase());
1270    
1271            if (ObjectUtils.isNull(getCustomerShipToAddressIdentifier())) {
1272                setCustomerShipToAddress(null);
1273                setCustomerShipToAddressOnInvoice(null);
1274            }
1275            
1276        }
1277        
1278        // returns true only when there is all the required recurrence info
1279        public boolean getProcessRecurrenceFlag() {
1280                CustomerInvoiceRecurrenceDetails rec = this.getCustomerInvoiceRecurrenceDetails();
1281            
1282            boolean processRecurrenceFlag = (null != rec.getDocumentRecurrenceIntervalCode());
1283            processRecurrenceFlag &= (null != rec.getDocumentRecurrenceBeginDate());
1284            processRecurrenceFlag &= ( (null != rec.getDocumentRecurrenceEndDate()) || (null != rec.getDocumentTotalRecurrenceNumber()));
1285            processRecurrenceFlag &= (rec.isActive());
1286            processRecurrenceFlag &= (null != rec.getDocumentInitiatorUserIdentifier());
1287            
1288            return processRecurrenceFlag;
1289                }
1290    
1291        // returns true only if there is no recurrence data at all in recurrence tab 
1292        public boolean getNoRecurrenceDataFlag() {
1293            CustomerInvoiceRecurrenceDetails rec = this.getCustomerInvoiceRecurrenceDetails();
1294            
1295            boolean noRecurrenceDataFlag = ObjectUtils.isNull(rec.getDocumentRecurrenceIntervalCode());
1296            noRecurrenceDataFlag &= ObjectUtils.isNull(rec.getDocumentRecurrenceBeginDate());
1297            noRecurrenceDataFlag &= ObjectUtils.isNull(rec.getDocumentRecurrenceEndDate());
1298            noRecurrenceDataFlag &= !rec.isActive();
1299            noRecurrenceDataFlag &= ObjectUtils.isNull(rec.getDocumentTotalRecurrenceNumber());
1300            noRecurrenceDataFlag &= ObjectUtils.isNull(rec.getDocumentInitiatorUserIdentifier());
1301    
1302            return noRecurrenceDataFlag;
1303        }
1304    
1305        /**
1306         * @see org.kuali.kfs.sys.document.AccountingDocumentBase#toCopy()
1307         */
1308        @Override
1309        public void toCopy() throws WorkflowException {
1310            super.toCopy();
1311            CustomerInvoiceDocumentService customerInvoiceDocumentService = SpringContext.getBean(CustomerInvoiceDocumentService.class);
1312            customerInvoiceDocumentService.setupDefaultValuesForCopiedCustomerInvoiceDocument(this);
1313            this.getDocumentHeader().setFinancialDocumentTotalAmount(getTotalDollarAmount());
1314        }
1315    
1316        /**
1317         * @see org.kuali.kfs.sys.document.GeneralLedgerPostingDocumentBase#toErrorCorrection()
1318         */
1319        @Override
1320        public void toErrorCorrection() throws WorkflowException {
1321            super.toErrorCorrection();
1322            negateCustomerInvoiceDetailUnitPrices();
1323            this.setOpenInvoiceIndicator(false);
1324            this.getDocumentHeader().setFinancialDocumentTotalAmount(getTotalDollarAmount());
1325            
1326            //  if we dont force this on the error correction, the recurrence will 
1327            // have the old doc number, and will revert the main doc due to OJB fun, 
1328            // which will cause PK unique index failure.
1329            if (ObjectUtils.isNotNull(customerInvoiceRecurrenceDetails)) {
1330                customerInvoiceRecurrenceDetails.setInvoiceNumber(this.documentNumber);
1331            }
1332        }
1333    
1334    
1335        /**
1336         * This method...
1337         */
1338        @SuppressWarnings("unchecked")
1339        public void negateCustomerInvoiceDetailUnitPrices() {
1340            CustomerInvoiceDetail customerInvoiceDetail;
1341            for (Iterator i = getSourceAccountingLines().iterator(); i.hasNext();) {
1342                customerInvoiceDetail = (CustomerInvoiceDetail) i.next();
1343                customerInvoiceDetail.setInvoiceItemUnitPrice(customerInvoiceDetail.getInvoiceItemUnitPrice().negate());
1344                
1345                //clear the old CustomerInvoiceDocument
1346                customerInvoiceDetail.setCustomerInvoiceDocument(null);
1347    
1348                // revert changes for custom invoice error correction
1349                //SpringContext.getBean(CustomerInvoiceDetailService.class).prepareCustomerInvoiceDetailForErrorCorrection(customerInvoiceDetail, this);            
1350            }
1351        }
1352    
1353        /**
1354         * This method returns true if invoice document has at least one discount line
1355         * 
1356         * @return
1357         */
1358        @SuppressWarnings("unchecked")
1359        public boolean hasAtLeastOneDiscount() {
1360    
1361            CustomerInvoiceDetail customerInvoiceDetail;
1362            for (Iterator i = getSourceAccountingLines().iterator(); i.hasNext();) {
1363                customerInvoiceDetail = (CustomerInvoiceDetail) i.next();
1364                if (customerInvoiceDetail.isDiscountLineParent()) {
1365                    return true;
1366                }
1367            }
1368            return false;
1369        }
1370    
1371        /**
1372         * This method returns true if line number is discount line number based on sequence number
1373         * 
1374         * @param sequenceNumber
1375         * @return
1376         */
1377        @SuppressWarnings("unchecked")
1378        public boolean isDiscountLineBasedOnSequenceNumber(Integer sequenceNumber) {
1379            if (ObjectUtils.isNull(sequenceNumber)) {
1380                return false;
1381            }
1382    
1383            CustomerInvoiceDetail customerInvoiceDetail;
1384            for (Iterator i = getSourceAccountingLines().iterator(); i.hasNext();) {
1385                customerInvoiceDetail = (CustomerInvoiceDetail) i.next();
1386                Integer discLineNum = customerInvoiceDetail.getInvoiceItemDiscountLineNumber();
1387    
1388                // check if sequence number is referenced as a discount line for another customer invoice detail (i.e. the parent line)
1389                if (ObjectUtils.isNotNull(discLineNum) && sequenceNumber.equals(customerInvoiceDetail.getInvoiceItemDiscountLineNumber())) {
1390                    return true;
1391                }
1392            }
1393            return false;
1394        }
1395    
1396        /**
1397         * This method returns parent customer invoice detail based on child discount sequence number
1398         * 
1399         * @param sequenceNumber
1400         * @return
1401         */
1402        @SuppressWarnings("unchecked")
1403        public CustomerInvoiceDetail getParentLineBasedOnDiscountSequenceNumber(Integer discountSequenceNumber) {
1404    
1405            if (ObjectUtils.isNull(discountSequenceNumber)) {
1406                return null;
1407            }
1408    
1409            CustomerInvoiceDetail customerInvoiceDetail;
1410            for (Iterator i = getSourceAccountingLines().iterator(); i.hasNext();) {
1411                customerInvoiceDetail = (CustomerInvoiceDetail) i.next();
1412                Integer discLineNum = customerInvoiceDetail.getInvoiceItemDiscountLineNumber();
1413                if (ObjectUtils.isNotNull(discLineNum) && discountSequenceNumber.equals(customerInvoiceDetail.getInvoiceItemDiscountLineNumber())) {
1414                    return customerInvoiceDetail;
1415                }
1416            }
1417            return null;
1418        }
1419    
1420    
1421        /**
1422         * This method is called on CustomerInvoiceDocumentAction.execute() to set isDiscount to true if it truly is a discount line
1423         */
1424        @SuppressWarnings("unchecked")
1425        public void updateDiscountAndParentLineReferences() {
1426    
1427            CustomerInvoiceDetail discount;
1428            for (Iterator i = getSourceAccountingLines().iterator(); i.hasNext();) {
1429                discount = (CustomerInvoiceDetail) i.next();
1430    
1431                // get sequence number and check if theres a corresponding parent line for that discount line
1432                CustomerInvoiceDetail parent = getParentLineBasedOnDiscountSequenceNumber(discount.getSequenceNumber());
1433                if (ObjectUtils.isNotNull(parent)) {
1434                    discount.setParentDiscountCustomerInvoiceDetail(parent);
1435                    parent.setDiscountCustomerInvoiceDetail(discount);
1436                }
1437                else {
1438                    discount.setParentDiscountCustomerInvoiceDetail(null);
1439                }
1440            }
1441        }
1442    
1443        /**
1444         * This method removes the corresponding discount line based on the index of the parent line index. This assumes that the
1445         * discount line is ALWAYS after the index of the parent line.
1446         * 
1447         * @param deleteIndex
1448         */
1449        public void removeDiscountLineBasedOnParentLineIndex(int parentLineIndex) {
1450            // get parent line line
1451            CustomerInvoiceDetail parentLine = (CustomerInvoiceDetail) getSourceAccountingLines().get(parentLineIndex);
1452    
1453            // get index for discount line
1454            int discountLineIndex = -1; // this should ALWAYS get set
1455            for (int i = 0; i < getSourceAccountingLines().size(); i++) {
1456                if (parentLine.getInvoiceItemDiscountLineNumber().equals(((CustomerInvoiceDetail) getSourceAccountingLines().get(i)).getSequenceNumber())) {
1457                    discountLineIndex = i;
1458                }
1459            }
1460            // remove discount line
1461            getSourceAccountingLines().remove(discountLineIndex);
1462        }
1463    
1464        public CustomerInvoiceRecurrenceDetails getCustomerInvoiceRecurrenceDetails() {
1465            return customerInvoiceRecurrenceDetails;
1466        }
1467    
1468        public void setCustomerInvoiceRecurrenceDetails(CustomerInvoiceRecurrenceDetails customerInvoiceRecurrenceDetails) {
1469            this.customerInvoiceRecurrenceDetails = customerInvoiceRecurrenceDetails;
1470        }
1471    
1472        public CustomerAddress getCustomerShipToAddress() {
1473            return customerShipToAddress;
1474        }
1475    
1476        public void setCustomerShipToAddress(CustomerAddress customerShipToAddress) {
1477            this.customerShipToAddress = customerShipToAddress;
1478        }
1479    
1480        public CustomerAddress getCustomerBillToAddress() {
1481            return customerBillToAddress;
1482        }
1483    
1484        public void setCustomerBillToAddress(CustomerAddress customerBillToAddress) {
1485            this.customerBillToAddress = customerBillToAddress;
1486        }
1487    
1488        public PrintInvoiceOptions getPrintInvoiceOption() {
1489            if (ObjectUtils.isNull(printInvoiceOption) && StringUtils.isNotEmpty(printInvoiceIndicator)){
1490                refreshReferenceObject("printInvoiceOption");
1491            }
1492            return printInvoiceOption;
1493        }
1494    
1495        public void setPrintInvoiceOption(PrintInvoiceOptions printInvoiceOption) {
1496            this.printInvoiceOption = printInvoiceOption;
1497        }
1498    
1499        /**
1500         * This method returns the total of all pre tax amounts for all customer invoice detail lines
1501         * 
1502         * @return
1503         */
1504        public KualiDecimal getInvoiceItemPreTaxAmountTotal() {
1505    
1506            KualiDecimal invoiceItemPreTaxAmountTotal = new KualiDecimal(0);
1507            for (Iterator i = getSourceAccountingLines().iterator(); i.hasNext();) {
1508                invoiceItemPreTaxAmountTotal = invoiceItemPreTaxAmountTotal.add(((CustomerInvoiceDetail) i.next()).getInvoiceItemPreTaxAmount());
1509            }
1510            return invoiceItemPreTaxAmountTotal;
1511        }
1512    
1513        /**
1514         * This method returns the total of all tax amounts for all customer invoice detail lines
1515         * 
1516         * @return
1517         */
1518        public KualiDecimal getInvoiceItemTaxAmountTotal() {
1519    
1520            KualiDecimal invoiceItemTaxAmountTotal = new KualiDecimal(0);
1521            for (Iterator i = getSourceAccountingLines().iterator(); i.hasNext();) {
1522                invoiceItemTaxAmountTotal = invoiceItemTaxAmountTotal.add(((CustomerInvoiceDetail) i.next()).getInvoiceItemTaxAmount());
1523            }
1524            return invoiceItemTaxAmountTotal;
1525        }
1526    
1527        /**
1528         * This method returns the primary customer address for the customer number provided.
1529         * 
1530         * @return
1531         */
1532        public CustomerAddress getPrimaryAddressForCustomerNumber() {
1533            if (ObjectUtils.isNotNull(accountsReceivableDocumentHeader) && StringUtils.isNotEmpty(accountsReceivableDocumentHeader.getCustomerNumber())) {
1534                return SpringContext.getBean(CustomerAddressService.class).getPrimaryAddress(accountsReceivableDocumentHeader.getCustomerNumber());
1535            }
1536            return null;
1537        }
1538    
1539        /**
1540         * This method returns the customer object for the invoice
1541         * 
1542         * @return
1543         */
1544        public Customer getCustomer() {
1545            if (ObjectUtils.isNotNull(accountsReceivableDocumentHeader)) {
1546                return accountsReceivableDocumentHeader.getCustomer();
1547            }
1548            return null;
1549        }
1550    
1551        /**
1552         * This method will return all the customer invoice details excluding discount invoice detail lines.
1553         * 
1554         * @return
1555         */
1556        public List<CustomerInvoiceDetail> getCustomerInvoiceDetailsWithoutDiscounts() {
1557            List<CustomerInvoiceDetail> customerInvoiceDetailsWithoutDiscounts = new TypedArrayList(CustomerInvoiceDetail.class);
1558    
1559            updateDiscountAndParentLineReferences();
1560    
1561            List<CustomerInvoiceDetail> customerInvoiceDetailsWithDiscounts = getSourceAccountingLines();
1562            for (CustomerInvoiceDetail customerInvoiceDetail : customerInvoiceDetailsWithDiscounts) {
1563                if (!customerInvoiceDetail.isDiscountLine()) {
1564                    customerInvoiceDetail.setDocumentNumber(getDocumentNumber());
1565                    customerInvoiceDetailsWithoutDiscounts.add(customerInvoiceDetail);
1566                }
1567            }
1568    
1569            return customerInvoiceDetailsWithoutDiscounts;
1570        }
1571    
1572        //TODO Andrew
1573    //    /**
1574    //     * This method could be a bit dangerous. It's meant to be used only on the payment application document, where the modified
1575    //     * invoice is never saved.
1576    //     * 
1577    //     * @param customerInvoiceDetails
1578    //     */
1579    //    public void setCustomerInvoiceDetailsWithoutDiscounts(List<CustomerInvoiceDetail> customerInvoiceDetails) {
1580    //        List<CustomerInvoiceDetail> customerInvoiceDetailsWithoutDiscounts = getSourceAccountingLines();
1581    //        int sequenceCounter = 0;
1582    //        for (CustomerInvoiceDetail customerInvoiceDetail : customerInvoiceDetailsWithoutDiscounts) {
1583    //            for (CustomerInvoiceDetail revisedCustomerInvoiceDetail : customerInvoiceDetails) {
1584    //                if (!customerInvoiceDetail.isDiscountLine() && customerInvoiceDetail.getSequenceNumber().equals(revisedCustomerInvoiceDetail.getSequenceNumber())) {
1585    //                    customerInvoiceDetailsWithoutDiscounts.remove(sequenceCounter);
1586    //                    customerInvoiceDetailsWithoutDiscounts.add(sequenceCounter, revisedCustomerInvoiceDetail);
1587    //                }
1588    //            }
1589    //            sequenceCounter += 1;
1590    //        }
1591    //        setSourceAccountingLines(customerInvoiceDetailsWithoutDiscounts);
1592    //    }
1593    
1594        /**
1595         * This method will return all the customer invoice details that are discounts
1596         * 
1597         * @return
1598         */
1599        public List<CustomerInvoiceDetail> getDiscounts() {
1600            List<CustomerInvoiceDetail> discounts = new TypedArrayList(CustomerInvoiceDetail.class);
1601    
1602            updateDiscountAndParentLineReferences();
1603    
1604            List<CustomerInvoiceDetail> customerInvoiceDetailsWithDiscounts = getSourceAccountingLines();
1605            for (CustomerInvoiceDetail customerInvoiceDetail : customerInvoiceDetailsWithDiscounts) {
1606                if (customerInvoiceDetail.isDiscountLine()) {
1607                    customerInvoiceDetail.setDocumentNumber(getDocumentNumber());
1608                    discounts.add(customerInvoiceDetail);
1609                }
1610            }
1611    
1612            return discounts;
1613        }
1614    
1615        public int compareTo(CustomerInvoiceDocument customerInvoiceDocument) {
1616            if (this.getBillByChartOfAccountCode().equals(customerInvoiceDocument.getBillByChartOfAccountCode()))
1617                if (this.getBilledByOrganizationCode().equals(customerInvoiceDocument.getBilledByOrganizationCode()))
1618                    return 0;
1619            return -1;
1620        }
1621    
1622        /**
1623         * 
1624         * Returns whether or not the Invoice would be paid off by applying the additional amount, passed in 
1625         * by the parameter.
1626         * 
1627         * @param additionalAmountToApply The additional applied amount to test against.
1628         * @return True if applying the additionalAmountToApply parameter amount would bring the OpenAmount to zero.
1629         */
1630        public boolean wouldPayOff(KualiDecimal additionalAmountToApply) {
1631            KualiDecimal openAmount = getOpenAmount();
1632            return KualiDecimal.ZERO.isGreaterEqual(openAmount.subtract(additionalAmountToApply));
1633        }
1634    
1635        @Override
1636        public KualiDecimal getTotalDollarAmount() {
1637            return getSourceTotal();
1638        }
1639    
1640        public String getBillingAddressInternationalProvinceName() {
1641            return billingAddressInternationalProvinceName;
1642        }
1643    
1644        public void setBillingAddressInternationalProvinceName(String billingAddressInternationalProvinceName) {
1645            this.billingAddressInternationalProvinceName = billingAddressInternationalProvinceName;
1646        }
1647    
1648        public String getBillingAddressName() {
1649            return billingAddressName;
1650        }
1651    
1652        public void setBillingAddressName(String billingAddressName) {
1653            this.billingAddressName = billingAddressName;
1654        }
1655    
1656        public String getBillingAddressTypeCode() {
1657            return billingAddressTypeCode;
1658        }
1659    
1660        public void setBillingAddressTypeCode(String billingAddressTypeCode) {
1661            this.billingAddressTypeCode = billingAddressTypeCode;
1662        }
1663    
1664        public String getBillingCityName() {
1665            return billingCityName;
1666        }
1667    
1668        public void setBillingCityName(String billingCityName) {
1669            this.billingCityName = billingCityName;
1670        }
1671    
1672        public String getBillingCountryCode() {
1673            return billingCountryCode;
1674        }
1675    
1676        public void setBillingCountryCode(String billingCountryCode) {
1677            this.billingCountryCode = billingCountryCode;
1678        }
1679    
1680        public String getBillingEmailAddress() {
1681            return billingEmailAddress;
1682        }
1683    
1684        public void setBillingEmailAddress(String billingEmailAddress) {
1685            this.billingEmailAddress = billingEmailAddress;
1686        }
1687    
1688        public String getBillingInternationalMailCode() {
1689            return billingInternationalMailCode;
1690        }
1691    
1692        public void setBillingInternationalMailCode(String billingInternationalMailCode) {
1693            this.billingInternationalMailCode = billingInternationalMailCode;
1694        }
1695    
1696        public String getBillingStateCode() {
1697            return billingStateCode;
1698        }
1699    
1700        public void setBillingStateCode(String billingStateCode) {
1701            this.billingStateCode = billingStateCode;
1702        }
1703    
1704        public String getBillingZipCode() {
1705            return billingZipCode;
1706        }
1707    
1708        public void setBillingZipCode(String billingZipCode) {
1709            this.billingZipCode = billingZipCode;
1710        }
1711    
1712        public String getCustomerName() {
1713            return customerName;
1714        }
1715    
1716        public void setCustomerName(String customerName) {
1717            this.customerName = customerName;
1718        }
1719    
1720        public String getShippingAddressInternationalProvinceName() {
1721            return shippingAddressInternationalProvinceName;
1722        }
1723    
1724        public void setShippingAddressInternationalProvinceName(String shippingAddressInternationalProvinceName) {
1725            this.shippingAddressInternationalProvinceName = shippingAddressInternationalProvinceName;
1726        }
1727    
1728        public String getShippingAddressName() {
1729            return shippingAddressName;
1730        }
1731    
1732        public void setShippingAddressName(String shippingAddressName) {
1733            this.shippingAddressName = shippingAddressName;
1734        }
1735    
1736        public String getShippingAddressTypeCode() {
1737            return shippingAddressTypeCode;
1738        }
1739    
1740        public void setShippingAddressTypeCode(String shippingAddressTypeCode) {
1741            this.shippingAddressTypeCode = shippingAddressTypeCode;
1742        }
1743    
1744        public String getShippingCityName() {
1745            return shippingCityName;
1746        }
1747    
1748        public void setShippingCityName(String shippingCityName) {
1749            this.shippingCityName = shippingCityName;
1750        }
1751    
1752        public String getShippingCountryCode() {
1753            return shippingCountryCode;
1754        }
1755    
1756        public void setShippingCountryCode(String shippingCountryCode) {
1757            this.shippingCountryCode = shippingCountryCode;
1758        }
1759    
1760        public String getShippingEmailAddress() {
1761            return shippingEmailAddress;
1762        }
1763    
1764        public void setShippingEmailAddress(String shippingEmailAddress) {
1765            this.shippingEmailAddress = shippingEmailAddress;
1766        }
1767    
1768        public String getShippingInternationalMailCode() {
1769            return shippingInternationalMailCode;
1770        }
1771    
1772        public void setShippingInternationalMailCode(String shippingInternationalMailCode) {
1773            this.shippingInternationalMailCode = shippingInternationalMailCode;
1774        }
1775    
1776        public String getShippingStateCode() {
1777            return shippingStateCode;
1778        }
1779    
1780        public void setShippingStateCode(String shippingStateCode) {
1781            this.shippingStateCode = shippingStateCode;
1782        }
1783    
1784        public String getShippingZipCode() {
1785            return shippingZipCode;
1786        }
1787    
1788        public void setShippingZipCode(String shippingZipCode) {
1789            this.shippingZipCode = shippingZipCode;
1790        }
1791    
1792        public String getBillingLine1StreetAddress() {
1793            return billingLine1StreetAddress;
1794        }
1795    
1796        public void setBillingLine1StreetAddress(String billingLine1StreetAddress) {
1797            this.billingLine1StreetAddress = billingLine1StreetAddress;
1798        }
1799    
1800        public String getBillingLine2StreetAddress() {
1801            return billingLine2StreetAddress;
1802        }
1803    
1804        public void setBillingLine2StreetAddress(String billingLine2StreetAddress) {
1805            this.billingLine2StreetAddress = billingLine2StreetAddress;
1806        }
1807    
1808        public String getShippingLine1StreetAddress() {
1809            return shippingLine1StreetAddress;
1810        }
1811    
1812        public void setShippingLine1StreetAddress(String shippingLine1StreetAddress) {
1813            this.shippingLine1StreetAddress = shippingLine1StreetAddress;
1814        }
1815    
1816        public String getShippingLine2StreetAddress() {
1817            return shippingLine2StreetAddress;
1818        }
1819    
1820        public void setShippingLine2StreetAddress(String shippingLine2StreetAddress) {
1821            this.shippingLine2StreetAddress = shippingLine2StreetAddress;
1822        }
1823    
1824        public boolean getRecurredInvoiceIndicator() {
1825            return recurredInvoiceIndicator;
1826        }
1827    
1828        public void setRecurredInvoiceIndicator(boolean recurredInvoiceIndicator) {
1829            this.recurredInvoiceIndicator = recurredInvoiceIndicator;
1830        }
1831    
1832        /**
1833         * Get a string representation for billing chart/organization
1834         * 
1835         * @return
1836         */
1837        public String getBilledByChartOfAccCodeAndOrgCode() {
1838            String returnVal = getBillByChartOfAccountCode() + "/" + getBilledByOrganizationCode();
1839    
1840            return returnVal;
1841        }
1842    
1843        /**
1844         * Populate Customer Billing Address fields on Customer Invoice.
1845         * 
1846         * @return
1847         */
1848        public void setCustomerBillToAddressOnInvoice(CustomerAddress customerBillToAddress) {
1849            accountsReceivableDocumentHeader.refreshReferenceObject("customer");
1850            if (ObjectUtils.isNotNull(accountsReceivableDocumentHeader.getCustomer())) {
1851                this.setCustomerName(accountsReceivableDocumentHeader.getCustomer().getCustomerName());
1852            }
1853            
1854            if (ObjectUtils.isNotNull(customerBillToAddress)) {
1855                this.setBillingAddressTypeCode(customerBillToAddress.getCustomerAddressTypeCode());
1856                this.setBillingAddressName(customerBillToAddress.getCustomerAddressName());
1857                this.setBillingLine1StreetAddress(customerBillToAddress.getCustomerLine1StreetAddress());
1858                this.setBillingLine2StreetAddress(customerBillToAddress.getCustomerLine2StreetAddress());
1859                this.setBillingCityName(customerBillToAddress.getCustomerCityName());
1860                this.setBillingStateCode(customerBillToAddress.getCustomerStateCode());
1861                this.setBillingZipCode(customerBillToAddress.getCustomerZipCode());
1862                this.setBillingCountryCode(customerBillToAddress.getCustomerCountryCode());
1863                this.setBillingAddressInternationalProvinceName(customerBillToAddress.getCustomerAddressInternationalProvinceName());
1864                this.setBillingInternationalMailCode(customerBillToAddress.getCustomerInternationalMailCode());
1865                this.setBillingEmailAddress(customerBillToAddress.getCustomerEmailAddress());
1866            }
1867        }
1868    
1869        /**
1870         * Populate Customer Shipping Address fields on Customer Invoice.
1871         * 
1872         * @return
1873         */
1874        public void setCustomerShipToAddressOnInvoice(CustomerAddress customerShipToAddress) {
1875    
1876            accountsReceivableDocumentHeader.refreshReferenceObject("customer");
1877            Customer customer = accountsReceivableDocumentHeader.getCustomer();
1878            if (ObjectUtils.isNotNull(customer))
1879                this.setCustomerName(customer.getCustomerName());
1880    
1881            if (ObjectUtils.isNotNull(customerShipToAddress)) {
1882                this.setShippingAddressTypeCode(customerShipToAddress.getCustomerAddressTypeCode());
1883                this.setShippingAddressName(customerShipToAddress.getCustomerAddressName());
1884                this.setShippingLine1StreetAddress(customerShipToAddress.getCustomerLine1StreetAddress());
1885                this.setShippingLine2StreetAddress(customerShipToAddress.getCustomerLine2StreetAddress());
1886                this.setShippingCityName(customerShipToAddress.getCustomerCityName());
1887                this.setShippingStateCode(customerShipToAddress.getCustomerStateCode());
1888                this.setShippingZipCode(customerShipToAddress.getCustomerZipCode());
1889                this.setShippingCountryCode(customerShipToAddress.getCustomerCountryCode());
1890                this.setShippingAddressInternationalProvinceName(customerShipToAddress.getCustomerAddressInternationalProvinceName());
1891                this.setShippingInternationalMailCode(customerShipToAddress.getCustomerInternationalMailCode());
1892                this.setShippingEmailAddress(customerShipToAddress.getCustomerEmailAddress());
1893            }
1894            else {
1895                this.setShippingAddressTypeCode(null);
1896                this.setShippingAddressName(null);
1897                this.setShippingLine1StreetAddress(null);
1898                this.setShippingLine2StreetAddress(null);
1899                this.setShippingCityName(null);
1900                this.setShippingStateCode(null);
1901                this.setShippingZipCode(null);
1902                this.setShippingCountryCode(null);
1903                this.setShippingAddressInternationalProvinceName(null);
1904                this.setShippingInternationalMailCode(null);
1905                this.setShippingEmailAddress(null);
1906            }
1907        }
1908    
1909        /**
1910         * Gets the quickApply attribute.
1911         * 
1912         * @return Returns the quickApply.
1913         */
1914        //TODO Andrew - this is payapp specific stuff and needs to go
1915    //    public boolean isQuickApply() {
1916    //        return quickApply;
1917    //    }
1918    //
1919    //    //TODO Andrew - this is payapp specific stuff and needs to go
1920    //    public boolean getQuickApply() {
1921    //        return isQuickApply();
1922    //    }
1923    //    
1924    //    /**
1925    //     * Sets the quickApply attribute value.
1926    //     * 
1927    //     * @param quickApply The quickApply to set.
1928    //     */
1929    //    //TODO Andrew - this is payapp specific stuff and needs to go
1930    //    public void setQuickApply(boolean quickApply) {
1931    //        this.quickApply = quickApply;
1932    //    }
1933    
1934    
1935        /**
1936         * Answers true when invoice recurrence details are provided by the user
1937         * 
1938         * @see org.kuali.kfs.sys.document.FinancialSystemTransactionalDocumentBase#answerSplitNodeQuestion(java.lang.String)
1939         */
1940        @Override
1941        public boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException {
1942            if (HAS_RECCURENCE_NODE.equals(nodeName)) {
1943                return hasRecurrence();
1944            }
1945            if (BATCH_GENERATED_NODE.equals(nodeName)) {
1946                return isBatchGenerated();
1947            }
1948            throw new UnsupportedOperationException("answerSplitNode('" + nodeName + "') was called but no handler for nodeName specified.");
1949        }
1950    
1951        /**
1952         * 
1953         * Determines whether this document was generated from a recurrence batch.  Returns true if so, false if not.
1954         * @return
1955         */
1956        protected boolean isBatchGenerated() {
1957            return recurredInvoiceIndicator;
1958        }
1959        
1960        /**
1961         * 
1962         * Determines whether this document has a Recurrence filled out enough to create an INVR doc.
1963         * @return
1964         */
1965        protected boolean hasRecurrence() {
1966            return (ObjectUtils.isNotNull(getCustomerInvoiceRecurrenceDetails()) && getCustomerInvoiceRecurrenceDetails().isActive());
1967        }
1968    
1969    }