Search in sources :

Example 11 with PurchaseOrderDocument

use of org.kuali.kfs.module.purap.document.PurchaseOrderDocument in project cu-kfs by CU-CommunityApps.

the class PaymentRequestItem method getPurchaseOrderItem.

/**
 * Retrieves a purchase order item by inspecting the item type to see if its above the line or below the line and returns the
 * appropriate type.
 *
 * @return - purchase order item
 */
@Override
public PurchaseOrderItem getPurchaseOrderItem() {
    if (ObjectUtils.isNotNull(this.getPurapDocumentIdentifier())) {
        if (ObjectUtils.isNull(this.getPaymentRequest())) {
            this.refreshReferenceObject(PurapPropertyConstants.PURAP_DOC);
        }
    }
    // update though)
    if (getPaymentRequest() != null) {
        PurchaseOrderDocument po = getPaymentRequest().getPurchaseOrderDocument();
        PurchaseOrderItem poi = null;
        if (this.getItemType().isLineItemIndicator()) {
            List items = po.getItems();
            if (items != null) {
                for (Object object : items) {
                    PurchaseOrderItem item = (PurchaseOrderItem) object;
                    if (item != null && item.getItemLineNumber().equals(this.getItemLineNumber())) {
                        poi = item;
                        break;
                    }
                }
            }
        } else {
            poi = (PurchaseOrderItem) SpringContext.getBean(PurapService.class).getBelowTheLineByType(po, this.getItemType());
        }
        if (poi != null) {
            return poi;
        } else {
            if (LOG.isDebugEnabled()) {
                LOG.debug("getPurchaseOrderItem() Returning null because PurchaseOrderItem object for line number" + getItemLineNumber() + "or itemType " + getItemTypeCode() + " is null");
            }
            return null;
        }
    } else {
        LOG.error("getPurchaseOrderItem() Returning null because paymentRequest object is null");
        throw new PurError("Payment Request Object in Purchase Order item line number " + getItemLineNumber() + "or itemType " + getItemTypeCode() + " is null");
    }
}
Also used : PurapService(org.kuali.kfs.module.purap.document.service.PurapService) PurchaseOrderDocument(org.kuali.kfs.module.purap.document.PurchaseOrderDocument) ArrayList(java.util.ArrayList) List(java.util.List) PurError(org.kuali.kfs.module.purap.exception.PurError)

Example 12 with PurchaseOrderDocument

use of org.kuali.kfs.module.purap.document.PurchaseOrderDocument in project cu-kfs by CU-CommunityApps.

the class CuBatchExtractServiceImpl method savePOLines.

/**
 * @see org.kuali.kfs.module.cam.batch.service.BatchExtractService#savePOLines(List, ExtractProcessLog)
 */
