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 }