001/* 002 * Copyright 2007 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 */ 016package org.kuali.ole.select.document.service.impl; 017 018import org.apache.commons.collections.CollectionUtils; 019import org.apache.commons.lang.StringUtils; 020import org.kuali.ole.module.purap.PurapConstants; 021import org.kuali.ole.module.purap.PurapParameterConstants; 022import org.kuali.ole.module.purap.businessobject.*; 023import org.kuali.ole.module.purap.document.PaymentRequestDocument; 024import org.kuali.ole.module.purap.document.PurchaseOrderDocument; 025import org.kuali.ole.module.purap.document.VendorCreditMemoDocument; 026import org.kuali.ole.module.purap.document.service.AccountsPayableService; 027import org.kuali.ole.module.purap.document.service.PurapService; 028import org.kuali.ole.module.purap.document.service.impl.CreditMemoServiceImpl; 029import org.kuali.ole.module.purap.service.PurapAccountingService; 030import org.kuali.ole.module.purap.util.ExpiredOrClosedAccountEntry; 031import org.kuali.ole.select.businessobject.OleCreditMemoItem; 032import org.kuali.ole.select.businessobject.OleInvoiceItem; 033import org.kuali.ole.select.businessobject.OlePaymentRequestItem; 034import org.kuali.ole.select.businessobject.OlePurchaseOrderItem; 035import org.kuali.ole.select.document.OleInvoiceDocument; 036import org.kuali.ole.select.document.OlePaymentRequestDocument; 037import org.kuali.ole.select.document.OleVendorCreditMemoDocument; 038import org.kuali.ole.select.document.service.*; 039import org.kuali.ole.sys.OLEConstants; 040import org.kuali.ole.sys.OLEKeyConstants; 041import org.kuali.ole.sys.businessobject.SourceAccountingLine; 042import org.kuali.ole.vnd.VendorConstants; 043import org.kuali.ole.vnd.VendorUtils; 044import org.kuali.ole.vnd.businessobject.VendorAddress; 045import org.kuali.ole.vnd.businessobject.VendorDetail; 046import org.kuali.ole.vnd.document.service.VendorService; 047import org.kuali.rice.core.api.util.type.AbstractKualiDecimal; 048import org.kuali.rice.core.api.util.type.KualiDecimal; 049import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator; 050import org.kuali.rice.kew.api.exception.WorkflowException; 051import org.kuali.rice.krad.service.DocumentService; 052import org.kuali.rice.krad.util.GlobalVariables; 053import org.kuali.rice.krad.util.ObjectUtils; 054import org.springframework.transaction.annotation.Transactional; 055 056import java.math.BigDecimal; 057import java.math.RoundingMode; 058import java.util.ArrayList; 059import java.util.HashMap; 060import java.util.List; 061 062/** 063 * Provides services to support the creation of a Credit Memo Document. 064 */ 065@Transactional 066public class OleCreditMemoServiceImpl extends CreditMemoServiceImpl implements OleCreditMemoService { 067 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OleCreditMemoServiceImpl.class); 068 069 private PurapAccountingService purapAccountingService; 070 private PurapService purapService; 071 private OlePaymentRequestService olePaymentRequestService; 072 private VendorService vendorService; 073 private OlePurchaseOrderService olePurchaseOrderService; 074 private OleInvoiceService oleInvoiceService; 075 private AccountsPayableService accountsPayableService; 076 private DocumentService documentService; 077 private OlePurapAccountingService olePurapAccountingService; 078 079 080 081 public void setOlePurchaseOrderService(OlePurchaseOrderService olePurchaseOrderService) { 082 this.olePurchaseOrderService = olePurchaseOrderService; 083 } 084 085 @Override 086 public void setVendorService(VendorService vendorService) { 087 this.vendorService = vendorService; 088 } 089 090 public void setOlePaymentRequestService(OlePaymentRequestService olePaymentRequestService) { 091 this.olePaymentRequestService = olePaymentRequestService; 092 } 093 094 @Override 095 public void setPurapAccountingService(PurapAccountingService purapAccountingService) { 096 this.purapAccountingService = purapAccountingService; 097 } 098 099 @Override 100 public void setPurapService(PurapService purapService) { 101 this.purapService = purapService; 102 } 103 104 public void setOleInvoiceService(OleInvoiceService oleInvoiceService) { 105 this.oleInvoiceService = oleInvoiceService; 106 } 107 108 public void setAccountsPayableService(AccountsPayableService accountsPayableService) { 109 this.accountsPayableService = accountsPayableService; 110 } 111 112 public void setDocumentService(DocumentService documentService) { 113 this.documentService = documentService; 114 } 115 116 public void setOlePurapAccountingService(OlePurapAccountingService olePurapAccountingService) { 117 this.olePurapAccountingService = olePurapAccountingService; 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 OleVendorCreditMemoDocument oleVendorCreditMemoDocument = (OleVendorCreditMemoDocument) cmDocument; 126 cmDocument.updateExtendedPriceOnItems(); 127 KualiDecimal totalAmount = KualiDecimal.ZERO; 128 KualiDecimal totalQty = KualiDecimal.ZERO; 129 KualiDecimal totalSurcharge = KualiDecimal.ZERO; 130 List<PurApItem> items = new ArrayList<>(); 131 //purapAccountingService.updateAccountAmounts(cmDocument); 132 for (OleCreditMemoItem item : (List<OleCreditMemoItem>) cmDocument.getItems()) { 133 // make sure restocking fee is negative 134 if (StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_RESTCK_FEE_CODE, item.getItemTypeCode())) { 135 if (item.getItemUnitPrice() != null) { 136 item.setExtendedPrice(item.getExtendedPrice().abs().negated()); 137 item.setItemUnitPrice(item.getItemUnitPrice().abs().negate()); 138 } 139 } 140 if (StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_MISC_CRDT_CODE, item.getItemTypeCode()) || 141 StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_RESTCK_FEE_CODE, item.getItemTypeCode()) || 142 StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_FREIGHT_CODE, item.getItemTypeCode()) || 143 StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_SHIP_AND_HAND_CODE, item.getItemTypeCode()) || 144 StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_MISC_CODE, item.getItemTypeCode()) || 145 StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_MIN_ORDER_CODE, item.getItemTypeCode())) { 146 if (item.getItemUnitPrice() != null && ((OleVendorCreditMemoDocument)cmDocument).getInvoiceIdentifier() == null) { 147 calculateProrateItemSurcharge((OleVendorCreditMemoDocument) cmDocument); 148 } 149 }if(item.getItemType().isQuantityBasedGeneralLedgerIndicator()) { 150 // invoiceItem.setRelatedViews(null); 151 if (item.getItemQuantity() != null) { 152 totalQty = totalQty.add(item.getItemQuantity()); 153 } 154 } 155 156 if (!(item.getItemType().isQuantityBasedGeneralLedgerIndicator()) && item.getExtendedPrice()!=null) { 157 totalSurcharge = totalSurcharge.add(item.getExtendedPrice()); 158 } 159 items.add(item); 160 } 161 162 //calculate tax if cm not based on vendor 163 if (cmDocument.isSourceVendor() == false) { 164 purapService.calculateTax(cmDocument); 165 } 166 167 // proration 168 if (cmDocument.isSourceVendor()) { 169 // no proration on vendor 170 return; 171 } 172 173 oleVendorCreditMemoDocument.setProrateBy(oleVendorCreditMemoDocument.isProrateQty() ? 174 OLEConstants.PRORATE_BY_QTY : oleVendorCreditMemoDocument.isProrateManual() ? 175 OLEConstants.MANUAL_PRORATE : oleVendorCreditMemoDocument.isProrateDollar() ? 176 OLEConstants.PRORATE_BY_DOLLAR : oleVendorCreditMemoDocument.isNoProrate() ? 177 OLEConstants.NO_PRORATE : null); 178 for (OleCreditMemoItem item : (List<OleCreditMemoItem>) cmDocument.getItems()) { 179 180 // skip above the line 181 if (item.getItemType().isLineItemIndicator()) { 182 continue; 183 } 184 totalAmount = cmDocument.getTotalDollarAmountAboveLineItems(); 185 totalAmount = totalAmount.subtract(totalSurcharge); 186 // purapAccountingService.updateAccountAmounts(invoiceDocument); 187 188 if ((ObjectUtils.isNotNull(item.getExtendedPrice())) && (KualiDecimal.ZERO.compareTo(item.getExtendedPrice()) != 0)) { 189 190 List<PurApAccountingLine> distributedAccounts = null; 191 List<SourceAccountingLine> summaryAccounts = null; 192 193 totalAmount = cmDocument.getLineItemTotal(); 194 // this should do nothing on preq which is fine 195 if(oleVendorCreditMemoDocument.isProrateDollar() || oleVendorCreditMemoDocument.isProrateQty()){ 196 summaryAccounts = olePurapAccountingService.generateSummary(items); 197 } 198 if(oleVendorCreditMemoDocument.isProrateDollar()){ 199 distributedAccounts = olePurapAccountingService.generateAccountDistributionForProration(summaryAccounts, totalAmount, PurapConstants.PRORATION_SCALE, CreditMemoAccount.class); 200 }else if(oleVendorCreditMemoDocument.isProrateQty()) { 201 distributedAccounts = olePurapAccountingService.generateAccountDistributionForProrationByQty(summaryAccounts, totalQty, PurapConstants.PRORATION_SCALE, CreditMemoAccount.class); 202 } 203 204 if (CollectionUtils.isNotEmpty(distributedAccounts) ) { 205 item.setSourceAccountingLines(distributedAccounts); 206 } 207 } 208 purapAccountingService.updateItemAccountAmounts(item); 209 210 } 211 purapAccountingService.updateAccountAmounts(cmDocument); 212 // end proration 213 } 214 215 216 public void calculateProrateItemSurcharge(OleVendorCreditMemoDocument vendorCreditMemoDocument) { 217 LOG.debug("Inside Calculation for ProrateItemSurcharge"); 218 vendorCreditMemoDocument.setProrateBy(vendorCreditMemoDocument.isProrateQty() ? OLEConstants.PRORATE_BY_QTY : 219 vendorCreditMemoDocument.isProrateManual() ? OLEConstants.MANUAL_PRORATE : 220 vendorCreditMemoDocument.isProrateDollar() ? OLEConstants.PRORATE_BY_DOLLAR : vendorCreditMemoDocument.isNoProrate() ? OLEConstants.NO_PRORATE : null); 221 BigDecimal addChargeItem = BigDecimal.ZERO; 222 List<OleCreditMemoItem> item = (List<OleCreditMemoItem>) vendorCreditMemoDocument.getItems(); 223 for (OleCreditMemoItem items : item) { 224 if (!items.getItemType().isQuantityBasedGeneralLedgerIndicator() && !items.getItemTypeCode().equalsIgnoreCase(PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE) && items.getItemUnitPrice() != null) { 225 addChargeItem = addChargeItem.add(items.getItemUnitPrice()); 226 } 227 } 228 List<BigDecimal> newUnitPriceList = new ArrayList<BigDecimal>(); 229 BigDecimal totalExtPrice = new BigDecimal(0); 230 BigDecimal newUnitPrice = new BigDecimal(0); 231 BigDecimal extPrice = new BigDecimal(0); 232 BigDecimal unitPricePercent = new BigDecimal(0); 233 BigDecimal hundred = new BigDecimal(100); 234 BigDecimal one = new BigDecimal(1); 235 BigDecimal totalSurCharge = new BigDecimal(0); 236 BigDecimal totalItemQuantity = new BigDecimal(0); 237 BigDecimal itemSurchargeCons = new BigDecimal(0); 238 for (int i = 0; item.size() > i; i++) { 239 OleCreditMemoItem items = (OleCreditMemoItem) vendorCreditMemoDocument.getItem(i); 240 if ((items.getItemType().isQuantityBasedGeneralLedgerIndicator()) && !ObjectUtils.isNull(items.getItemQuantity())) { 241 if (vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.PRORATE_BY_QTY)) { 242 totalItemQuantity = totalItemQuantity.add(items.getItemQuantity().bigDecimalValue()); 243 } 244 if (vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.PRORATE_BY_DOLLAR) || vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.MANUAL_PRORATE) || vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.PRORATE_BY_QTY)) { 245 /*if (items.getItemDiscount() == null) { 246 items.setItemDiscount(KualiDecimal.ZERO); 247 } 248 if (items.getItemDiscountType() != null && items.getItemDiscountType().equalsIgnoreCase(OleSelectConstant.DISCOUNT_TYPE_PERCENTAGE)) { 249 newUnitPrice = (hundred.subtract(items.getItemDiscount().bigDecimalValue())).divide(hundred).multiply(items.getItemListPrice().bigDecimalValue()); 250 } 251 else { 252 newUnitPrice = items.getItemListPrice().bigDecimalValue().subtract(items.getItemDiscount().bigDecimalValue()); 253 }*/ 254 newUnitPrice = items.getItemUnitPrice(); 255 newUnitPriceList.add(newUnitPrice); 256 extPrice = newUnitPrice.multiply(items.getItemQuantity().bigDecimalValue()); 257 totalExtPrice = totalExtPrice.add(extPrice); 258 } 259 if (vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.MANUAL_PRORATE)) { 260 if (items.getItemSurcharge() == null) { 261 items.setItemSurcharge(BigDecimal.ZERO); 262 } 263 totalSurCharge = totalSurCharge.add(items.getItemQuantity().bigDecimalValue().multiply(items.getItemSurcharge())); 264 } 265 } 266 267 } 268 if (vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.PRORATE_BY_QTY)) { 269 if (totalItemQuantity.compareTo(BigDecimal.ZERO) != 0) { 270 itemSurchargeCons = one.divide(totalItemQuantity, 8, RoundingMode.HALF_UP); 271 } 272 } 273 for (int i = 0, j = 0; item.size() > i; i++) { 274 OleCreditMemoItem items = (OleCreditMemoItem) vendorCreditMemoDocument.getItem(i); 275 if (items.getItemType().isQuantityBasedGeneralLedgerIndicator() && newUnitPriceList.size() > j && !ObjectUtils.isNull(items.getItemQuantity())) { 276 if (vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.PRORATE_BY_DOLLAR)) { 277 if (totalExtPrice.compareTo(BigDecimal.ZERO) != 0) { 278 unitPricePercent = newUnitPriceList.get(j).divide(totalExtPrice, 8, RoundingMode.HALF_UP); 279 } 280 items.setItemSurcharge(unitPricePercent.multiply(addChargeItem).setScale(4, RoundingMode.HALF_UP)); 281 items.setExtendedPrice((new KualiDecimal((newUnitPriceList.get(j).add(items.getItemSurcharge()).toString()))).multiply(items.getItemQuantity())); 282 } 283 if (vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.PRORATE_BY_QTY)) { 284 items.setItemSurcharge(itemSurchargeCons.multiply(addChargeItem).setScale(4, RoundingMode.HALF_UP)); 285 items.setExtendedPrice(new KualiDecimal(((newUnitPriceList.get(j).add(items.getItemSurcharge()).toString()))).multiply(items.getItemQuantity())); 286 } 287 if (vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.MANUAL_PRORATE) && items.getItemSurcharge() != null) { 288 items.setExtendedPrice(new KualiDecimal(((newUnitPriceList.get(j).add(items.getItemSurcharge()).toString()))).multiply(items.getItemQuantity())); 289 } 290 j++; 291 } 292 } 293 if (vendorCreditMemoDocument.getProrateBy().equals(OLEConstants.MANUAL_PRORATE)) { 294 if (totalSurCharge.compareTo(addChargeItem) != 0) { 295 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OLEKeyConstants.ERROR_PAYMENT_REQUEST_TOTAL_MISMATCH); 296 } 297 } 298 LOG.debug("Leaving Calculation for ProrateItemSurcharge"); 299 } 300 301 302 /** 303 * Populates the credit memo items from the payment request items. 304 * 305 * @param cmDocument - Credit Memo Document to Populate 306 */ 307 @Override 308 protected void populateItemLinesFromPreq(VendorCreditMemoDocument cmDocument, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) { 309 OlePaymentRequestDocument preqDocument = (OlePaymentRequestDocument) cmDocument.getPaymentRequestDocument(); 310 311 for (OlePaymentRequestItem preqItemToTemplate : (List<OlePaymentRequestItem>) preqDocument.getItems()) { 312 if (preqItemToTemplate.getItemType().isLineItemIndicator() && ((preqItemToTemplate.getItemType().isQuantityBasedGeneralLedgerIndicator() && preqItemToTemplate.getItemQuantity().isNonZero()) 313 || (preqItemToTemplate.getItemType().isAmountBasedGeneralLedgerIndicator() && preqItemToTemplate.getTotalAmount().isNonZero()))) { 314 cmDocument.getItems().add(new OleCreditMemoItem(cmDocument, preqItemToTemplate, (OlePurchaseOrderItem) preqItemToTemplate.getPurchaseOrderItem(), expiredOrClosedAccountList)); 315 } 316 } 317 318 // add below the line items 319 purapService.addBelowLineItems(cmDocument); 320 321 cmDocument.fixItemReferences(); 322 } 323 324 /** 325 * Populate Credit Memo of type Payment Request. 326 * 327 * @param cmDocument - Credit Memo Document to Populate 328 */ 329 @Override 330 protected void populateDocumentFromPreq(VendorCreditMemoDocument cmDocument, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) { 331 PaymentRequestDocument paymentRequestDocument = olePaymentRequestService.getPaymentRequestById(cmDocument.getPaymentRequestIdentifier()); 332 cmDocument.getDocumentHeader().setOrganizationDocumentNumber(paymentRequestDocument.getDocumentHeader().getOrganizationDocumentNumber()); 333 cmDocument.setPaymentRequestDocument(paymentRequestDocument); 334 cmDocument.setPurchaseOrderDocument(paymentRequestDocument.getPurchaseOrderDocument()); 335 cmDocument.setUseTaxIndicator(paymentRequestDocument.isUseTaxIndicator()); 336 337 // credit memo address taken directly from payment request 338 cmDocument.setVendorHeaderGeneratedIdentifier(paymentRequestDocument.getVendorHeaderGeneratedIdentifier()); 339 cmDocument.setVendorDetailAssignedIdentifier(paymentRequestDocument.getVendorDetailAssignedIdentifier()); 340 cmDocument.setVendorAddressGeneratedIdentifier(paymentRequestDocument.getVendorAddressGeneratedIdentifier()); 341 cmDocument.setVendorCustomerNumber(paymentRequestDocument.getVendorCustomerNumber()); 342 cmDocument.setVendorName(paymentRequestDocument.getVendorName()); 343 cmDocument.setVendorLine1Address(paymentRequestDocument.getVendorLine1Address()); 344 cmDocument.setVendorLine2Address(paymentRequestDocument.getVendorLine2Address()); 345 cmDocument.setVendorCityName(paymentRequestDocument.getVendorCityName()); 346 cmDocument.setVendorStateCode(paymentRequestDocument.getVendorStateCode()); 347 cmDocument.setVendorPostalCode(paymentRequestDocument.getVendorPostalCode()); 348 cmDocument.setVendorCountryCode(paymentRequestDocument.getVendorCountryCode()); 349 cmDocument.setVendorAttentionName(paymentRequestDocument.getVendorAttentionName()); 350 cmDocument.setAccountsPayablePurchasingDocumentLinkIdentifier(paymentRequestDocument.getAccountsPayablePurchasingDocumentLinkIdentifier()); 351 cmDocument.setPaymentMethodId(paymentRequestDocument.getVendorDetail().getPaymentMethodId()); 352 cmDocument.setPurchaseOrderTypeId(paymentRequestDocument.getPurchaseOrderTypeId()); 353 // prep the item lines (also collect warnings for later display) this is only done on paymentRequest 354 purapAccountingService.convertMoneyToPercent(paymentRequestDocument); 355 populateItemLinesFromPreq(cmDocument, expiredOrClosedAccountList); 356 } 357 358 359 @Override 360 protected void populateDocumentFromPO(VendorCreditMemoDocument cmDocument, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) { 361 PurchaseOrderDocument purchaseOrderDocument = olePurchaseOrderService.getCurrentPurchaseOrder(cmDocument.getPurchaseOrderIdentifier()); 362 cmDocument.setPurchaseOrderDocument(purchaseOrderDocument); 363 cmDocument.getDocumentHeader().setOrganizationDocumentNumber(purchaseOrderDocument.getDocumentHeader().getOrganizationDocumentNumber()); 364 cmDocument.setUseTaxIndicator(cmDocument.isUseTaxIndicator()); 365 366 cmDocument.setVendorHeaderGeneratedIdentifier(purchaseOrderDocument.getVendorHeaderGeneratedIdentifier()); 367 cmDocument.setVendorDetailAssignedIdentifier(purchaseOrderDocument.getVendorDetailAssignedIdentifier()); 368 cmDocument.setVendorCustomerNumber(purchaseOrderDocument.getVendorCustomerNumber()); 369 cmDocument.setVendorName(purchaseOrderDocument.getVendorName()); 370 cmDocument.setAccountsPayablePurchasingDocumentLinkIdentifier(purchaseOrderDocument.getAccountsPayablePurchasingDocumentLinkIdentifier()); 371 cmDocument.setPaymentMethodId(purchaseOrderDocument.getVendorDetail().getPaymentMethodId()); 372 cmDocument.setPurchaseOrderTypeId(purchaseOrderDocument.getPurchaseOrderTypeId()); 373 // populate cm vendor address with the default remit address type for the vendor if found 374 String userCampus = GlobalVariables.getUserSession().getPerson().getCampusCode(); 375 VendorAddress vendorAddress = vendorService.getVendorDefaultAddress(purchaseOrderDocument.getVendorHeaderGeneratedIdentifier(), purchaseOrderDocument.getVendorDetailAssignedIdentifier(), VendorConstants.AddressTypes.REMIT, userCampus); 376 if (vendorAddress != null) { 377 cmDocument.templateVendorAddress(vendorAddress); 378 cmDocument.setVendorAddressGeneratedIdentifier(vendorAddress.getVendorAddressGeneratedIdentifier()); 379 cmDocument.setVendorAttentionName(StringUtils.defaultString(vendorAddress.getVendorAttentionName())); 380 } else { 381 // set address from PO 382 cmDocument.setVendorAddressGeneratedIdentifier(purchaseOrderDocument.getVendorAddressGeneratedIdentifier()); 383 cmDocument.setVendorLine1Address(purchaseOrderDocument.getVendorLine1Address()); 384 cmDocument.setVendorLine2Address(purchaseOrderDocument.getVendorLine2Address()); 385 cmDocument.setVendorCityName(purchaseOrderDocument.getVendorCityName()); 386 cmDocument.setVendorStateCode(purchaseOrderDocument.getVendorStateCode()); 387 cmDocument.setVendorPostalCode(purchaseOrderDocument.getVendorPostalCode()); 388 cmDocument.setVendorCountryCode(purchaseOrderDocument.getVendorCountryCode()); 389 390 391 boolean blankAttentionLine = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(PurapConstants.PURAP_NAMESPACE, "Document", PurapParameterConstants.BLANK_ATTENTION_LINE_FOR_PO_TYPE_ADDRESS, false); 392 if (blankAttentionLine) { 393 cmDocument.setVendorAttentionName(StringUtils.EMPTY); 394 } else { 395 cmDocument.setVendorAttentionName(StringUtils.defaultString(purchaseOrderDocument.getVendorAttentionName())); 396 } 397 } 398 399 populateItemLinesFromPO(cmDocument, expiredOrClosedAccountList); 400 } 401 402 /** 403 * Populates the credit memo items from the payment request items. 404 * 405 * @param cmDocument - Credit Memo Document to Populate 406 */ 407 @Override 408 protected void populateItemLinesFromPO(VendorCreditMemoDocument cmDocument, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) { 409 List<PurchaseOrderItem> invoicedItems = getPOInvoicedItems(cmDocument.getPurchaseOrderDocument()); 410 for (PurchaseOrderItem poItem : invoicedItems) { 411 if ((poItem.getItemType().isQuantityBasedGeneralLedgerIndicator() && poItem.getItemInvoicedTotalQuantity().isNonZero()) 412 || (poItem.getItemType().isAmountBasedGeneralLedgerIndicator() && poItem.getItemInvoicedTotalAmount().isNonZero())) { 413 OleCreditMemoItem olecreditMemoItem = new OleCreditMemoItem(cmDocument, (OlePurchaseOrderItem) poItem, expiredOrClosedAccountList); 414 cmDocument.getItems().add(olecreditMemoItem); 415 PurchasingCapitalAssetItem purchasingCAMSItem = cmDocument.getPurchaseOrderDocument().getPurchasingCapitalAssetItemByItemIdentifier(poItem.getItemIdentifier()); 416 if (purchasingCAMSItem != null) { 417 olecreditMemoItem.setCapitalAssetTransactionTypeCode(purchasingCAMSItem.getCapitalAssetTransactionTypeCode()); 418 } 419 } 420 } 421 422 // add below the line items 423 purapService.addBelowLineItems(cmDocument); 424 425 cmDocument.fixItemReferences(); 426 } 427 428 @Override 429 protected void populateDocumentFromVendor(VendorCreditMemoDocument cmDocument) { 430 Integer vendorHeaderId = VendorUtils.getVendorHeaderId(cmDocument.getVendorNumber()); 431 Integer vendorDetailId = VendorUtils.getVendorDetailId(cmDocument.getVendorNumber()); 432 433 VendorDetail vendorDetail = vendorService.getVendorDetail(vendorHeaderId, vendorDetailId); 434 cmDocument.setVendorDetail(vendorDetail); 435 436 cmDocument.setVendorHeaderGeneratedIdentifier(vendorDetail.getVendorHeaderGeneratedIdentifier()); 437 cmDocument.setVendorDetailAssignedIdentifier(vendorDetail.getVendorDetailAssignedIdentifier()); 438 cmDocument.setVendorCustomerNumber(vendorDetail.getVendorNumber()); 439 cmDocument.setVendorName(vendorDetail.getVendorName()); 440 cmDocument.setPaymentMethodId(vendorDetail.getPaymentMethodId()); 441 442 // credit memo type vendor uses the default remit type address for the vendor if found 443 String userCampus = GlobalVariables.getUserSession().getPerson().getCampusCode(); 444 VendorAddress vendorAddress = vendorService.getVendorDefaultAddress(vendorHeaderId, vendorDetailId, VendorConstants.AddressTypes.REMIT, userCampus); 445 if (vendorAddress == null) { 446 // pick up the default vendor po address type 447 vendorAddress = vendorService.getVendorDefaultAddress(vendorHeaderId, vendorDetailId, VendorConstants.AddressTypes.PURCHASE_ORDER, userCampus); 448 } 449 450 cmDocument.setVendorAddressGeneratedIdentifier(vendorAddress.getVendorAddressGeneratedIdentifier()); 451 cmDocument.templateVendorAddress(vendorAddress); 452 453 // add below the line items 454 purapService.addBelowLineItems(cmDocument); 455 } 456 457 /** 458 * @see org.kuali.ole.module.purap.document.service.CreditMemoCreateService# populateDocumentAfterInit(org.kuali.ole.module.purap.document.CreditMemoDocument) 459 */ 460 @Override 461 public void populateDocumentAfterInit(VendorCreditMemoDocument cmDocument) { 462 463 OleVendorCreditMemoDocument vendorCreditMemoDocument = (OleVendorCreditMemoDocument) cmDocument; 464 // make a call to search for expired/closed accounts 465 HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList = accountsPayableService.getExpiredOrClosedAccountList(cmDocument); 466 467 if (vendorCreditMemoDocument.isSourceDocumentPaymentRequest() && vendorCreditMemoDocument.getInvoiceIdentifier() == null) { 468 populateDocumentFromPreq(vendorCreditMemoDocument, expiredOrClosedAccountList); 469 } else if (vendorCreditMemoDocument.isSourceDocumentPurchaseOrder() && vendorCreditMemoDocument.getInvoiceIdentifier() == null) { 470 populateDocumentFromPO(vendorCreditMemoDocument, expiredOrClosedAccountList); 471 } else if (vendorCreditMemoDocument.getInvoiceIdentifier() != null) { 472 populateDocumentFromInvoice(vendorCreditMemoDocument, expiredOrClosedAccountList); 473 } else { 474 populateDocumentFromVendor(vendorCreditMemoDocument); 475 } 476 477 populateDocumentDescription(vendorCreditMemoDocument); 478 479 // write a note for expired/closed accounts if any exist and add a message stating there were expired/closed accounts at the 480 // top of the document 481 accountsPayableService.generateExpiredOrClosedAccountNote(cmDocument, expiredOrClosedAccountList); 482 483 // set indicator so a message is displayed for accounts that were replaced due to expired/closed status 484 if (ObjectUtils.isNotNull(expiredOrClosedAccountList) && !expiredOrClosedAccountList.isEmpty()) { 485 cmDocument.setContinuationAccountIndicator(true); 486 } 487 488 } 489 490 @Override 491 public void populateDocumentFromInvoice(OleVendorCreditMemoDocument cmDocument, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) { 492 OleInvoiceDocument invoiceDocument = oleInvoiceService.getInvoiceDocumentById(cmDocument.getInvoiceIdentifier()); 493 //cmDocument.setPurchaseOrderDocument(); 494 cmDocument.getDocumentHeader().setOrganizationDocumentNumber(invoiceDocument.getDocumentHeader().getOrganizationDocumentNumber()); 495 cmDocument.setUseTaxIndicator(cmDocument.isUseTaxIndicator()); 496 cmDocument.setPaymentMethodId(invoiceDocument.getPaymentMethodId()); 497 cmDocument.setOlePaymentMethod(invoiceDocument.getPaymentMethod()); 498 cmDocument.setVendorHeaderGeneratedIdentifier(invoiceDocument.getVendorHeaderGeneratedIdentifier()); 499 cmDocument.setVendorDetailAssignedIdentifier(invoiceDocument.getVendorDetailAssignedIdentifier()); 500 cmDocument.setVendorCustomerNumber(invoiceDocument.getVendorCustomerNumber()); 501 cmDocument.setVendorName(invoiceDocument.getVendorName()); 502 // cmDocument.setAccountsPayablePurchasingDocumentLinkIdentifier(invoiceDocument.getAccountsPayablePurchasingDocumentLinkIdentifier()); 503 cmDocument.setPaymentMethodId(invoiceDocument.getPaymentMethodId()); 504 cmDocument.setPurchaseOrderTypeId(invoiceDocument.getPurchaseOrderTypeId()); 505 // populate cm vendor address with the default remit address type for the vendor if found 506 String userCampus = GlobalVariables.getUserSession().getPerson().getCampusCode(); 507 VendorAddress vendorAddress = vendorService.getVendorDefaultAddress(invoiceDocument.getVendorHeaderGeneratedIdentifier(), invoiceDocument.getVendorDetailAssignedIdentifier(), VendorConstants.AddressTypes.REMIT, userCampus); 508 if (vendorAddress != null) { 509 cmDocument.templateVendorAddress(vendorAddress); 510 cmDocument.setVendorAddressGeneratedIdentifier(vendorAddress.getVendorAddressGeneratedIdentifier()); 511 cmDocument.setVendorAttentionName(StringUtils.defaultString(vendorAddress.getVendorAttentionName())); 512 } else { 513 // set address from PO 514 cmDocument.setVendorAddressGeneratedIdentifier(invoiceDocument.getVendorAddressGeneratedIdentifier()); 515 cmDocument.setVendorLine1Address(invoiceDocument.getVendorLine1Address()); 516 cmDocument.setVendorLine2Address(invoiceDocument.getVendorLine2Address()); 517 cmDocument.setVendorCityName(invoiceDocument.getVendorCityName()); 518 cmDocument.setVendorStateCode(invoiceDocument.getVendorStateCode()); 519 cmDocument.setVendorPostalCode(invoiceDocument.getVendorPostalCode()); 520 cmDocument.setVendorCountryCode(invoiceDocument.getVendorCountryCode()); 521 522 523 boolean blankAttentionLine = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(PurapConstants.PURAP_NAMESPACE, "Document", PurapParameterConstants.BLANK_ATTENTION_LINE_FOR_PO_TYPE_ADDRESS, false); 524 if (blankAttentionLine) { 525 cmDocument.setVendorAttentionName(StringUtils.EMPTY); 526 } else { 527 cmDocument.setVendorAttentionName(StringUtils.defaultString(invoiceDocument.getVendorAttentionName())); 528 } 529 } 530 531 //populateItemLinesFromInvoice(invoiceDocument, cmDocument, expiredOrClosedAccountList); 532 } 533 534 535 /** 536 * Populates the credit memo items from the payment request items. 537 * 538 * @param cmDocument - Credit Memo Document to Populate 539 */ 540 @Override 541 public void populateItemLinesFromInvoice(OleInvoiceDocument invoiceDocument, OleVendorCreditMemoDocument cmDocument, 542 HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) { 543 544 List<OleInvoiceItem> invoicedItems = invoiceDocument.getItems(); 545 for (OleInvoiceItem invoiceItem : invoicedItems) { 546 if (invoiceItem.getExtendedPrice().isLessThan(AbstractKualiDecimal.ZERO)) { 547 /*invoiceItem.setItemListPrice(invoiceItem.getItemListPrice().abs()); 548 KualiDecimal listPrice = invoiceItem.getItemListPrice().abs(); 549 BigDecimal unitPrice = invoiceItem.getItemUnitPrice(); 550 BigDecimal itemSurcharge = invoiceItem.getItemSurcharge(); 551 invoiceItem.setItemListPrice(listPrice); 552 invoiceItem.setItemUnitPrice(unitPrice.abs()); 553 if (invoiceItem.getItemUnitPrice() != null) { 554 invoiceItem.setItemUnitPrice(invoiceItem.getItemUnitPrice().abs()); 555 }*/ 556 if (!invoiceItem.isDebitItem() && ((invoiceItem.getItemType().isQuantityBasedGeneralLedgerIndicator() && invoiceItem.getItemQuantity().isNonZero()) 557 || (invoiceItem.getItemType().isAmountBasedGeneralLedgerIndicator() && invoiceItem.getTotalAmount().isNonZero()))) { 558 OleCreditMemoItem olecreditMemoItem = new OleCreditMemoItem(invoiceItem, cmDocument, expiredOrClosedAccountList); 559 cmDocument.getItems().add(olecreditMemoItem); 560 PurchasingCapitalAssetItem purchasingCAMSItem = cmDocument.getPurchaseOrderDocument().getPurchasingCapitalAssetItemByItemIdentifier(invoiceItem.getItemIdentifier()); 561 if (purchasingCAMSItem != null) { 562 olecreditMemoItem.setCapitalAssetTransactionTypeCode(purchasingCAMSItem.getCapitalAssetTransactionTypeCode()); 563 } 564 } 565 } 566 567 } 568 569 // add below the line items 570 purapService.addBelowLineItems(cmDocument); 571 572 cmDocument.fixItemReferences(); 573 } 574 575 /** 576 * NOTE: in the event of auto-approval failure, this method may throw a RuntimeException, indicating to Spring transactional 577 * management that the transaction should be rolled back. 578 * 579 * @see org.kuali.ole.select.document.service.OleCreditMemoService# autoApproveCreditMemo(org.kuali.ole.module.purap.document.PaymentRequestDocument, 580 * org.kuali.rice.core.api.util.type.KualiDecimal) 581 */ 582 @Override 583 public boolean autoApproveCreditMemo(OleVendorCreditMemoDocument creditMemoDoc) { 584 try { 585 // Much of the rice frameworks assumes that document instances that are saved via DocumentService.saveDocument are 586 // those 587 // that were dynamically created by PojoFormBase (i.e., the Document instance wasn't created from OJB). We need to 588 // make 589 // a deep copy and materialize collections to fulfill that assumption so that collection elements will delete 590 // properly 591 592 // TODO: maybe rewriting PurapService.calculateItemTax could be rewritten so that the a deep copy doesn't need to be 593 // made 594 // by taking advantage of OJB's managed array lists 595 try { 596 ObjectUtils.materializeUpdateableCollections(creditMemoDoc); 597 for (OleCreditMemoItem item : (List<OleCreditMemoItem>) creditMemoDoc.getItems()) { 598 ObjectUtils.materializeUpdateableCollections(item); 599 } 600 } catch (Exception ex) { 601 throw new RuntimeException(ex); 602 } 603 creditMemoDoc = (OleVendorCreditMemoDocument) ObjectUtils.deepCopy(creditMemoDoc); 604 //purapService.updateStatus(doc, PaymentRequestStatuses.AUTO_APPROVED); 605 creditMemoDoc.updateAndSaveAppDocStatus(PurapConstants.CreditMemoStatuses.APPDOC_COMPLETE); 606 607 documentService.blanketApproveDocument(creditMemoDoc, "auto-approving: Total is below threshold.", null); 608 } catch (WorkflowException we) { 609 LOG.error("Exception encountered when approving document number " + creditMemoDoc.getDocumentNumber() + ".", we); 610 // throw a runtime exception up so that we can force a rollback 611 throw new RuntimeException("Exception encountered when approving document number " + creditMemoDoc.getDocumentNumber() + ".", we); 612 } 613 return true; 614 } 615}