@Transactional
@Override
public HashSet<PurchasingAccountsPayableDocument> savePOLines(List<Entry> poLines, ExtractProcessLog processLog) {
    HashSet<PurchasingAccountsPayableDocument> purApDocuments = new HashSet<PurchasingAccountsPayableDocument>();
    // This is a list of pending GL entries created after last GL process and Cab Batch extract
    // PurAp Account Line history comes from PURAP module
    Collection<PurApAccountingLineBase> purapAcctLines = findPurapAccountRevisions();
    // Pass the records to reconciliation service method
    reconciliationService.reconcile(poLines, purapAcctLines);
    // for each valid GL entry there is a collection of valid PO Doc and Account Lines
    Collection<GlAccountLineGroup> matchedGroups = reconciliationService.getMatchedGroups();
    // Keep track of unique item lines
    HashMap<String, PurchasingAccountsPayableItemAsset> assetItems = new HashMap<String, PurchasingAccountsPayableItemAsset>();
    // Keep track of unique account lines
    HashMap<String, PurchasingAccountsPayableLineAssetAccount> assetAcctLines = new HashMap<String, PurchasingAccountsPayableLineAssetAccount>();
    // Keep track of asset lock
    HashMap<String, Object> assetLockMap = new HashMap<String, Object>();
    // Keep track of purchaseOrderDocument
    HashMap<Integer, PurchaseOrderDocument> poDocMap = new HashMap<Integer, PurchaseOrderDocument>();
    // KFSMI-7214, add document map for processing multiple items from the same AP doc
    HashMap<String, PurchasingAccountsPayableDocument> papdMap = new HashMap<String, PurchasingAccountsPayableDocument>();
    for (GlAccountLineGroup group : matchedGroups) {
        Entry entry = group.getTargetEntry();
        GeneralLedgerEntry generalLedgerEntry = new GeneralLedgerEntry(entry);
        GeneralLedgerEntry debitEntry = null;
        GeneralLedgerEntry creditEntry = null;
        KualiDecimal transactionLedgerEntryAmount = generalLedgerEntry.getTransactionLedgerEntryAmount();
        List<PurApAccountingLineBase> matchedPurApAcctLines = group.getMatchedPurApAcctLines();
        boolean hasPositiveAndNegative = hasPositiveAndNegative(matchedPurApAcctLines);
        boolean nonZero = ObjectUtils.isNotNull(transactionLedgerEntryAmount) && transactionLedgerEntryAmount.isNonZero();
        // generally for non-zero transaction ledger amount we should create a single GL entry with that amount,
        if (nonZero && !hasPositiveAndNegative) {
            businessObjectService.save(generalLedgerEntry);
        } else // but if there is FO revision or negative amount lines such as discount, create and save the set of debit(positive) and credit(negative) entries initialized with zero transaction amounts
        {
            debitEntry = createPositiveGlEntry(entry);
            businessObjectService.save(debitEntry);
            creditEntry = createNegativeGlEntry(entry);
            businessObjectService.save(creditEntry);
        }
        // KFSMI-7214, create an active document reference map
        boolean newApDoc = false;
        // KFSMI-7214, find from active document reference map first
        PurchasingAccountsPayableDocument cabPurapDoc = papdMap.get(entry.getDocumentNumber());
        if (ObjectUtils.isNull(cabPurapDoc)) {
            // find from DB
            cabPurapDoc = findPurchasingAccountsPayableDocument(entry);
        }
        // if document is found already, update the active flag
        if (ObjectUtils.isNull(cabPurapDoc)) {
            cabPurapDoc = createPurchasingAccountsPayableDocument(entry);
            newApDoc = true;
        }
        if (cabPurapDoc != null) {
            // KFSMI-7214, add to the cached document map
            papdMap.put(entry.getDocumentNumber(), cabPurapDoc);
            // we only deal with PREQ or CM, so isPREQ = !isCM, isCM = !PREQ
            boolean isPREQ = CamsConstants.PREQ.equals(entry.getFinancialDocumentTypeCode());
            boolean hasRevisionWithMixedLines = isPREQ && hasRevisionWithMixedLines(matchedPurApAcctLines);
            for (PurApAccountingLineBase purApAccountingLine : matchedPurApAcctLines) {
                // KFSMI-7214,tracking down changes on CAB item.
                boolean newAssetItem = false;
                PurApItem purapItem = purApAccountingLine.getPurapItem();
                String itemAssetKey = cabPurapDoc.getDocumentNumber() + "-" + purapItem.getItemIdentifier();
                // KFSMI-7214, search CAB item from active object reference map first
                PurchasingAccountsPayableItemAsset itemAsset = assetItems.get(itemAssetKey);
                if (ObjectUtils.isNull(itemAsset)) {
                    itemAsset = findMatchingPurapAssetItem(cabPurapDoc, purapItem);
                }
                // if new item, create and add to the list
                if (ObjectUtils.isNull(itemAsset)) {
                    itemAsset = createPurchasingAccountsPayableItemAsset(cabPurapDoc, purapItem);
                    cabPurapDoc.getPurchasingAccountsPayableItemAssets().add(itemAsset);
                    newAssetItem = true;
                }
                assetItems.put(itemAssetKey, itemAsset);
                Long generalLedgerAccountIdentifier = generalLedgerEntry.getGeneralLedgerAccountIdentifier();
                KualiDecimal purapAmount = purApAccountingLine.getAmount();
                // note that PurAp Doc accounting lines won't have zero amount, so !isPositive = isNegative
                boolean isPositive = purapAmount.isPositive();
                // trade-in and discount items on PREQ usually have negative amount (unless it's a revision)
                boolean usuallyNegative = isItemTypeUsuallyOfNegativeAmount(purapItem.getItemTypeCode());
                // decide if current accounting line should be consolidated into debit or credit entry based on the above criteria
                boolean isDebitEntry = hasRevisionWithMixedLines ? // case 2.2
                (usuallyNegative ? !isPositive : isPositive) : // case 1.1/1.2/2.1
                (isPREQ ? isPositive : !isPositive);
                GeneralLedgerEntry currentEntry = isDebitEntry ? debitEntry : creditEntry;
                if (ObjectUtils.isNull(generalLedgerAccountIdentifier)) {
                    generalLedgerAccountIdentifier = currentEntry.getGeneralLedgerAccountIdentifier();
                }
                String acctLineKey = cabPurapDoc.getDocumentNumber() + "-" + itemAsset.getAccountsPayableLineItemIdentifier() + "-" + itemAsset.getCapitalAssetBuilderLineNumber() + "-" + generalLedgerAccountIdentifier;
                PurchasingAccountsPayableLineAssetAccount assetAccount = assetAcctLines.get(acctLineKey);
                if (ObjectUtils.isNull(assetAccount) && nonZero && !hasPositiveAndNegative) {
                    // if new unique account line within GL, then create a new account line
                    assetAccount = createPurchasingAccountsPayableLineAssetAccount(generalLedgerEntry, cabPurapDoc, purApAccountingLine, itemAsset);
                    assetAcctLines.put(acctLineKey, assetAccount);
                    itemAsset.getPurchasingAccountsPayableLineAssetAccounts().add(assetAccount);
                } else if (!nonZero || hasPositiveAndNegative) {
                    // if amount is zero, means canceled doc, then create a copy and retain the account line
                    /*
                         * KFSMI-9760 / KFSCNTRB-???(FSKD-5097)
                         * 1.   Usually, we consolidate matched accounting lines (for the same account) based on positive/negative amount, i.e.
                         * 1.1  For PREQ, positive -> debit, negative -> credit;
                         *      That means charges (positive amount) are debit, trade-ins/discounts (negative amount) are credit.
                         * 1.2. For CM, the opposite, positive -> credit, negative -> debit
                         *      That means payments (positive amount) are credit, Less Restocking Fees (negative amount) are debit.
                         * 2.   However when there is a FO revision on PREQ (CMs don't have revisions), it's more complicated:
                         * 2.1  If the matched accounting lines are either all for non trade-in/discount items, or all for trade-in/discount items,
                         *      then we still could base the debit/credit on positive/negative amount;
                         *      That means reverse of charges (negative amount) are credit, reverse of trade-ins/discounts (positive amount) are debit.
                         * 2.2  Otherwise, i.e. the matched accounting lines cover both non trade-in/discount items and trade-in/discount items,
                         *      In this case we prefer to consolidate based on revision,
                         *      that means the original charges and trade-in/discounts are combined together,
                         *      while the reversed charges and trade-in/discounts are combined together;
                         *      So: original charge + original trade-in/discount -> debit, reversed charge + reversed trade-in/discount -> credit
                         * 3.   On top of these, we ensure that the final capital asset GL entries created is a debit if the consolidated amount is positive, and vice versa.
                         *      Note: In general, the consolidated amount for debit entry should already be positive, and vice versa. But there could be special cases,
                         *      for ex, in the case of 2.2, if the revision is only on discount, then the credit entry for the reverse would come out as positive, so we need
                         *      to swap it into a debit entry. This means, we will have 2 debit entries, one for the original lines, the other for the reversed discount line.
                         */
                    // during calculation, regard D/C code as a +/- sign in front of the amount
                    KualiDecimal oldAmount = currentEntry.getTransactionLedgerEntryAmount();
                    oldAmount = isDebitEntry ? oldAmount : oldAmount.negated();
                    KualiDecimal newAmount = oldAmount.add(purapAmount);
                    newAmount = isDebitEntry ? newAmount : newAmount.negated();
                    currentEntry.setTransactionLedgerEntryAmount(newAmount);
                    if (ObjectUtils.isNotNull(assetAccount)) {
                        // if account line key matches within same GL Entry, combine the amount
                        assetAccount.setItemAccountTotalAmount(assetAccount.getItemAccountTotalAmount().add(purApAccountingLine.getAmount()));
                    } else {
                        assetAccount = createPurchasingAccountsPayableLineAssetAccount(currentEntry, cabPurapDoc, purApAccountingLine, itemAsset);
                        assetAcctLines.put(acctLineKey, assetAccount);
                        itemAsset.getPurchasingAccountsPayableLineAssetAccounts().add(assetAccount);
                    }
                } else if (ObjectUtils.isNotNull(assetAccount)) {
                    // if account line key matches within same GL Entry, combine the amount
                    assetAccount.setItemAccountTotalAmount(assetAccount.getItemAccountTotalAmount().add(purApAccountingLine.getAmount()));
                }
                // KFSMI-7214: fixed OJB auto-update object issue.
                if (!newAssetItem) {
                    businessObjectService.save(itemAsset);
                }
                businessObjectService.save(cabPurapDoc);
                // Add to the asset lock table if purap has asset number information
                addAssetLocks(assetLockMap, cabPurapDoc, purapItem, itemAsset.getAccountsPayableLineItemIdentifier(), poDocMap);
            }
            // since the real amount being positive/negative shall be solely indicated by the D/C code.
            if (debitEntry != null) {
                KualiDecimal amount = debitEntry.getTransactionLedgerEntryAmount();
                if (amount.isNegative()) {
                    debitEntry.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
                    debitEntry.setTransactionLedgerEntryAmount(amount.negated());
                }
                businessObjectService.save(debitEntry);
            }
            if (creditEntry != null) {
                KualiDecimal amount = creditEntry.getTransactionLedgerEntryAmount();
                if (amount.isNegative()) {
                    creditEntry.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
                    creditEntry.setTransactionLedgerEntryAmount(amount.negated());
                }
                businessObjectService.save(creditEntry);
            }
            // batch.
            if (newApDoc) {
                purApDocuments.add(cabPurapDoc);
            }
        } else {
            LOG.error("Could not create a valid PurchasingAccountsPayableDocument object for document number " + entry.getDocumentNumber());
        }
    }
    updateProcessLog(processLog, reconciliationService);
    return purApDocuments;
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) GeneralLedgerEntry(org.kuali.kfs.module.cam.businessobject.GeneralLedgerEntry) GlAccountLineGroup(org.kuali.kfs.module.cam.businessobject.GlAccountLineGroup) PurchasingAccountsPayableItemAsset(org.kuali.kfs.module.cam.businessobject.PurchasingAccountsPayableItemAsset) Entry(org.kuali.kfs.gl.businessobject.Entry) GeneralLedgerEntry(org.kuali.kfs.module.cam.businessobject.GeneralLedgerEntry) PurchaseOrderDocument(org.kuali.kfs.module.purap.document.PurchaseOrderDocument) KualiDecimal(org.kuali.rice.core.api.util.type.KualiDecimal) HashSet(java.util.HashSet) PurApItem(org.kuali.kfs.module.purap.businessobject.PurApItem) PurApAccountingLineBase(org.kuali.kfs.module.purap.businessobject.PurApAccountingLineBase) PurchasingAccountsPayableLineAssetAccount(org.kuali.kfs.module.cam.businessobject.PurchasingAccountsPayableLineAssetAccount) PurchasingAccountsPayableDocument(org.kuali.kfs.module.cam.businessobject.PurchasingAccountsPayableDocument) Transactional(org.springframework.transaction.annotation.Transactional)

