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.purap.service.impl;
017    
018    import java.math.BigDecimal;
019    import java.sql.Date;
020    import java.text.ParseException;
021    import java.util.ArrayList;
022    import java.util.HashMap;
023    import java.util.List;
024    import java.util.Map;
025    
026    import org.apache.commons.lang.ArrayUtils;
027    import org.apache.commons.lang.StringUtils;
028    import org.apache.commons.lang.builder.ToStringBuilder;
029    import org.apache.log4j.Logger;
030    import org.kuali.kfs.module.purap.PurapConstants;
031    import org.kuali.kfs.module.purap.businessobject.ElectronicInvoice;
032    import org.kuali.kfs.module.purap.businessobject.ElectronicInvoiceItem;
033    import org.kuali.kfs.module.purap.businessobject.ElectronicInvoiceItemMapping;
034    import org.kuali.kfs.module.purap.businessobject.ElectronicInvoiceOrder;
035    import org.kuali.kfs.module.purap.businessobject.ElectronicInvoicePostalAddress;
036    import org.kuali.kfs.module.purap.businessobject.ElectronicInvoiceRejectItem;
037    import org.kuali.kfs.module.purap.businessobject.ElectronicInvoiceRejectReason;
038    import org.kuali.kfs.module.purap.businessobject.ItemType;
039    import org.kuali.kfs.module.purap.businessobject.PurApItem;
040    import org.kuali.kfs.module.purap.businessobject.PurchaseOrderItem;
041    import org.kuali.kfs.module.purap.document.ElectronicInvoiceRejectDocument;
042    import org.kuali.kfs.module.purap.document.PurchaseOrderDocument;
043    import org.kuali.kfs.module.purap.util.ElectronicInvoiceUtils;
044    import org.kuali.kfs.sys.context.SpringContext;
045    import org.kuali.rice.kns.service.DateTimeService;
046    import org.kuali.rice.kns.util.GlobalVariables;
047    
048    /**
049     * This is a holder class which can be passed to the matching service to validate einvoice or reject doc data 
050     * against the po document.   
051     * 
052     */
053    
054    public class ElectronicInvoiceOrderHolder {
055        
056        private final static Logger LOG = Logger.getLogger(ElectronicInvoiceOrderHolder.class);
057        
058        private ElectronicInvoiceRejectDocument rejectDocument;
059        private ElectronicInvoiceOrder invoiceOrder;
060        private ElectronicInvoice eInvoice;
061        private PurchaseOrderDocument poDocument;
062        private Map<String,ElectronicInvoiceItemMapping> itemTypeMappings;
063        private Map<String,ItemType> kualiItemTypes;
064        
065        private Map<String, FieldErrorHelper> errorFieldDetails = new HashMap<String, FieldErrorHelper>(); 
066        
067        private List<ElectronicInvoiceItemHolder> items = new ArrayList<ElectronicInvoiceItemHolder>();
068        
069        private boolean isRejected = false;
070        private boolean isRejectDocumentHolder;
071        private boolean validateHeader;
072        
073        private String[] summaryRejectCodes = new String[]{PurapConstants.ElectronicInvoice.TAX_SUMMARY_AMT_MISMATCH,
074                                                           PurapConstants.ElectronicInvoice.SHIPPING_SUMMARY_AMT_MISMATCH,
075                                                           PurapConstants.ElectronicInvoice.SPL_HANDLING_SUMMARY_AMT_MISMATCH,
076                                                           PurapConstants.ElectronicInvoice.DISCOUNT_SUMMARY_AMT_MISMATCH};
077        
078        public ElectronicInvoiceOrderHolder(ElectronicInvoiceRejectDocument rejectDocument,
079                                            Map itemTypeMappings,
080                                            Map itemTypes){
081            
082            /**
083             * This class has been designed based on good citizen pattern.
084             */
085            if (rejectDocument == null){
086                throw new NullPointerException("ElectronicInvoiceRejectDocument should not be null");
087            }
088            
089            this.rejectDocument = rejectDocument;
090            this.itemTypeMappings = itemTypeMappings;
091            this.poDocument = rejectDocument.getCurrentPurchaseOrderDocument();
092            this.kualiItemTypes = itemTypes;
093            
094            isRejectDocumentHolder = true;
095            validateHeader = true;
096            
097            for (int i = 0; i < rejectDocument.getInvoiceRejectItems().size(); i++) {
098                
099                ElectronicInvoiceRejectItem invoiceRejectItem = rejectDocument.getInvoiceRejectItems().get(i);
100                
101                PurApItem poItem = null;
102                if (poDocument != null){
103                    try{
104                        poItem = poDocument.getItemByLineNumber(invoiceRejectItem.getInvoiceReferenceItemLineNumber());
105                    }catch(NullPointerException e){
106                        /**
107                         * Not needed to handle this invalid item here, this will be handled in the matching process 
108                         */
109                    }
110                }
111                
112                items.add(new ElectronicInvoiceItemHolder(invoiceRejectItem,itemTypeMappings,poItem == null ? null : (PurchaseOrderItem)poItem,this));
113            }
114            
115            /**
116             * It's needed to retain any reject reasons which are related to summary amount matching
117             * which should not escape from the matching process 
118             */
119            retainSummaryRejects(rejectDocument);
120            
121        }
122        
123        protected void retainSummaryRejects(ElectronicInvoiceRejectDocument rejectDocument){
124            
125            if (LOG.isInfoEnabled()){
126                LOG.info("Searching for summary rejects");
127            }
128            
129            List<ElectronicInvoiceRejectReason> retainList = new ArrayList<ElectronicInvoiceRejectReason>();
130            List<ElectronicInvoiceRejectReason> rejectReasons = rejectDocument.getInvoiceRejectReasons();
131            
132            for (int i = 0; i < rejectReasons.size(); i++) {
133                if (ArrayUtils.contains(summaryRejectCodes,rejectReasons.get(i).getInvoiceRejectReasonTypeCode())){
134                    retainList.add(rejectReasons.get(i));
135                    if (LOG.isInfoEnabled()){
136                        LOG.info("Retaining Reject [Code=" + rejectReasons.get(i).getInvoiceRejectReasonTypeCode() + ",Desc=" + rejectReasons.get(i).getInvoiceRejectReasonDescription());
137                    }
138                }
139            }
140            
141            if (LOG.isInfoEnabled()){
142                if (retainList.size() == 0){
143                    LOG.info("No summary rejects found");
144                }
145            }
146            
147            /**
148             * FIXME: Use rejectDocument.getInvoiceRejectReasons().remove(index) instead of creating a new list
149             */
150            rejectDocument.getInvoiceRejectReasons().clear();
151            
152            for (int i = 0; i < retainList.size(); i++) {
153                rejectDocument.addRejectReason(retainList.get(i));
154            }
155        }
156        
157        
158        public ElectronicInvoiceOrderHolder(ElectronicInvoice eInvoice,
159                                            ElectronicInvoiceOrder invoiceOrder,
160                                            PurchaseOrderDocument poDocument,
161                                            Map itemTypeMappings,
162                                            Map itemTypes,
163                                            boolean validateHeader){
164            
165            if (eInvoice == null){
166                throw new NullPointerException("ElectronicInvoice should not be null");
167            }
168            
169            if (invoiceOrder == null){
170                throw new NullPointerException("ElectronicInvoiceOrder should not be null");
171            }
172            
173            this.eInvoice = eInvoice;
174            this.invoiceOrder = invoiceOrder;
175            this.itemTypeMappings = itemTypeMappings;
176            this.validateHeader = validateHeader;
177            this.kualiItemTypes = itemTypes;
178            
179            this.poDocument = poDocument;
180            
181            isRejectDocumentHolder = false;
182            
183            for (int i = 0; i < invoiceOrder.getInvoiceItems().size(); i++) {
184    
185                ElectronicInvoiceItem orderItem = invoiceOrder.getInvoiceItems().get(i);
186                
187                PurApItem poItem = null;
188                if (poDocument != null){
189                    try{
190                        poItem = poDocument.getItemByLineNumber(orderItem.getReferenceLineNumberInteger());
191                    }catch(NullPointerException e){
192                        /**
193                         * Not needed to handle this invalid item here, this will be handled in the matching process 
194                         */
195                    }
196                }
197                
198                items.add(new ElectronicInvoiceItemHolder(orderItem,itemTypeMappings,poItem == null ? null : (PurchaseOrderItem)poItem,this));
199            }
200            
201        }
202        
203        public String getFileName() {
204            if (isRejectDocumentHolder()){
205                return rejectDocument.getInvoiceFileName();
206            }else{
207                return eInvoice.getFileName();
208            }
209        }
210        
211        public String getDunsNumber() {
212            if (isRejectDocumentHolder()){
213                return rejectDocument.getVendorDunsNumber();
214            }else{
215                return eInvoice.getDunsNumber();
216            }
217        }
218        
219        public String getCustomerNumber() {
220            if (isRejectDocumentHolder()){
221                return rejectDocument.getInvoiceCustomerNumber();
222            }else{
223                return eInvoice.getCustomerNumber();
224            }
225        }
226        
227        public Integer getVendorHeaderId(){
228            if (isRejectDocumentHolder()){
229                return rejectDocument.getVendorHeaderGeneratedIdentifier();
230            }else{
231                return eInvoice.getVendorHeaderID();
232            }
233        }
234        
235        public Integer getVendorDetailId(){
236            if (isRejectDocumentHolder()){
237                return rejectDocument.getVendorDetailAssignedIdentifier();
238            }else{
239                return eInvoice.getVendorDetailID();
240            }
241        }
242        
243        public String getVendorName(){
244            if (isRejectDocumentHolder()){
245                if (rejectDocument.getVendorDetail() != null){
246                    return rejectDocument.getVendorDetail().getVendorName();
247                }else{
248                   return StringUtils.EMPTY; 
249                }
250            }else{
251                return eInvoice.getVendorName();
252            }
253        }
254        
255        public String getInvoiceNumber(){
256            if (isRejectDocumentHolder()){
257                return rejectDocument.getInvoiceFileNumber();
258            }else{
259                return eInvoice.getInvoiceDetailRequestHeader().getInvoiceId();
260            }
261        }
262        
263        public Date getInvoiceDate(){
264            if (isRejectDocumentHolder()){
265                return ElectronicInvoiceUtils.getDate(rejectDocument.getInvoiceFileDate());
266            }else{
267                return eInvoice.getInvoiceDetailRequestHeader().getInvoiceDate();
268            }
269        }
270        
271        public String getInvoiceDateString(){
272            if (isRejectDocumentHolder()){
273                return rejectDocument.getInvoiceFileDate();
274            }else{
275                return eInvoice.getInvoiceDetailRequestHeader().getInvoiceDateString();
276            }
277        }
278        
279        
280        public boolean isInformationOnly(){
281            if (isRejectDocumentHolder()){
282                return rejectDocument.isInvoiceFileInformationOnlyIndicator();
283            }else{
284                return eInvoice.getInvoiceDetailRequestHeader().isInformationOnly();
285            }
286        }
287        
288        public String getInvoicePurchaseOrderID(){
289            if (isRejectDocumentHolder()){
290                return rejectDocument.getInvoicePurchaseOrderNumber();
291            }else{
292                return invoiceOrder.getOrderReferenceOrderID();
293            }
294        }
295        
296        public boolean isTaxInLine(){
297            if (isRejectDocumentHolder()){
298                return rejectDocument.isInvoiceFileTaxInLineIndicator();
299            }else{
300                return eInvoice.getInvoiceDetailRequestHeader().isTaxInLine();
301            }
302        }
303        
304        public BigDecimal getTaxAmount(){
305            if (isRejectDocumentHolder()){
306                return rejectDocument.getInvoiceItemTaxAmount();
307            }else{
308                return eInvoice.getInvoiceTaxAmount(invoiceOrder);
309            }
310        }
311        
312        public String getTaxDescription(){
313            if (isRejectDocumentHolder()){
314                return rejectDocument.getInvoiceItemTaxDescription();
315            }else{
316                return eInvoice.getInvoiceTaxDescription(invoiceOrder);
317            }
318        }
319        public boolean isSpecialHandlingInLine(){
320            if (isRejectDocumentHolder()){
321                return rejectDocument.isInvoiceFileSpecialHandlingInLineIndicator();
322            }else{
323                return eInvoice.getInvoiceDetailRequestHeader().isSpecialHandlingInLine();
324            }
325        }
326        
327        public BigDecimal getInvoiceSpecialHandlingAmount(){
328            if (isRejectDocumentHolder()){
329                return rejectDocument.getInvoiceItemSpecialHandlingAmount();
330            }else{
331                return eInvoice.getInvoiceSpecialHandlingAmount(invoiceOrder);
332            }
333        }
334        
335        public String getInvoiceSpecialHandlingDescription(){
336            if (isRejectDocumentHolder()){
337                return rejectDocument.getInvoiceItemSpecialHandlingDescription();
338            }else{
339                return eInvoice.getInvoiceSpecialHandlingDescription(invoiceOrder);
340            }
341        }
342        
343        public boolean isShippingInLine(){
344            if (isRejectDocumentHolder()){
345                return rejectDocument.isInvoiceFileShippingInLineIndicator();
346            }else{
347                return eInvoice.getInvoiceDetailRequestHeader().isShippingInLine();
348            }
349        }
350        
351        public BigDecimal getInvoiceShippingAmount(){
352            if (isRejectDocumentHolder()){
353                return rejectDocument.getInvoiceItemShippingAmount();
354            }else{
355                return eInvoice.getInvoiceShippingAmount(invoiceOrder);
356            }
357        }
358        
359        public String getInvoiceShippingDescription(){
360            if (isRejectDocumentHolder()){
361                return rejectDocument.getInvoiceItemShippingDescription();
362            }else{
363                return eInvoice.getInvoiceShippingDescription(invoiceOrder);
364            }
365        }
366        
367        public boolean isDiscountInLine(){
368            if (isRejectDocumentHolder()){
369                return rejectDocument.isInvoiceFileDiscountInLineIndicator();
370            }else{
371                return eInvoice.getInvoiceDetailRequestHeader().isDiscountInLine();
372            }
373        }
374        
375        public BigDecimal getInvoiceDiscountAmount(){
376            if (isRejectDocumentHolder()){
377                return rejectDocument.getInvoiceItemDiscountAmount();
378            }else{
379                return eInvoice.getInvoiceDiscountAmount(invoiceOrder);
380            }
381        }
382        
383        public BigDecimal getInvoiceDepositAmount() {
384            if (isRejectDocumentHolder()){
385                throw new UnsupportedOperationException("Deposit amount not available for the reject document");
386            }else{
387                return eInvoice.getInvoiceDepositAmount();    
388            }
389        }
390    
391        public BigDecimal getInvoiceDueAmount() {
392            if (isRejectDocumentHolder()){
393                throw new UnsupportedOperationException("Deposit amount not available for the reject document");
394            }else{
395                return eInvoice.getInvoiceDueAmount();
396            }
397        }
398          
399        public PurchaseOrderDocument getPurchaseOrderDocument(){
400            return poDocument;
401        }
402        
403        public ElectronicInvoiceItemHolder[] getItems() {
404            if (items != null){
405                ElectronicInvoiceItemHolder[] returnItems = new ElectronicInvoiceItemHolder[items.size()];
406                items.toArray(returnItems);
407                return returnItems;
408            }
409            return null;
410        }
411        
412        public ElectronicInvoiceItemHolder getItemByLineNumber(int lineNumber){
413            
414            if (items != null){
415                for (int i = 0; i < items.size(); i++) {
416                    ElectronicInvoiceItemHolder itemHolder = items.get(i);
417                    if (itemHolder.getInvoiceItemLineNumber().intValue() == lineNumber){
418                        return itemHolder;
419                    }
420                }
421            }
422            return null;
423        }
424        
425        public void addInvoiceHeaderRejectReason(ElectronicInvoiceRejectReason rejectReason){
426            addInvoiceHeaderRejectReason(rejectReason,null,null);
427        }
428        
429        public void addInvoiceHeaderRejectReason(ElectronicInvoiceRejectReason rejectReason,
430                                                 String fieldName,
431                                                 String applnResourceKey){
432            
433            if (LOG.isInfoEnabled()){
434                LOG.info("Adding reject reason - " + rejectReason.getInvoiceRejectReasonDescription());
435            }
436            
437            if (isRejectDocumentHolder()){
438                rejectDocument.addRejectReason(rejectReason);
439                if (fieldName != null && applnResourceKey != null){
440                    /**
441                     * FIXME : Create a helper method to get the fieldname and key name in the resource bundle
442                     * for a specific reject reason type code instead of getting it from the 
443                     * calling method. Matching service should not do these things. It should 
444                     * not know whether it's doing the matching process for a reject doc or for einvoice. It should
445                     * be independent of the incoming data
446                     * 
447                     */
448                    GlobalVariables.getMessageMap().putError(fieldName, applnResourceKey);    
449                }
450            }else{
451                eInvoice.addFileRejectReasonToList(rejectReason);
452                eInvoice.setFileRejected(true);
453            }
454        }
455        
456        public void addInvoiceOrderRejectReason(ElectronicInvoiceRejectReason rejectReason,
457                                                String fieldName){
458            addInvoiceOrderRejectReason(rejectReason,fieldName,null);
459        }
460    
461        public void addInvoiceOrderRejectReason(ElectronicInvoiceRejectReason rejectReason,
462                                                String fieldName,
463                                                String applnResourceKey){
464            
465            if (LOG.isInfoEnabled()){
466                LOG.info("Adding reject reason - " + rejectReason.getInvoiceRejectReasonDescription());
467            }
468            
469            if (isRejectDocumentHolder()){
470                rejectDocument.addRejectReason(rejectReason);
471                if (fieldName != null && applnResourceKey != null){
472                    /**
473                     * FIXME : Create a helper method to get the fieldname and key name in the resource bundle
474                     * for a specific reject reason type code instead of getting it from the 
475                     * calling method. Matching service should not do these things. It should 
476                     * not know whether it's doing the matching process for a reject doc or for einvoice. It should
477                     * be independent of the incoming data
478                     * 
479                     * Also, needs to analyze the way of handling errors in specific line item
480                     */
481                    GlobalVariables.getMessageMap().putError(fieldName, applnResourceKey);
482                }
483            }else{
484                invoiceOrder.addRejectReasonToList(rejectReason);
485                eInvoice.setFileRejected(true);
486            }
487        }
488        
489        public void addInvoiceOrderRejectReason(ElectronicInvoiceRejectReason rejectReason) {
490            addInvoiceOrderRejectReason(rejectReason,null,null);
491        }
492        
493        public boolean isValidateHeaderInformation(){
494            return validateHeader;
495        }
496        
497        public boolean isRejectDocumentHolder(){
498            return isRejectDocumentHolder;
499        }
500    
501        public ElectronicInvoiceItemMapping getInvoiceItemMapping(String invoiceItemTypeCode){
502            if (itemTypeMappings == null){
503                return null;
504            }else{
505                return itemTypeMappings.get(invoiceItemTypeCode);
506            }
507        }
508        
509        /*public boolean isItemTypeAvailableInKuali(String invoiceItemTypeCode) {
510            if (itemTypeMappings == null) {
511                return false;
512            }
513            else {
514                return itemTypeMappings.containsKey(invoiceItemTypeCode);
515            }
516        }*/
517        
518        public boolean isItemTypeAvailableInItemMapping(String invoiceItemTypeCode) {
519            if (itemTypeMappings == null) {
520                return false;
521            }
522            else {
523                return itemTypeMappings.containsKey(invoiceItemTypeCode);
524            }
525        }
526    
527        
528        public boolean isInvoiceRejected() {
529            if (isRejectDocumentHolder()) {
530                return rejectDocument.getInvoiceRejectReasons() != null && rejectDocument.getInvoiceRejectReasons().size() > 0;
531            }
532            else {
533                return eInvoice.isFileRejected();
534            }
535        }
536    
537        
538        public String getKualiItemTypeCodeFromMappings(String invoiceItemTypeCode) {
539            
540            ElectronicInvoiceItemMapping itemMapping = getInvoiceItemMapping(invoiceItemTypeCode);
541            
542            if (itemMapping != null) {
543                return itemMapping.getItemTypeCode();
544            } else {
545                return null;
546            }
547        }
548        
549       /* public String getKualiItemTypeCode(String invoiceItemTypeCode) {
550            
551            ItemType itemType = kualiItemTypes.get(invoiceItemTypeCode);
552            
553            if (itemType != null) {
554                return itemType.getItemTypeCode();
555            }
556            else {
557                return null;
558            }
559        }*/
560        
561       /* public boolean isKualiItemTypeExistsInVendorItemTypeMappings(String kualiItemType){
562            ElectronicInvoiceItemMapping[] mappings = getInvoiceItemTypeMappings();
563            if (mappings != null){
564                for (int i = 0; i < mappings.length; i++) {
565                    if (StringUtils.equals(kualiItemType,mappings[i].getItemTypeCode())){
566                        return true;
567                    }
568                }
569            }
570            
571            return false;
572        }*/
573        
574        public ElectronicInvoiceItemMapping[] getInvoiceItemTypeMappings(){
575            if (itemTypeMappings != null){
576                ElectronicInvoiceItemMapping[] itemMappings = new ElectronicInvoiceItemMapping[itemTypeMappings.size()];
577                itemTypeMappings.values().toArray(itemMappings);
578                return itemMappings;
579            }else{
580                return null;
581            }
582        }
583        
584        public boolean isInvoiceNumberAcceptIndicatorEnabled(){
585            if (isRejectDocumentHolder()) {
586                return rejectDocument.isInvoiceNumberAcceptIndicator();
587            }else {
588                return false;
589            }
590        }
591        
592        public ElectronicInvoice getElectronicInvoice(){
593            if (isRejectDocumentHolder()){
594                throw new UnsupportedOperationException("ElectronicInvoice object not available for ElectronicInvoiceRejectDocument");
595            }else{
596                return eInvoice;
597            }
598        }
599        
600        public BigDecimal getInvoiceNetAmount(){
601            if (isRejectDocumentHolder()){
602                return rejectDocument.getInvoiceItemNetAmount();
603            }else{
604                return eInvoice.getInvoiceNetAmount(invoiceOrder);
605            }
606        }
607        
608        public Date getInvoiceProcessedDate(){
609            DateTimeService dateTimeService = SpringContext.getBean(DateTimeService.class);
610            if (isRejectDocumentHolder()){
611                try {
612                    return dateTimeService.convertToSqlDate(rejectDocument.getInvoiceProcessTimestamp());
613                }
614                catch (ParseException e) {
615                    throw new RuntimeException("ParseException thrown when trying to convert a Timestamp to SqlDate.", e);
616                }
617            }else{
618                return dateTimeService.getCurrentSqlDate();
619            }
620        }
621        
622        public String getInvoiceShipToAddressAsString() {
623    
624            StringBuffer noteBuffer = new StringBuffer();
625            noteBuffer.append("Shipping Address from Electronic Invoice:\n\n");
626    
627            if (!isRejectDocumentHolder()) {
628    
629                ElectronicInvoicePostalAddress shipToAddress = eInvoice.getCxmlPostalAddress(invoiceOrder, PurapConstants.ElectronicInvoice.CXML_ADDRESS_SHIP_TO_ROLE_ID, PurapConstants.ElectronicInvoice.CXML_ADDRESS_SHIP_TO_NAME);
630                if (shipToAddress != null) {
631    
632                    if (StringUtils.isNotEmpty(shipToAddress.getName())) {
633                        noteBuffer.append(shipToAddress.getName() + "\n");
634                    }
635    
636                    noteBuffer.append(shipToAddress.getLine1() + "\n");
637    
638                    if (StringUtils.isNotEmpty(shipToAddress.getLine2())) {
639                        noteBuffer.append(shipToAddress.getLine2() + "\n");
640                    }
641    
642                    if (StringUtils.isNotEmpty(shipToAddress.getLine3())) {
643                        noteBuffer.append(shipToAddress.getLine3() + "\n");
644                    }
645    
646                    noteBuffer.append(shipToAddress.getCityName() + ", " + shipToAddress.getStateCode() + " " + shipToAddress.getPostalCode() + "\n");
647                    noteBuffer.append(shipToAddress.getCountryName());
648                }
649    
650            } else {
651    
652                if (StringUtils.isNotEmpty(rejectDocument.getInvoiceShipToAddressName())) {
653                    noteBuffer.append(rejectDocument.getInvoiceShipToAddressName() + "\n");
654                }
655    
656                noteBuffer.append(rejectDocument.getInvoiceShipToAddressLine1() + "\n");
657    
658                if (StringUtils.isNotEmpty(rejectDocument.getInvoiceShipToAddressLine2())) {
659                    noteBuffer.append(rejectDocument.getInvoiceShipToAddressLine2() + "\n");
660                }
661    
662                if (StringUtils.isNotEmpty(rejectDocument.getInvoiceShipToAddressLine3())) {
663                    noteBuffer.append(rejectDocument.getInvoiceShipToAddressLine3() + "\n");
664                }
665    
666                noteBuffer.append(rejectDocument.getInvoiceShipToAddressCityName() + ", " + rejectDocument.getInvoiceShipToAddressStateCode() + " " + rejectDocument.getInvoiceShipToAddressPostalCode() + "\n");
667                noteBuffer.append(rejectDocument.getInvoiceShipToAddressCountryName());
668    
669            }
670            return noteBuffer.toString();
671        }
672        
673        public String getInvoiceBillToAddressAsString(){
674            
675            StringBuffer noteBuffer = new StringBuffer();
676            noteBuffer.append("Billing Address from Electronic Invoice:\n\n");
677            
678            if (!isRejectDocumentHolder()){
679                
680                ElectronicInvoicePostalAddress billToAddress = eInvoice.getCxmlPostalAddress(invoiceOrder,
681                                                                                             PurapConstants.ElectronicInvoice.CXML_ADDRESS_BILL_TO_ROLE_ID,
682                                                                                             PurapConstants.ElectronicInvoice.CXML_ADDRESS_BILL_TO_NAME);
683                
684                if (billToAddress != null) {
685    
686                    if (StringUtils.isNotEmpty(billToAddress.getName())) {
687                        noteBuffer.append(billToAddress.getName() + "\n");
688                    }
689    
690                    noteBuffer.append(billToAddress.getLine1() + "\n");
691    
692                    if (StringUtils.isNotEmpty(billToAddress.getLine2())) {
693                        noteBuffer.append(billToAddress.getLine2() + "\n");
694                    }
695    
696                    if (StringUtils.isNotEmpty(billToAddress.getLine3())) {
697                        noteBuffer.append(billToAddress.getLine3() + "\n");
698                    }
699    
700                    noteBuffer.append(billToAddress.getCityName() + ", " + billToAddress.getStateCode() + " " + billToAddress.getPostalCode() + "\n");
701                    noteBuffer.append(billToAddress.getCountryName());
702                }   
703            }else{
704                
705                if (StringUtils.isNotEmpty(rejectDocument.getInvoiceBillToAddressName())) {
706                    noteBuffer.append(rejectDocument.getInvoiceBillToAddressName() + "\n");
707                  }
708                  
709                  noteBuffer.append(rejectDocument.getInvoiceBillToAddressLine1() + "\n");
710                  
711                  if (StringUtils.isNotEmpty(rejectDocument.getInvoiceBillToAddressLine2())){
712                    noteBuffer.append(rejectDocument.getInvoiceBillToAddressLine2() + "\n");
713                  }
714                
715                  if (StringUtils.isNotEmpty(rejectDocument.getInvoiceBillToAddressLine3())){
716                      noteBuffer.append(rejectDocument.getInvoiceBillToAddressLine3() + "\n");
717                  }
718            
719                  noteBuffer.append(rejectDocument.getInvoiceBillToAddressCityName() + ", " + rejectDocument.getInvoiceBillToAddressStateCode() + " " + rejectDocument.getInvoiceBillToAddressPostalCode() + "\n");
720                  noteBuffer.append(rejectDocument.getInvoiceBillToAddressCountryName());
721            }
722            
723            return noteBuffer.toString();
724        }
725        
726        public Integer getAccountsPayablePurchasingDocumentLinkIdentifier(){
727            if (isRejectDocumentHolder()){
728                return rejectDocument.getAccountsPayablePurchasingDocumentLinkIdentifier();
729            }else{
730                if (poDocument != null){
731                    return poDocument.getAccountsPayablePurchasingDocumentLinkIdentifier();
732                }else{
733                    return null;
734                }
735            }
736        }
737        
738        protected class FieldErrorHelper {
739            
740            private String fieldName;
741            private String applicationResourceKeyName;
742            private String rejectReasonTypeCode;
743            
744            FieldErrorHelper(String fieldName,
745                             String applicationResourceKeyName,
746                             String rejectReasonTypeCode){
747                
748                if (StringUtils.isEmpty(fieldName) ||
749                    StringUtils.isEmpty(applicationResourceKeyName) ||
750                    StringUtils.isEmpty(rejectReasonTypeCode)){
751                    throw new NullPointerException("Invalid field Values [fieldName=" + fieldName + ",applicationResourceKeyName=" + applicationResourceKeyName + ",rejectReasonTypeCode=" + rejectReasonTypeCode + "]");
752                }
753                
754                this.fieldName = fieldName;
755                this.applicationResourceKeyName = applicationResourceKeyName;
756                this.rejectReasonTypeCode = rejectReasonTypeCode;
757            }
758            
759            public String getApplicationResourceKeyName() {
760                return applicationResourceKeyName;
761            }
762            public void setApplicationResourceKeyName(String applicationResourceKeyName) {
763                this.applicationResourceKeyName = applicationResourceKeyName;
764            }
765            public String getFieldName() {
766                return fieldName;
767            }
768            public void setFieldName(String fieldName) {
769                this.fieldName = fieldName;
770            }
771            public String getRejectReasonTypeCode() {
772                return rejectReasonTypeCode;
773            }
774            public void setRejectReasonTypeCode(String rejectReasonTypeCode) {
775                this.rejectReasonTypeCode = rejectReasonTypeCode;
776            }
777            
778            public String toString(){
779                ToStringBuilder toString = new ToStringBuilder(this);
780                toString.append("fieldName",fieldName);
781                toString.append("applicationResourceKeyName",applicationResourceKeyName);
782                toString.append("rejectReasonTypeCode",rejectReasonTypeCode);
783                return toString.toString();
784            }
785            
786        }
787        
788        
789    }