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.util; 017 018 import java.util.ArrayList; 019 import java.util.Collections; 020 import java.util.Comparator; 021 import java.util.List; 022 023 import org.apache.commons.lang.StringUtils; 024 import org.kuali.kfs.module.purap.businessobject.AbstractRelatedView; 025 import org.kuali.kfs.module.purap.businessobject.BulkReceivingView; 026 import org.kuali.kfs.module.purap.businessobject.CorrectionReceivingView; 027 import org.kuali.kfs.module.purap.businessobject.CreditMemoView; 028 import org.kuali.kfs.module.purap.businessobject.ElectronicInvoiceRejectView; 029 import org.kuali.kfs.module.purap.businessobject.LineItemReceivingView; 030 import org.kuali.kfs.module.purap.businessobject.PaymentRequestView; 031 import org.kuali.kfs.module.purap.businessobject.PurchaseOrderView; 032 import org.kuali.kfs.module.purap.businessobject.RequisitionView; 033 import org.kuali.kfs.module.purap.document.service.PurapService; 034 import org.kuali.kfs.sys.context.SpringContext; 035 036 public class PurApRelatedViews { 037 private String documentNumber; 038 private Integer accountsPayablePurchasingDocumentLinkIdentifier; 039 040 private transient List<RequisitionView> relatedRequisitionViews; 041 private transient List<PurchaseOrderView> relatedPurchaseOrderViews; 042 private transient List<PaymentRequestView> relatedPaymentRequestViews; 043 private transient List<PaymentRequestView> paymentHistoryPaymentRequestViews; 044 private transient List<CreditMemoView> relatedCreditMemoViews; 045 private transient List<CreditMemoView> paymentHistoryCreditMemoViews; 046 private transient List<LineItemReceivingView> relatedLineItemReceivingViews; 047 private transient List<CorrectionReceivingView> relatedCorrectionReceivingViews; 048 private transient List<BulkReceivingView> relatedBulkReceivingViews; 049 private transient List<PurchaseOrderViewGroup> groupedRelatedPurchaseOrderViews; 050 private transient List<ReceivingViewGroup> groupedRelatedReceivingViews; 051 private transient List<ElectronicInvoiceRejectView> relatedRejectViews; 052 053 public PurApRelatedViews(String documentNumber, Integer accountsPayablePurchasingDocumentLinkIdentifier) { 054 super(); 055 this.documentNumber = documentNumber; 056 this.accountsPayablePurchasingDocumentLinkIdentifier = accountsPayablePurchasingDocumentLinkIdentifier; 057 } 058 059 /** 060 * Reset all related view lists to null. 061 */ 062 public void resetRelatedViews() { 063 relatedRequisitionViews = null; 064 relatedPurchaseOrderViews = null; 065 relatedPaymentRequestViews = null; 066 paymentHistoryPaymentRequestViews = null; 067 relatedCreditMemoViews = null; 068 paymentHistoryCreditMemoViews = null; 069 relatedLineItemReceivingViews = null; 070 relatedCorrectionReceivingViews = null; 071 relatedBulkReceivingViews = null; 072 groupedRelatedPurchaseOrderViews = null; 073 groupedRelatedReceivingViews = null; 074 relatedRejectViews = null; 075 } 076 077 public List updateRelatedView(Class<?> clazz, List<? extends AbstractRelatedView> relatedList, boolean removeCurrentDocument) { 078 if (relatedList == null) { 079 relatedList = SpringContext.getBean(PurapService.class).getRelatedViews(clazz, accountsPayablePurchasingDocumentLinkIdentifier); 080 if (removeCurrentDocument) { 081 for (AbstractRelatedView view : relatedList) { 082 if (documentNumber.equals(view.getDocumentNumber())) { 083 relatedList.remove(view); 084 break; 085 } 086 } 087 } 088 } 089 return relatedList; 090 } 091 092 /** 093 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#getRelatedRequisitionViews() 094 */ 095 public List<RequisitionView> getRelatedRequisitionViews() { 096 relatedRequisitionViews = updateRelatedView(RequisitionView.class, relatedRequisitionViews, true); 097 return relatedRequisitionViews; 098 } 099 100 public List<ElectronicInvoiceRejectView> getRelatedRejectViews() { 101 relatedRejectViews = updateRelatedView(ElectronicInvoiceRejectView.class, relatedRejectViews, true); 102 return relatedRejectViews; 103 } 104 105 /** 106 * Obtains a list of related PurchaseOrderViews, first ordered by POIDs descending, then by document numbers descending; 107 * thus POs with newer POIDs will be in the front, and within the same POID, the current PO will be in the front. 108 * 109 * @return A list of <PurchaseOrderView> with newer POs in the front. 110 */ 111 public List<PurchaseOrderView> getRelatedPurchaseOrderViews() { 112 if (relatedPurchaseOrderViews != null) 113 return relatedPurchaseOrderViews; 114 115 // Obtain a list which is sorted by workflow document ID descending. 116 relatedPurchaseOrderViews = updateRelatedView(PurchaseOrderView.class, relatedPurchaseOrderViews, true); 117 118 // Sort the list. 119 Collections.sort(relatedPurchaseOrderViews, 120 new Comparator<PurchaseOrderView>() { 121 public int compare(PurchaseOrderView v1, PurchaseOrderView v2) { 122 if ((v1 != null) && (v2 != null) && 123 (v1.getPurapDocumentIdentifier() != null) && 124 (v2.getPurapDocumentIdentifier() != null)) { 125 // sort by POID descending 126 int compare = -v1.getPurapDocumentIdentifier().compareTo(v2.getPurapDocumentIdentifier()); 127 // if POIDs are the same, sort by document number descending; usually current PO has biggest documentNumber 128 if (compare == 0) { 129 compare = v1.getPurchaseOrderCurrentIndicator() ? -1 : 130 v2.getPurchaseOrderCurrentIndicator() ? 1 : 131 -v1.getDocumentNumber().compareTo(v2.getDocumentNumber()); 132 } 133 return compare; 134 } 135 return 0; 136 } 137 } 138 ); 139 140 return relatedPurchaseOrderViews; 141 } 142 143 /** 144 * Groups related PurchaseOrderViews by POIDs descending, and within each group order POs by document numbers descending; 145 * thus groups of newer POIDs will be in the front, and within each group, more current POs will be in the front. 146 * 147 * @return A list of <PurchaseOrderViewGroup> with newer POs in the front. 148 * @see org.kuali.kfs.module.purap.util.PurApRelatedViews.getRelatedPurchaseOrderViews 149 * @see org.kuali.kfs.module.purap.businessobject.PurchaseOrderView 150 */ 151 public List<PurchaseOrderViewGroup> getGroupedRelatedPurchaseOrderViews() { 152 if (groupedRelatedPurchaseOrderViews != null) 153 return groupedRelatedPurchaseOrderViews; 154 155 /* 156 * This extra layer of grouping is necessary in order to display the notes for a group of 157 * related POChange documents (which should have identical POID) after that group, 158 * and before any other related groups which may result from PO splitting (with different POIDs). 159 * With direct use of relatedPurchaseOrderViews, location of the end of the group is problematic. 160 */ 161 groupedRelatedPurchaseOrderViews = new ArrayList<PurchaseOrderViewGroup>(); 162 PurchaseOrderViewGroup group = new PurchaseOrderViewGroup(); 163 int previousPOID = 0; 164 relatedPurchaseOrderViews = getRelatedPurchaseOrderViews(); 165 for(PurchaseOrderView view : relatedPurchaseOrderViews) { 166 if (previousPOID == 0) { 167 previousPOID = view.getPurapDocumentIdentifier(); 168 169 } 170 if( view.getPurapDocumentIdentifier() == previousPOID ) { 171 group.getViews().add(view); 172 } 173 else { 174 groupedRelatedPurchaseOrderViews.add(group); 175 group = new PurchaseOrderViewGroup(); 176 group.getViews().add(view); 177 previousPOID = view.getPurapDocumentIdentifier(); 178 } 179 if (relatedPurchaseOrderViews.size() == relatedPurchaseOrderViews.indexOf(view) + 1) { 180 groupedRelatedPurchaseOrderViews.add(group); 181 } 182 } 183 184 return groupedRelatedPurchaseOrderViews; 185 } 186 187 /** 188 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#getRelatedPaymentRequestViews() 189 */ 190 public List<PaymentRequestView> getRelatedPaymentRequestViews() { 191 relatedPaymentRequestViews = updateRelatedView(PaymentRequestView.class, relatedPaymentRequestViews, true); 192 return relatedPaymentRequestViews; 193 } 194 195 /** 196 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#getRelatedCreditMemoViews() 197 */ 198 public List<CreditMemoView> getRelatedCreditMemoViews() { 199 relatedCreditMemoViews = updateRelatedView(CreditMemoView.class, relatedCreditMemoViews, true); 200 return relatedCreditMemoViews; 201 } 202 203 /** 204 * Gets the Payment History Payment Request Views for this document. 205 * 206 * @return the list of Payment History Payment Request Views. 207 */ 208 public List<PaymentRequestView> getPaymentHistoryPaymentRequestViews() { 209 paymentHistoryPaymentRequestViews = updateRelatedView(PaymentRequestView.class, paymentHistoryPaymentRequestViews, false); 210 return paymentHistoryPaymentRequestViews; 211 } 212 213 /** 214 * Gets the Payment History Credit Memo Views for this document. 215 * 216 * @return the list of Payment History Credit Memo Views. 217 */ 218 public List<CreditMemoView> getPaymentHistoryCreditMemoViews() { 219 paymentHistoryCreditMemoViews = updateRelatedView(CreditMemoView.class, paymentHistoryCreditMemoViews, false); 220 return paymentHistoryCreditMemoViews; 221 } 222 223 /** 224 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#getRelatedRequisitionViews() 225 */ 226 public List<LineItemReceivingView> getRelatedLineItemReceivingViews() { 227 relatedLineItemReceivingViews = updateRelatedView(LineItemReceivingView.class, relatedLineItemReceivingViews, true); 228 return relatedLineItemReceivingViews; 229 } 230 231 /** 232 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#getRelatedRequisitionViews() 233 */ 234 public List<CorrectionReceivingView> getRelatedCorrectionReceivingViews() { 235 relatedCorrectionReceivingViews = updateRelatedView(CorrectionReceivingView.class, relatedCorrectionReceivingViews, true); 236 return relatedCorrectionReceivingViews; 237 } 238 239 public List<BulkReceivingView> getRelatedBulkReceivingViews() { 240 relatedBulkReceivingViews = updateRelatedView(BulkReceivingView.class, relatedBulkReceivingViews, true); 241 return relatedBulkReceivingViews; 242 } 243 244 /** 245 * Groups related LineItemReceivingView and its CorrectionReceivingViews, with more recent receiving groups in the front; 246 * and within each group, with more recent corrections in the front. 247 * 248 * @return A list of ReceivingCorrectionViewGroups. 249 */ 250 public List<ReceivingViewGroup> getGroupedRelatedReceivingViews() { 251 if (groupedRelatedReceivingViews != null) 252 return groupedRelatedReceivingViews; 253 254 groupedRelatedReceivingViews = new ArrayList<ReceivingViewGroup>(); 255 PurapService purapService = SpringContext.getBean(PurapService.class); 256 List<LineItemReceivingView> liviews = purapService.getRelatedViews(LineItemReceivingView.class, accountsPayablePurchasingDocumentLinkIdentifier); 257 List<CorrectionReceivingView> crviews = purapService.getRelatedViews(CorrectionReceivingView.class, accountsPayablePurchasingDocumentLinkIdentifier); 258 259 // both LineItemReceivingViews and CorrectionReceivingViews are already in order with most recent first, so no need to sort 260 for (LineItemReceivingView liview : liviews) { 261 ReceivingViewGroup group = new ReceivingViewGroup(); 262 group.lineItemView = liview; // could be current document 263 for (CorrectionReceivingView crview : crviews) { 264 if (StringUtils.equals(crview.getLineItemReceivingDocumentNumber(), liview.getDocumentNumber()) && 265 !documentNumber.equals(crview.getDocumentNumber())) {// exclude current document 266 group.addCorrectionView(crview); 267 } 268 } 269 groupedRelatedReceivingViews.add(group); 270 } 271 272 return groupedRelatedReceivingViews; 273 } 274 275 /** 276 * A container for a List<PurchaseOrderView>, to be used by a nested c:forEach tag 277 * in relatedPurchaseOrderDocumentsDetail.tag. 278 */ 279 public class PurchaseOrderViewGroup { 280 protected List<PurchaseOrderView> views = new ArrayList<PurchaseOrderView>(); 281 282 protected PurchaseOrderViewGroup() { 283 } 284 285 public List<PurchaseOrderView> getViews() { 286 return views; 287 } 288 } 289 290 /** 291 * A container for a LineItemReceivingView and a list of its associated CorrectionReceivingViews. 292 */ 293 public class ReceivingViewGroup { 294 protected LineItemReceivingView lineItemView; 295 protected List<CorrectionReceivingView> correctionViews = new ArrayList<CorrectionReceivingView>(); 296 297 protected ReceivingViewGroup() { 298 } 299 300 public LineItemReceivingView getLineItemView() { 301 return lineItemView; 302 } 303 304 public List<CorrectionReceivingView> getCorrectionViews() { 305 return correctionViews; 306 } 307 308 public void addCorrectionView(CorrectionReceivingView correctionView) { 309 correctionViews.add(correctionView); 310 } 311 312 public boolean getIsLineItemViewCurrentDocument() { 313 return (lineItemView != null && documentNumber.equals(lineItemView.getDocumentNumber())); 314 } 315 } 316 317 }