Example 13 with PurchaseOrderDocument

use of org.kuali.kfs.module.purap.document.PurchaseOrderDocument in project cu-kfs by CU-CommunityApps.

the class CuPendingTransactionServiceImpl method generateCreditMemoReversalEntries.

/**
 * Generates the reversal entries for the given input VendorCreditMemoDocument.
 *
 * @param doc
 *            the VendorCreditMemoDocument for which we generate the reversal entries
 * @param sequenceHelper
 */
protected void generateCreditMemoReversalEntries(VendorCreditMemoDocument cm) {
    cm.setGeneralLedgerPendingEntries(new ArrayList());
    boolean success = true;
    GeneralLedgerPendingEntrySequenceHelper sequenceHelper = new GeneralLedgerPendingEntrySequenceHelper(getNextAvailableSequence(cm.getDocumentNumber()));
    if (!cm.isSourceVendor()) {
        LOG.debug("generateEntriesCreditMemo() create encumbrance entries for CM against a PO or PREQ (not vendor)");
        PurchaseOrderDocument po = null;
        if (cm.isSourceDocumentPurchaseOrder()) {
            LOG.debug("generateEntriesCreditMemo() PO type");
            po = SpringContext.getBean(PurchaseOrderService.class).getCurrentPurchaseOrder(cm.getPurchaseOrderIdentifier());
        } else if (cm.isSourceDocumentPaymentRequest()) {
            LOG.debug("generateEntriesCreditMemo() PREQ type");
            po = SpringContext.getBean(PurchaseOrderService.class).getCurrentPurchaseOrder(cm.getPaymentRequestDocument().getPurchaseOrderIdentifier());
        }
        // for CM cancel or create, do not book encumbrances if PO is CLOSED, but do update the amounts on the PO
        List encumbrances = getCreditMemoEncumbrance(cm, po);
        if (!(PurapConstants.PurchaseOrderStatuses.APPDOC_CLOSED.equals(po.getApplicationDocumentStatus()))) {
            if (encumbrances != null) {
                cm.setGenerateEncumbranceEntries(true);
                // even if generating encumbrance entries on cancel, call is the same because the method gets negative amounts
                // from
                // the map so Debits on negatives = a credit
                cm.setDebitCreditCodeForGLEntries(GL_DEBIT_CODE);
                for (Iterator iter = encumbrances.iterator(); iter.hasNext(); ) {
                    AccountingLine accountingLine = (AccountingLine) iter.next();
                    if (accountingLine.getAmount().compareTo(ZERO) != 0) {
                        cm.generateGeneralLedgerPendingEntries(accountingLine, sequenceHelper);
                        // increment for the next line
                        sequenceHelper.increment();
                    }
                }
            }
        }
    }
    List<SummaryAccount> summaryAccounts = SpringContext.getBean(PurapAccountingService.class).generateSummaryAccountsWithNoZeroTotalsNoUseTax(cm);
    if (summaryAccounts != null) {
        LOG.debug("generateEntriesCreditMemo() now book the actuals");
        cm.setGenerateEncumbranceEntries(false);
        for (Iterator iter = summaryAccounts.iterator(); iter.hasNext(); ) {
            SummaryAccount summaryAccount = (SummaryAccount) iter.next();
            cm.generateGeneralLedgerPendingEntries(summaryAccount.getAccount(), sequenceHelper);
            // increment for the next line
            sequenceHelper.increment();
        }
        // generate offset accounts for use tax if it exists (useTaxContainers will be empty if not a use tax document)
        List<UseTaxContainer> useTaxContainers = SpringContext.getBean(PurapAccountingService.class).generateUseTaxAccount(cm);
        for (UseTaxContainer useTaxContainer : useTaxContainers) {
            PurApItemUseTax offset = useTaxContainer.getUseTax();
            List<SourceAccountingLine> accounts = useTaxContainer.getAccounts();
            for (SourceAccountingLine sourceAccountingLine : accounts) {
                cm.generateGeneralLedgerPendingEntries(sourceAccountingLine, sequenceHelper, useTaxContainer.getUseTax());
                // increment for the next line
                sequenceHelper.increment();
            }
        }
        // manually save cm account change tables (CAMS needs this)
        SpringContext.getBean(PurapAccountRevisionService.class).cancelCreditMemoAccountRevisions(cm.getItems(), cm.getPostingYearFromPendingGLEntries(), cm.getPostingPeriodCodeFromPendingGLEntries());
    }
    businessObjectService.save(cm.getGeneralLedgerPendingEntries());
}
Also used : SourceAccountingLine(org.kuali.kfs.sys.businessobject.SourceAccountingLine) AccountingLine(org.kuali.kfs.sys.businessobject.AccountingLine) UseTaxContainer(org.kuali.kfs.module.purap.util.UseTaxContainer) PurApItemUseTax(org.kuali.kfs.module.purap.businessobject.PurApItemUseTax) PurchaseOrderService(org.kuali.kfs.module.purap.document.service.PurchaseOrderService) ArrayList(java.util.ArrayList) SourceAccountingLine(org.kuali.kfs.sys.businessobject.SourceAccountingLine) PurapAccountingService(org.kuali.kfs.module.purap.service.PurapAccountingService) GeneralLedgerPendingEntrySequenceHelper(org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper) PurapAccountRevisionService(org.kuali.kfs.module.purap.service.PurapAccountRevisionService) SummaryAccount(org.kuali.kfs.module.purap.util.SummaryAccount) PurchaseOrderDocument(org.kuali.kfs.module.purap.document.PurchaseOrderDocument) Iterator(java.util.Iterator) List(java.util.List) ArrayList(java.util.ArrayList)

