View Javadoc

1   /*
2    * Copyright 2007 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.select.document.service.impl;
17  
18  import org.apache.commons.collections.CollectionUtils;
19  import org.apache.commons.lang.StringUtils;
20  import org.kuali.ole.module.purap.PurapConstants;
21  import org.kuali.ole.module.purap.PurapParameterConstants;
22  import org.kuali.ole.module.purap.businessobject.CreditMemoAccount;
23  import org.kuali.ole.module.purap.businessobject.PurApAccountingLine;
24  import org.kuali.ole.module.purap.businessobject.PurchaseOrderItem;
25  import org.kuali.ole.module.purap.businessobject.PurchasingCapitalAssetItem;
26  import org.kuali.ole.module.purap.document.PaymentRequestDocument;
27  import org.kuali.ole.module.purap.document.PurchaseOrderDocument;
28  import org.kuali.ole.module.purap.document.VendorCreditMemoDocument;
29  import org.kuali.ole.module.purap.document.service.AccountsPayableService;
30  import org.kuali.ole.module.purap.document.service.PurapService;
31  import org.kuali.ole.module.purap.document.service.impl.CreditMemoServiceImpl;
32  import org.kuali.ole.module.purap.service.PurapAccountingService;
33  import org.kuali.ole.module.purap.util.ExpiredOrClosedAccountEntry;
34  import org.kuali.ole.select.businessobject.OleCreditMemoItem;
35  import org.kuali.ole.select.businessobject.OleInvoiceItem;
36  import org.kuali.ole.select.businessobject.OlePaymentRequestItem;
37  import org.kuali.ole.select.businessobject.OlePurchaseOrderItem;
38  import org.kuali.ole.select.document.OleInvoiceDocument;
39  import org.kuali.ole.select.document.OlePaymentRequestDocument;
40  import org.kuali.ole.select.document.OleVendorCreditMemoDocument;
41  import org.kuali.ole.select.document.service.OleCreditMemoService;
42  import org.kuali.ole.select.document.service.OleInvoiceService;
43  import org.kuali.ole.select.document.service.OlePaymentRequestService;
44  import org.kuali.ole.select.document.service.OlePurchaseOrderService;
45  import org.kuali.ole.sys.OLEConstants;
46  import org.kuali.ole.sys.OLEKeyConstants;
47  import org.kuali.ole.sys.businessobject.SourceAccountingLine;
48  import org.kuali.ole.vnd.VendorConstants;
49  import org.kuali.ole.vnd.VendorUtils;
50  import org.kuali.ole.vnd.businessobject.VendorAddress;
51  import org.kuali.ole.vnd.businessobject.VendorDetail;
52  import org.kuali.ole.vnd.document.service.VendorService;
53  import org.kuali.rice.core.api.util.type.AbstractKualiDecimal;
54  import org.kuali.rice.core.api.util.type.KualiDecimal;
55  import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
56  import org.kuali.rice.kew.api.exception.WorkflowException;
57  import org.kuali.rice.krad.service.DocumentService;
58  import org.kuali.rice.krad.util.GlobalVariables;
59  import org.kuali.rice.krad.util.ObjectUtils;
60  import org.springframework.transaction.annotation.Transactional;
61  
62  import java.math.BigDecimal;
63  import java.math.RoundingMode;
64  import java.util.ArrayList;
65  import java.util.HashMap;
66  import java.util.List;
67  
68  /**
69   * Provides services to support the creation of a Credit Memo Document.
70   */
71  @Transactional
72  public class OleCreditMemoServiceImpl extends CreditMemoServiceImpl implements OleCreditMemoService {
73      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OleCreditMemoServiceImpl.class);
74  
75      private PurapAccountingService purapAccountingService;
76      private PurapService purapService;
77      private OlePaymentRequestService olePaymentRequestService;
78      private VendorService vendorService;
79      private OlePurchaseOrderService olePurchaseOrderService;
80      private OleInvoiceService oleInvoiceService;
81      private AccountsPayableService accountsPayableService;
82      private DocumentService documentService;
83  
84  
85      public void setOlePurchaseOrderService(OlePurchaseOrderService olePurchaseOrderService) {
86          this.olePurchaseOrderService = olePurchaseOrderService;
87      }
88  
89      @Override
90      public void setVendorService(VendorService vendorService) {
91          this.vendorService = vendorService;
92      }
93  
94      public void setOlePaymentRequestService(OlePaymentRequestService olePaymentRequestService) {
95          this.olePaymentRequestService = olePaymentRequestService;
96      }
97  
98      @Override
99      public void setPurapAccountingService(PurapAccountingService purapAccountingService) {
100         this.purapAccountingService = purapAccountingService;
101     }
102 
103     @Override
104     public void setPurapService(PurapService purapService) {
105         this.purapService = purapService;
106     }
107 
108     public void setOleInvoiceService(OleInvoiceService oleInvoiceService) {
109         this.oleInvoiceService = oleInvoiceService;
110     }
111 
112     public void setAccountsPayableService(AccountsPayableService accountsPayableService) {
113         this.accountsPayableService = accountsPayableService;
114     }
115 
116     public void setDocumentService(DocumentService documentService) {
117         this.documentService = documentService;
118     }
119 
120     /**
121      * @see org.kuali.ole.module.purap.document.service.CreditMemoService# calculateCreditMemo(org.kuali.ole.module.purap.document.VendorCreditMemoDocument)
122      */
123     @Override
124     public void calculateCreditMemo(VendorCreditMemoDocument cmDocument) {
125 
126         cmDocument.updateExtendedPriceOnItems();
127 
128         for (OleCreditMemoItem item : (List<OleCreditMemoItem>) cmDocument.getItems()) {
129             // make sure restocking fee is negative
130             if (StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_RESTCK_FEE_CODE, item.getItemTypeCode())) {
131                 if (item.getItemUnitPrice() != null) {
132                     item.setExtendedPrice(item.getExtendedPrice().abs().negated());
133                     item.setItemUnitPrice(item.getItemUnitPrice().abs().negate());
134                 }
135             }
136             if (StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_MISC_CRDT_CODE, item.getItemTypeCode()) || StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_RESTCK_FEE_CODE, item.getItemTypeCode())) {
137                 if (item.getItemUnitPrice() != null) {
138                     calculateProrateItemSurcharge((OleVendorCreditMemoDocument) cmDocument);
139 
140                 }
141             }
142         }
143 
144         //calculate tax if cm not based on vendor
145         if (cmDocument.isSourceVendor() == false) {
146             purapService.calculateTax(cmDocument);
147         }
148 
149         // proration
150         if (cmDocument.isSourceVendor()) {
151             // no proration on vendor
152             return;
153         }
154 
155         for (OleCreditMemoItem item : (List<OleCreditMemoItem>) cmDocument.getItems()) {
156 
157             // skip above the line
158             if (item.getItemType().isLineItemIndicator()) {
159                 continue;
160             }
161 
162             if ((item.getSourceAccountingLines().isEmpty()) && (ObjectUtils.isNotNull(item.getExtendedPrice())) && (KualiDecimal.ZERO.compareTo(item.getExtendedPrice()) != 0)) {
163 
164                 KualiDecimal totalAmount = KualiDecimal.ZERO;
165                 List<PurApAccountingLine> distributedAccounts = null;
166                 List<SourceAccountingLine> summaryAccounts = null;
167 
168                 totalAmount = cmDocument.getLineItemTotal();
169                 // this should do nothing on preq which is fine
170                 purapAccountingService.updateAccountAmounts(cmDocument.getPurApSourceDocumentIfPossible());
171                 summaryAccounts = purapAccountingService.generateSummary(cmDocument.getPurApSourceDocumentIfPossible().getItems());
172                 distributedAccounts = purapAccountingService.generateAccountDistributionForProration(summaryAccounts, totalAmount, PurapConstants.PRORATION_SCALE, CreditMemoAccount.class);
173 
174                 if (CollectionUtils.isNotEmpty(distributedAccounts) && CollectionUtils.isEmpty(item.getSourceAccountingLines())) {
175                     item.setSourceAccountingLines(distributedAccounts);
176                 }
177             }
178         }
179         // end proration          
180     }
181 
182 
183     public void calculateProrateItemSurcharge(OleVendorCreditMemoDocument vendorCreditMemoDocument) {
184         LOG.debug("Inside Calculation for ProrateItemSurcharge");
185         vendorCreditMemoDocument.setProrateBy(vendorCreditMemoDocument.isProrateQty() ? OLEConstants.PRORATE_BY_QTY : vendorCreditMemoDocument.isProrateManual() ? OLEConstants.MANUAL_PRORATE : vendorCreditMemoDocument.isProrateDollar() ? OLEConstants.PRORATE_BY_DOLLAR : null);
186         BigDecimal addChargeItem = BigDecimal.ZERO;
187         List<OleCreditMemoItem> item = (List<OleCreditMemoItem>) vendorCreditMemoDocument.getItems();
188         for (OleCreditMemoItem items : item) {
189             if (!items.getItemType().isQuantityBasedGeneralLedgerIndicator() && !items.getItemTypeCode().equalsIgnoreCase(PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE) && items.getItemUnitPrice() != null) {
190                 addChargeItem = addChargeItem.add(items.getItemUnitPrice());
191             }
192         }
193         List<BigDecimal> newUnitPriceList = new ArrayList<BigDecimal>();
194         BigDecimal totalExtPrice = new BigDecimal(0);
195         BigDecimal newUnitPrice = new BigDecimal(0);
196         BigDecimal extPrice = new BigDecimal(0);
197         BigDecimal unitPricePercent = new BigDecimal(0);
198         BigDecimal hundred = new BigDecimal(100);
199         BigDecimal one = new BigDecimal(1);
200         BigDecimal totalSurCharge = new BigDecimal(0);
201         BigDecimal totalItemQuantity = new BigDecimal(0);
202         BigDecimal itemSurchargeCons = new BigDecimal(0);
203         for (int i = 0; item.size() > i; i++) {
204             OleCreditMemoItem items = (OleCreditMemoItem) vendorCreditMemoDocument.getItem(i);
205             if ((items.getItemType().isQuantityBasedGeneralLedgerIndicator()) && !ObjectUtils.isNull(items.getItemQuantity())) {
206                 if (vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.PRORATE_BY_QTY)) {
207                     totalItemQuantity = totalItemQuantity.add(items.getItemQuantity().bigDecimalValue());
208                 }
209                 if (vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.PRORATE_BY_DOLLAR) || vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.MANUAL_PRORATE) || vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.PRORATE_BY_QTY)) {
210                     /*if (items.getItemDiscount() == null) {
211                         items.setItemDiscount(KualiDecimal.ZERO);
212                     }
213                     if (items.getItemDiscountType() != null && items.getItemDiscountType().equalsIgnoreCase(OleSelectConstant.DISCOUNT_TYPE_PERCENTAGE)) {
214                         newUnitPrice = (hundred.subtract(items.getItemDiscount().bigDecimalValue())).divide(hundred).multiply(items.getItemListPrice().bigDecimalValue());
215                     }
216                     else {
217                         newUnitPrice = items.getItemListPrice().bigDecimalValue().subtract(items.getItemDiscount().bigDecimalValue());
218                     }*/
219                     newUnitPrice = items.getItemUnitPrice();
220                     newUnitPriceList.add(newUnitPrice);
221                     extPrice = newUnitPrice.multiply(items.getItemQuantity().bigDecimalValue());
222                     totalExtPrice = totalExtPrice.add(extPrice);
223                 }
224                 if (vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.MANUAL_PRORATE)) {
225                     if (items.getItemSurcharge() == null) {
226                         items.setItemSurcharge(BigDecimal.ZERO);
227                     }
228                     totalSurCharge = totalSurCharge.add(items.getItemQuantity().bigDecimalValue().multiply(items.getItemSurcharge()));
229                 }
230             }
231 
232         }
233         if (vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.PRORATE_BY_QTY)) {
234             if (totalItemQuantity.compareTo(BigDecimal.ZERO) != 0) {
235                 itemSurchargeCons = one.divide(totalItemQuantity, 8, RoundingMode.HALF_UP);
236             }
237         }
238         for (int i = 0, j = 0; item.size() > i; i++) {
239             OleCreditMemoItem items = (OleCreditMemoItem) vendorCreditMemoDocument.getItem(i);
240             if (items.getItemType().isQuantityBasedGeneralLedgerIndicator() && newUnitPriceList.size() > j && !ObjectUtils.isNull(items.getItemQuantity())) {
241                 if (vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.PRORATE_BY_DOLLAR)) {
242                     if (totalExtPrice.compareTo(BigDecimal.ZERO) != 0) {
243                         unitPricePercent = newUnitPriceList.get(j).divide(totalExtPrice, 8, RoundingMode.HALF_UP);
244                     }
245                     items.setItemSurcharge(unitPricePercent.multiply(addChargeItem).setScale(4, RoundingMode.HALF_UP));
246                     items.setExtendedPrice((new KualiDecimal((newUnitPriceList.get(j).add(items.getItemSurcharge()).toString()))).multiply(items.getItemQuantity()));
247                 }
248                 if (vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.PRORATE_BY_QTY)) {
249                     items.setItemSurcharge(itemSurchargeCons.multiply(addChargeItem).setScale(4, RoundingMode.HALF_UP));
250                     items.setExtendedPrice(new KualiDecimal(((newUnitPriceList.get(j).add(items.getItemSurcharge()).toString()))).multiply(items.getItemQuantity()));
251                 }
252                 if (vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.MANUAL_PRORATE) && items.getItemSurcharge() != null) {
253                     items.setExtendedPrice(new KualiDecimal(((newUnitPriceList.get(j).add(items.getItemSurcharge()).toString()))).multiply(items.getItemQuantity()));
254                 }
255                 j++;
256             }
257         }
258         if (vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.MANUAL_PRORATE)) {
259             if (totalSurCharge.compareTo(addChargeItem) != 0) {
260                 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OLEKeyConstants.ERROR_PAYMENT_REQUEST_TOTAL_MISMATCH);
261             }
262         }
263         LOG.debug("Leaving Calculation for ProrateItemSurcharge");
264     }
265 
266 
267     /**
268      * Populates the credit memo items from the payment request items.
269      *
270      * @param cmDocument - Credit Memo Document to Populate
271      */
272     @Override
273     protected void populateItemLinesFromPreq(VendorCreditMemoDocument cmDocument, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
274         OlePaymentRequestDocument preqDocument = (OlePaymentRequestDocument) cmDocument.getPaymentRequestDocument();
275 
276         for (OlePaymentRequestItem preqItemToTemplate : (List<OlePaymentRequestItem>) preqDocument.getItems()) {
277             if (preqItemToTemplate.getItemType().isLineItemIndicator() && ((preqItemToTemplate.getItemType().isQuantityBasedGeneralLedgerIndicator() && preqItemToTemplate.getItemQuantity().isNonZero())
278                     || (preqItemToTemplate.getItemType().isAmountBasedGeneralLedgerIndicator() && preqItemToTemplate.getTotalAmount().isNonZero()))) {
279                 cmDocument.getItems().add(new OleCreditMemoItem(cmDocument, preqItemToTemplate, (OlePurchaseOrderItem) preqItemToTemplate.getPurchaseOrderItem(), expiredOrClosedAccountList));
280             }
281         }
282 
283         // add below the line items
284         purapService.addBelowLineItems(cmDocument);
285 
286         cmDocument.fixItemReferences();
287     }
288 
289     /**
290      * Populate Credit Memo of type Payment Request.
291      *
292      * @param cmDocument - Credit Memo Document to Populate
293      */
294     @Override
295     protected void populateDocumentFromPreq(VendorCreditMemoDocument cmDocument, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
296         PaymentRequestDocument paymentRequestDocument = olePaymentRequestService.getPaymentRequestById(cmDocument.getPaymentRequestIdentifier());
297         cmDocument.getDocumentHeader().setOrganizationDocumentNumber(paymentRequestDocument.getDocumentHeader().getOrganizationDocumentNumber());
298         cmDocument.setPaymentRequestDocument(paymentRequestDocument);
299         cmDocument.setPurchaseOrderDocument(paymentRequestDocument.getPurchaseOrderDocument());
300         cmDocument.setUseTaxIndicator(paymentRequestDocument.isUseTaxIndicator());
301 
302         // credit memo address taken directly from payment request
303         cmDocument.setVendorHeaderGeneratedIdentifier(paymentRequestDocument.getVendorHeaderGeneratedIdentifier());
304         cmDocument.setVendorDetailAssignedIdentifier(paymentRequestDocument.getVendorDetailAssignedIdentifier());
305         cmDocument.setVendorAddressGeneratedIdentifier(paymentRequestDocument.getVendorAddressGeneratedIdentifier());
306         cmDocument.setVendorCustomerNumber(paymentRequestDocument.getVendorCustomerNumber());
307         cmDocument.setVendorName(paymentRequestDocument.getVendorName());
308         cmDocument.setVendorLine1Address(paymentRequestDocument.getVendorLine1Address());
309         cmDocument.setVendorLine2Address(paymentRequestDocument.getVendorLine2Address());
310         cmDocument.setVendorCityName(paymentRequestDocument.getVendorCityName());
311         cmDocument.setVendorStateCode(paymentRequestDocument.getVendorStateCode());
312         cmDocument.setVendorPostalCode(paymentRequestDocument.getVendorPostalCode());
313         cmDocument.setVendorCountryCode(paymentRequestDocument.getVendorCountryCode());
314         cmDocument.setVendorAttentionName(paymentRequestDocument.getVendorAttentionName());
315         cmDocument.setAccountsPayablePurchasingDocumentLinkIdentifier(paymentRequestDocument.getAccountsPayablePurchasingDocumentLinkIdentifier());
316         cmDocument.setPaymentMethodId(paymentRequestDocument.getVendorDetail().getPaymentMethodId());
317         cmDocument.setPurchaseOrderTypeId(paymentRequestDocument.getPurchaseOrderTypeId());
318         // prep the item lines (also collect warnings for later display) this is only done on paymentRequest
319         purapAccountingService.convertMoneyToPercent(paymentRequestDocument);
320         populateItemLinesFromPreq(cmDocument, expiredOrClosedAccountList);
321     }
322 
323 
324     @Override
325     protected void populateDocumentFromPO(VendorCreditMemoDocument cmDocument, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
326         PurchaseOrderDocument purchaseOrderDocument = olePurchaseOrderService.getCurrentPurchaseOrder(cmDocument.getPurchaseOrderIdentifier());
327         cmDocument.setPurchaseOrderDocument(purchaseOrderDocument);
328         cmDocument.getDocumentHeader().setOrganizationDocumentNumber(purchaseOrderDocument.getDocumentHeader().getOrganizationDocumentNumber());
329         cmDocument.setUseTaxIndicator(cmDocument.isUseTaxIndicator());
330 
331         cmDocument.setVendorHeaderGeneratedIdentifier(purchaseOrderDocument.getVendorHeaderGeneratedIdentifier());
332         cmDocument.setVendorDetailAssignedIdentifier(purchaseOrderDocument.getVendorDetailAssignedIdentifier());
333         cmDocument.setVendorCustomerNumber(purchaseOrderDocument.getVendorCustomerNumber());
334         cmDocument.setVendorName(purchaseOrderDocument.getVendorName());
335         cmDocument.setAccountsPayablePurchasingDocumentLinkIdentifier(purchaseOrderDocument.getAccountsPayablePurchasingDocumentLinkIdentifier());
336         cmDocument.setPaymentMethodId(purchaseOrderDocument.getVendorDetail().getPaymentMethodId());
337         cmDocument.setPurchaseOrderTypeId(purchaseOrderDocument.getPurchaseOrderTypeId());
338         // populate cm vendor address with the default remit address type for the vendor if found
339         String userCampus = GlobalVariables.getUserSession().getPerson().getCampusCode();
340         VendorAddress vendorAddress = vendorService.getVendorDefaultAddress(purchaseOrderDocument.getVendorHeaderGeneratedIdentifier(), purchaseOrderDocument.getVendorDetailAssignedIdentifier(), VendorConstants.AddressTypes.REMIT, userCampus);
341         if (vendorAddress != null) {
342             cmDocument.templateVendorAddress(vendorAddress);
343             cmDocument.setVendorAddressGeneratedIdentifier(vendorAddress.getVendorAddressGeneratedIdentifier());
344             cmDocument.setVendorAttentionName(StringUtils.defaultString(vendorAddress.getVendorAttentionName()));
345         } else {
346             // set address from PO
347             cmDocument.setVendorAddressGeneratedIdentifier(purchaseOrderDocument.getVendorAddressGeneratedIdentifier());
348             cmDocument.setVendorLine1Address(purchaseOrderDocument.getVendorLine1Address());
349             cmDocument.setVendorLine2Address(purchaseOrderDocument.getVendorLine2Address());
350             cmDocument.setVendorCityName(purchaseOrderDocument.getVendorCityName());
351             cmDocument.setVendorStateCode(purchaseOrderDocument.getVendorStateCode());
352             cmDocument.setVendorPostalCode(purchaseOrderDocument.getVendorPostalCode());
353             cmDocument.setVendorCountryCode(purchaseOrderDocument.getVendorCountryCode());
354 
355 
356             boolean blankAttentionLine = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(PurapConstants.PURAP_NAMESPACE, "Document", PurapParameterConstants.BLANK_ATTENTION_LINE_FOR_PO_TYPE_ADDRESS, false);
357             if (blankAttentionLine) {
358                 cmDocument.setVendorAttentionName(StringUtils.EMPTY);
359             } else {
360                 cmDocument.setVendorAttentionName(StringUtils.defaultString(purchaseOrderDocument.getVendorAttentionName()));
361             }
362         }
363 
364         populateItemLinesFromPO(cmDocument, expiredOrClosedAccountList);
365     }
366 
367     /**
368      * Populates the credit memo items from the payment request items.
369      *
370      * @param cmDocument - Credit Memo Document to Populate
371      */
372     @Override
373     protected void populateItemLinesFromPO(VendorCreditMemoDocument cmDocument, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
374         List<PurchaseOrderItem> invoicedItems = getPOInvoicedItems(cmDocument.getPurchaseOrderDocument());
375         for (PurchaseOrderItem poItem : invoicedItems) {
376             if ((poItem.getItemType().isQuantityBasedGeneralLedgerIndicator() && poItem.getItemInvoicedTotalQuantity().isNonZero())
377                     || (poItem.getItemType().isAmountBasedGeneralLedgerIndicator() && poItem.getItemInvoicedTotalAmount().isNonZero())) {
378                 OleCreditMemoItem olecreditMemoItem = new OleCreditMemoItem(cmDocument, (OlePurchaseOrderItem) poItem, expiredOrClosedAccountList);
379                 cmDocument.getItems().add(olecreditMemoItem);
380                 PurchasingCapitalAssetItem purchasingCAMSItem = cmDocument.getPurchaseOrderDocument().getPurchasingCapitalAssetItemByItemIdentifier(poItem.getItemIdentifier());
381                 if (purchasingCAMSItem != null) {
382                     olecreditMemoItem.setCapitalAssetTransactionTypeCode(purchasingCAMSItem.getCapitalAssetTransactionTypeCode());
383                 }
384             }
385         }
386 
387         // add below the line items
388         purapService.addBelowLineItems(cmDocument);
389 
390         cmDocument.fixItemReferences();
391     }
392 
393     @Override
394     protected void populateDocumentFromVendor(VendorCreditMemoDocument cmDocument) {
395         Integer vendorHeaderId = VendorUtils.getVendorHeaderId(cmDocument.getVendorNumber());
396         Integer vendorDetailId = VendorUtils.getVendorDetailId(cmDocument.getVendorNumber());
397 
398         VendorDetail vendorDetail = vendorService.getVendorDetail(vendorHeaderId, vendorDetailId);
399         cmDocument.setVendorDetail(vendorDetail);
400 
401         cmDocument.setVendorHeaderGeneratedIdentifier(vendorDetail.getVendorHeaderGeneratedIdentifier());
402         cmDocument.setVendorDetailAssignedIdentifier(vendorDetail.getVendorDetailAssignedIdentifier());
403         cmDocument.setVendorCustomerNumber(vendorDetail.getVendorNumber());
404         cmDocument.setVendorName(vendorDetail.getVendorName());
405         cmDocument.setPaymentMethodId(vendorDetail.getPaymentMethodId());
406 
407         // credit memo type vendor uses the default remit type address for the vendor if found
408         String userCampus = GlobalVariables.getUserSession().getPerson().getCampusCode();
409         VendorAddress vendorAddress = vendorService.getVendorDefaultAddress(vendorHeaderId, vendorDetailId, VendorConstants.AddressTypes.REMIT, userCampus);
410         if (vendorAddress == null) {
411             // pick up the default vendor po address type
412             vendorAddress = vendorService.getVendorDefaultAddress(vendorHeaderId, vendorDetailId, VendorConstants.AddressTypes.PURCHASE_ORDER, userCampus);
413         }
414 
415         cmDocument.setVendorAddressGeneratedIdentifier(vendorAddress.getVendorAddressGeneratedIdentifier());
416         cmDocument.templateVendorAddress(vendorAddress);
417 
418         // add below the line items
419         purapService.addBelowLineItems(cmDocument);
420     }
421 
422     /**
423      * @see org.kuali.ole.module.purap.document.service.CreditMemoCreateService# populateDocumentAfterInit(org.kuali.ole.module.purap.document.CreditMemoDocument)
424      */
425     @Override
426     public void populateDocumentAfterInit(VendorCreditMemoDocument cmDocument) {
427 
428         OleVendorCreditMemoDocument vendorCreditMemoDocument = (OleVendorCreditMemoDocument) cmDocument;
429         // make a call to search for expired/closed accounts
430         HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList = accountsPayableService.getExpiredOrClosedAccountList(cmDocument);
431 
432         if (vendorCreditMemoDocument.isSourceDocumentPaymentRequest() && vendorCreditMemoDocument.getInvoiceIdentifier() == null) {
433             populateDocumentFromPreq(vendorCreditMemoDocument, expiredOrClosedAccountList);
434         } else if (vendorCreditMemoDocument.isSourceDocumentPurchaseOrder() && vendorCreditMemoDocument.getInvoiceIdentifier() == null) {
435             populateDocumentFromPO(vendorCreditMemoDocument, expiredOrClosedAccountList);
436         } else if (vendorCreditMemoDocument.getInvoiceIdentifier() != null) {
437             populateDocumentFromInvoice(vendorCreditMemoDocument, expiredOrClosedAccountList);
438         } else {
439             populateDocumentFromVendor(vendorCreditMemoDocument);
440         }
441 
442         populateDocumentDescription(vendorCreditMemoDocument);
443 
444         // write a note for expired/closed accounts if any exist and add a message stating there were expired/closed accounts at the
445         // top of the document
446         accountsPayableService.generateExpiredOrClosedAccountNote(cmDocument, expiredOrClosedAccountList);
447 
448         // set indicator so a message is displayed for accounts that were replaced due to expired/closed status
449         if (ObjectUtils.isNotNull(expiredOrClosedAccountList) && !expiredOrClosedAccountList.isEmpty()) {
450             cmDocument.setContinuationAccountIndicator(true);
451         }
452 
453     }
454 
455     @Override
456     public void populateDocumentFromInvoice(OleVendorCreditMemoDocument cmDocument, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
457         OleInvoiceDocument invoiceDocument = oleInvoiceService.getInvoiceDocumentById(cmDocument.getInvoiceIdentifier());
458         //cmDocument.setPurchaseOrderDocument();
459         cmDocument.getDocumentHeader().setOrganizationDocumentNumber(invoiceDocument.getDocumentHeader().getOrganizationDocumentNumber());
460         cmDocument.setUseTaxIndicator(cmDocument.isUseTaxIndicator());
461         cmDocument.setPaymentMethodId(invoiceDocument.getPaymentMethodId());
462         cmDocument.setOlePaymentMethod(invoiceDocument.getPaymentMethod());
463         cmDocument.setVendorHeaderGeneratedIdentifier(invoiceDocument.getVendorHeaderGeneratedIdentifier());
464         cmDocument.setVendorDetailAssignedIdentifier(invoiceDocument.getVendorDetailAssignedIdentifier());
465         cmDocument.setVendorCustomerNumber(invoiceDocument.getVendorCustomerNumber());
466         cmDocument.setVendorName(invoiceDocument.getVendorName());
467         cmDocument.setAccountsPayablePurchasingDocumentLinkIdentifier(invoiceDocument.getAccountsPayablePurchasingDocumentLinkIdentifier());
468         cmDocument.setPaymentMethodId(invoiceDocument.getPaymentMethodId());
469         cmDocument.setPurchaseOrderTypeId(invoiceDocument.getPurchaseOrderTypeId());
470         // populate cm vendor address with the default remit address type for the vendor if found
471         String userCampus = GlobalVariables.getUserSession().getPerson().getCampusCode();
472         VendorAddress vendorAddress = vendorService.getVendorDefaultAddress(invoiceDocument.getVendorHeaderGeneratedIdentifier(), invoiceDocument.getVendorDetailAssignedIdentifier(), VendorConstants.AddressTypes.REMIT, userCampus);
473         if (vendorAddress != null) {
474             cmDocument.templateVendorAddress(vendorAddress);
475             cmDocument.setVendorAddressGeneratedIdentifier(vendorAddress.getVendorAddressGeneratedIdentifier());
476             cmDocument.setVendorAttentionName(StringUtils.defaultString(vendorAddress.getVendorAttentionName()));
477         } else {
478             // set address from PO
479             cmDocument.setVendorAddressGeneratedIdentifier(invoiceDocument.getVendorAddressGeneratedIdentifier());
480             cmDocument.setVendorLine1Address(invoiceDocument.getVendorLine1Address());
481             cmDocument.setVendorLine2Address(invoiceDocument.getVendorLine2Address());
482             cmDocument.setVendorCityName(invoiceDocument.getVendorCityName());
483             cmDocument.setVendorStateCode(invoiceDocument.getVendorStateCode());
484             cmDocument.setVendorPostalCode(invoiceDocument.getVendorPostalCode());
485             cmDocument.setVendorCountryCode(invoiceDocument.getVendorCountryCode());
486 
487 
488             boolean blankAttentionLine = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(PurapConstants.PURAP_NAMESPACE, "Document", PurapParameterConstants.BLANK_ATTENTION_LINE_FOR_PO_TYPE_ADDRESS, false);
489             if (blankAttentionLine) {
490                 cmDocument.setVendorAttentionName(StringUtils.EMPTY);
491             } else {
492                 cmDocument.setVendorAttentionName(StringUtils.defaultString(invoiceDocument.getVendorAttentionName()));
493             }
494         }
495 
496         //populateItemLinesFromInvoice(invoiceDocument, cmDocument, expiredOrClosedAccountList);
497     }
498 
499 
500     /**
501      * Populates the credit memo items from the payment request items.
502      *
503      * @param cmDocument - Credit Memo Document to Populate
504      */
505     @Override
506     public void populateItemLinesFromInvoice(OleInvoiceDocument invoiceDocument, OleVendorCreditMemoDocument cmDocument,
507                                              HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
508 
509         List<OleInvoiceItem> invoicedItems = invoiceDocument.getItems();
510         for (OleInvoiceItem invoiceItem : invoicedItems) {
511             if (invoiceItem.getExtendedPrice().isLessThan(AbstractKualiDecimal.ZERO)) {
512                 invoiceItem.setItemListPrice(invoiceItem.getItemListPrice().abs());
513                 KualiDecimal listPrice = invoiceItem.getItemListPrice().abs();
514                 BigDecimal unitPrice = invoiceItem.getItemUnitPrice();
515                 BigDecimal itemSurcharge = invoiceItem.getItemSurcharge();
516                 invoiceItem.setItemListPrice(listPrice);
517                 invoiceItem.setItemUnitPrice(unitPrice.abs());
518                 if (invoiceItem.getItemUnitPrice() != null) {
519                     invoiceItem.setItemUnitPrice(invoiceItem.getItemUnitPrice().abs());
520                 }
521                 if ((invoiceItem.getItemType().isQuantityBasedGeneralLedgerIndicator() && invoiceItem.getItemQuantity().isNonZero())
522                         || (invoiceItem.getItemType().isAmountBasedGeneralLedgerIndicator() && invoiceItem.getTotalAmount().isNonZero())) {
523                     OleCreditMemoItem olecreditMemoItem = new OleCreditMemoItem(invoiceItem, cmDocument, expiredOrClosedAccountList);
524                     cmDocument.getItems().add(olecreditMemoItem);
525                     PurchasingCapitalAssetItem purchasingCAMSItem = cmDocument.getPurchaseOrderDocument().getPurchasingCapitalAssetItemByItemIdentifier(invoiceItem.getItemIdentifier());
526                     if (purchasingCAMSItem != null) {
527                         olecreditMemoItem.setCapitalAssetTransactionTypeCode(purchasingCAMSItem.getCapitalAssetTransactionTypeCode());
528                     }
529                 }
530             }
531 
532         }
533 
534         // add below the line items
535         purapService.addBelowLineItems(cmDocument);
536 
537         cmDocument.fixItemReferences();
538     }
539 
540     /**
541      * NOTE: in the event of auto-approval failure, this method may throw a RuntimeException, indicating to Spring transactional
542      * management that the transaction should be rolled back.
543      *
544      * @see org.kuali.ole.select.document.service.OleCreditMemoService# autoApproveCreditMemo(org.kuali.ole.module.purap.document.PaymentRequestDocument,
545      *      org.kuali.rice.core.api.util.type.KualiDecimal)
546      */
547     @Override
548     public boolean autoApproveCreditMemo(OleVendorCreditMemoDocument creditMemoDoc) {
549         try {
550             // Much of the rice frameworks assumes that document instances that are saved via DocumentService.saveDocument are
551             // those
552             // that were dynamically created by PojoFormBase (i.e., the Document instance wasn't created from OJB). We need to
553             // make
554             // a deep copy and materialize collections to fulfill that assumption so that collection elements will delete
555             // properly
556 
557             // TODO: maybe rewriting PurapService.calculateItemTax could be rewritten so that the a deep copy doesn't need to be
558             // made
559             // by taking advantage of OJB's managed array lists
560             try {
561                 ObjectUtils.materializeUpdateableCollections(creditMemoDoc);
562                 for (OleCreditMemoItem item : (List<OleCreditMemoItem>) creditMemoDoc.getItems()) {
563                     ObjectUtils.materializeUpdateableCollections(item);
564                 }
565             } catch (Exception ex) {
566                 throw new RuntimeException(ex);
567             }
568             creditMemoDoc = (OleVendorCreditMemoDocument) ObjectUtils.deepCopy(creditMemoDoc);
569             //purapService.updateStatus(doc, PaymentRequestStatuses.AUTO_APPROVED);
570             creditMemoDoc.updateAndSaveAppDocStatus(PurapConstants.CreditMemoStatuses.APPDOC_COMPLETE);
571 
572             documentService.blanketApproveDocument(creditMemoDoc, "auto-approving: Total is below threshold.", null);
573         } catch (WorkflowException we) {
574             LOG.error("Exception encountered when approving document number " + creditMemoDoc.getDocumentNumber() + ".", we);
575             // throw a runtime exception up so that we can force a rollback
576             throw new RuntimeException("Exception encountered when approving document number " + creditMemoDoc.getDocumentNumber() + ".", we);
577         }
578         return true;
579     }
580 }