Example 14 with PurchaseOrderDocument

use of org.kuali.kfs.module.purap.document.PurchaseOrderDocument in project cu-kfs by CU-CommunityApps.

the class CuPendingTransactionServiceImpl method reencumberEncumbrance.

/**
 * Re-encumber the Encumbrance on a PO based on values in a PREQ. This is used when a PREQ is cancelled. Note: This modifies the
 * encumbrance values on the PO and saves the PO
 *
 * @param preq PREQ for invoice
 * @return List of accounting lines to use to create the pending general ledger entries
 */
protected List<SourceAccountingLine> reencumberEncumbrance(PaymentRequestDocument preq) {
    LOG.debug("reencumberEncumbrance() started");
    PurchaseOrderDocument po = SpringContext.getBean(PurchaseOrderService.class).getCurrentPurchaseOrder(preq.getPurchaseOrderIdentifier());
    Map encumbranceAccountMap = new HashMap();
    // Get each item one by one
    for (Iterator items = preq.getItems().iterator(); items.hasNext(); ) {
        PaymentRequestItem payRequestItem = (PaymentRequestItem) items.next();
        PurchaseOrderItem poItem = getPoItem(po, payRequestItem.getItemLineNumber(), payRequestItem.getItemType());
        // Amount to reencumber for this item
        KualiDecimal itemReEncumber = null;
        String logItmNbr = "Item # " + payRequestItem.getItemLineNumber();
        LOG.debug("reencumberEncumbrance() " + logItmNbr);
        // If there isn't a PO item or the total amount is 0, we don't need encumbrances
        final KualiDecimal preqItemTotalAmount = (payRequestItem.getTotalAmount() == null) ? KualiDecimal.ZERO : payRequestItem.getTotalAmount();
        if ((poItem == null) || (preqItemTotalAmount.doubleValue() == 0)) {
            LOG.debug("reencumberEncumbrance() " + logItmNbr + " No encumbrances required");
        } else {
            LOG.debug("reencumberEncumbrance() " + logItmNbr + " Calculate encumbrance GL entries");
            // Do we calculate the encumbrance amount based on quantity or amount?
            if (poItem.getItemType().isQuantityBasedGeneralLedgerIndicator()) {
                LOG.debug("reencumberEncumbrance() " + logItmNbr + " Calculate encumbrance based on quantity");
                // Do disencumbrance calculations based on quantity
                KualiDecimal preqQuantity = payRequestItem.getItemQuantity() == null ? ZERO : payRequestItem.getItemQuantity();
                KualiDecimal outstandingEncumberedQuantity = poItem.getItemOutstandingEncumberedQuantity() == null ? ZERO : poItem.getItemOutstandingEncumberedQuantity();
                KualiDecimal invoicedTotal = poItem.getItemInvoicedTotalQuantity() == null ? ZERO : poItem.getItemInvoicedTotalQuantity();
                poItem.setItemInvoicedTotalQuantity(invoicedTotal.subtract(preqQuantity));
                poItem.setItemOutstandingEncumberedQuantity(outstandingEncumberedQuantity.add(preqQuantity));
                itemReEncumber = preqQuantity.multiply(new KualiDecimal(poItem.getItemUnitPrice()));
                // add tax for encumbrance
                KualiDecimal itemTaxAmount = poItem.getItemTaxAmount() == null ? ZERO : poItem.getItemTaxAmount();
                KualiDecimal encumbranceTaxAmount = preqQuantity.divide(poItem.getItemQuantity()).multiply(itemTaxAmount);
                itemReEncumber = itemReEncumber.add(encumbranceTaxAmount);
            } else {
                LOG.debug("reencumberEncumbrance() " + logItmNbr + " Calculate encumbrance based on amount");
                itemReEncumber = preqItemTotalAmount;
                // this prevents negative encumbrance
                if ((poItem.getTotalAmount() != null) && (poItem.getTotalAmount().bigDecimalValue().signum() < 0)) {
                    // po item extended cost is negative
                    if ((poItem.getTotalAmount().compareTo(itemReEncumber)) > 0) {
                        itemReEncumber = poItem.getTotalAmount();
                    }
                } else if ((poItem.getTotalAmount() != null) && (poItem.getTotalAmount().bigDecimalValue().signum() >= 0)) {
                    // po item extended cost is positive
                    if ((poItem.getTotalAmount().compareTo(itemReEncumber)) < 0) {
                        itemReEncumber = poItem.getTotalAmount();
                    }
                }
            }
            LOG.debug("reencumberEncumbrance() " + logItmNbr + " Amount to reencumber: " + itemReEncumber);
            KualiDecimal outstandingEncumberedAmount = poItem.getItemOutstandingEncumberedAmount() == null ? ZERO : poItem.getItemOutstandingEncumberedAmount();
            LOG.debug("reencumberEncumbrance() " + logItmNbr + " PO Item Outstanding Encumbrance Amount set to: " + outstandingEncumberedAmount);
            KualiDecimal newOutstandingEncumberedAmount = outstandingEncumberedAmount.add(itemReEncumber);
            LOG.debug("reencumberEncumbrance() " + logItmNbr + " New PO Item Outstanding Encumbrance Amount to set: " + newOutstandingEncumberedAmount);
            poItem.setItemOutstandingEncumberedAmount(newOutstandingEncumberedAmount);
            KualiDecimal invoicedTotalAmount = poItem.getItemInvoicedTotalAmount() == null ? ZERO : poItem.getItemInvoicedTotalAmount();
            LOG.debug("reencumberEncumbrance() " + logItmNbr + " PO Item Invoiced Total Amount set to: " + invoicedTotalAmount);
            KualiDecimal newInvoicedTotalAmount = invoicedTotalAmount.subtract(preqItemTotalAmount);
            LOG.debug("reencumberEncumbrance() " + logItmNbr + " New PO Item Invoiced Total Amount to set: " + newInvoicedTotalAmount);
            poItem.setItemInvoicedTotalAmount(newInvoicedTotalAmount);
            // make the list of accounts for the reencumbrance entry
            PurchaseOrderAccount lastAccount = null;
            KualiDecimal accountTotal = ZERO;
            // Sort accounts
            Collections.sort((List) poItem.getSourceAccountingLines());
            for (Iterator accountIter = poItem.getSourceAccountingLines().iterator(); accountIter.hasNext(); ) {
                PurchaseOrderAccount account = (PurchaseOrderAccount) accountIter.next();
                if (!account.isEmpty()) {
                    SourceAccountingLine acctString = account.generateSourceAccountingLine();
                    // amount = item reencumber * account percent / 100
                    KualiDecimal reencumbranceAmount = itemReEncumber.multiply(new KualiDecimal(account.getAccountLinePercent().toString())).divide(HUNDRED);
                    account.setItemAccountOutstandingEncumbranceAmount(account.getItemAccountOutstandingEncumbranceAmount().add(reencumbranceAmount));
                    // For rounding check at the end
                    accountTotal = accountTotal.add(reencumbranceAmount);
                    lastAccount = account;
                    LOG.debug("reencumberEncumbrance() " + logItmNbr + " " + acctString + " = " + reencumbranceAmount);
                    if (encumbranceAccountMap.containsKey(acctString)) {
                        KualiDecimal currentAmount = (KualiDecimal) encumbranceAccountMap.get(acctString);
                        encumbranceAccountMap.put(acctString, reencumbranceAmount.add(currentAmount));
                    } else {
                        encumbranceAccountMap.put(acctString, reencumbranceAmount);
                    }
                }
            }
            // account for rounding by adjusting last account as needed
            if (lastAccount != null) {
                KualiDecimal difference = itemReEncumber.subtract(accountTotal);
                LOG.debug("reencumberEncumbrance() difference: " + logItmNbr + " " + difference);
                SourceAccountingLine acctString = lastAccount.generateSourceAccountingLine();
                KualiDecimal amount = (KualiDecimal) encumbranceAccountMap.get(acctString);
                if (amount == null) {
                    encumbranceAccountMap.put(acctString, difference);
                } else {
                    encumbranceAccountMap.put(acctString, amount.add(difference));
                }
                lastAccount.setItemAccountOutstandingEncumbranceAmount(lastAccount.getItemAccountOutstandingEncumbranceAmount().add(difference));
            }
        }
    }
    List<SourceAccountingLine> encumbranceAccounts = new ArrayList<SourceAccountingLine>();
    for (Iterator<SourceAccountingLine> iter = encumbranceAccountMap.keySet().iterator(); iter.hasNext(); ) {
        SourceAccountingLine acctString = (SourceAccountingLine) iter.next();
        KualiDecimal amount = (KualiDecimal) encumbranceAccountMap.get(acctString);
        if (amount.doubleValue() != 0) {
            acctString.setAmount(amount);
            encumbranceAccounts.add(acctString);
        }
    }
    return encumbranceAccounts;
}
Also used : PurchaseOrderService(org.kuali.kfs.module.purap.document.service.PurchaseOrderService) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) SourceAccountingLine(org.kuali.kfs.sys.businessobject.SourceAccountingLine) PurchaseOrderItem(org.kuali.kfs.module.purap.businessobject.PurchaseOrderItem) PaymentRequestItem(org.kuali.kfs.module.purap.businessobject.PaymentRequestItem) PurchaseOrderDocument(org.kuali.kfs.module.purap.document.PurchaseOrderDocument) Iterator(java.util.Iterator) KualiDecimal(org.kuali.rice.core.api.util.type.KualiDecimal) Map(java.util.Map) HashMap(java.util.HashMap) PurchaseOrderAccount(org.kuali.kfs.module.purap.businessobject.PurchaseOrderAccount)

Example 15 with PurchaseOrderDocument

use of org.kuali.kfs.module.purap.document.PurchaseOrderDocument in project cu-kfs by CU-CommunityApps.

the class CuB2BPurchaseOrderSciquestServiceImplTest method testVerifyCxmlPOData_InValid.

public void testVerifyCxmlPOData_InValid() throws Exception {
    String errors = KFSConstants.EMPTY_STRING;
    PurchaseOrderDocument po = PurchaseOrderFixture.PO_B2B_CXML_VALIDATION_INVALID.createPurchaseOrderdDocument(documentService);
    po.setDeliveryPostalCode(null);
    po.setDeliveryStateCode(null);
    errors = b2bPurchaseOrderService.verifyCxmlPOData(po, UserNameFixture.ccs1.getPerson().getPrincipalId(), cuB2BPurchaseOrderSciquestServiceImpl.getB2bPurchaseOrderPassword(), po.getVendorContract().getContractManager(), cuB2BPurchaseOrderSciquestServiceImpl.getContractManagerEmail(po.getVendorContract().getContractManager()), po.getVendorDetail().getVendorDunsNumber());
    assertFalse(errors.isEmpty());
}
Also used : PurchaseOrderDocument(org.kuali.kfs.module.purap.document.PurchaseOrderDocument)

Aggregations

PurchaseOrderDocument (org.kuali.kfs.module.purap.document.PurchaseOrderDocument)52 CuPaymentRequestDocument (edu.cornell.kfs.module.purap.document.CuPaymentRequestDocument)17 DocumentService (org.kuali.kfs.krad.service.DocumentService)16 PaymentRequestDocument (org.kuali.kfs.module.purap.document.PaymentRequestDocument)14 KualiDecimal (org.kuali.rice.core.api.util.type.KualiDecimal)12 PaymentRequestItem (org.kuali.kfs.module.purap.businessobject.PaymentRequestItem)9 ArrayList (java.util.ArrayList)6 PurchaseOrderItem (org.kuali.kfs.module.purap.businessobject.PurchaseOrderItem)6 RequisitionDocument (org.kuali.kfs.module.purap.document.RequisitionDocument)5 PurchaseOrderService (org.kuali.kfs.module.purap.document.service.PurchaseOrderService)5 HashMap (java.util.HashMap)4 List (java.util.List)4 Map (java.util.Map)4 BusinessObjectService (org.kuali.kfs.krad.service.BusinessObjectService)4 MessageMap (org.kuali.kfs.krad.util.MessageMap)4 PurchaseOrderAmendmentDocument (org.kuali.kfs.module.purap.document.PurchaseOrderAmendmentDocument)4 PurapService (org.kuali.kfs.module.purap.document.service.PurapService)4 File (java.io.File)3 BigDecimal (java.math.BigDecimal)3 Iterator (java.util.Iterator)3