Search in sources :

Example 51 with KualiDecimal

use of org.kuali.rice.core.api.util.type.KualiDecimal in project cu-kfs by CU-CommunityApps.

the class CuRequisitionServiceImpl method checkAutomaticPurchaseOrderRules.

/**
 * Checks the rule for Automatic Purchase Order eligibility of the requisition and return a String containing the reason why the
 * requisition was not eligible to become an APO if it was not eligible, or return an empty String if the requisition is
 * eligible to become an APO
 *
 * @param requisition the requisition document to be checked for APO eligibility.
 * @return String containing the reason why the requisition was not eligible to become an APO if it was not eligible, or an
 *         empty String if the requisition is eligible to become an APO.
 */
protected String checkAutomaticPurchaseOrderRules(RequisitionDocument requisition) {
    String requisitionSource = requisition.getRequisitionSourceCode();
    KualiDecimal reqTotal = requisition.getTotalDollarAmount();
    KualiDecimal apoLimit = purapService.getApoLimit(requisition.getVendorContractGeneratedIdentifier(), requisition.getChartOfAccountsCode(), requisition.getOrganizationCode());
    requisition.setOrganizationAutomaticPurchaseOrderLimit(apoLimit);
    if (LOG.isDebugEnabled()) {
        LOG.debug("isAPO() reqId = " + requisition.getPurapDocumentIdentifier() + "; apoLimit = " + apoLimit + "; reqTotal = " + reqTotal);
    }
    if (apoLimit == null) {
        return "APO limit is empty.";
    } else {
        if (reqTotal.compareTo(apoLimit) == 1) {
            return "Requisition total is greater than the APO limit.";
        }
    }
    if (reqTotal.compareTo(KualiDecimal.ZERO) <= 0) {
        return "Requisition total is not greater than zero.";
    }
    if (LOG.isDebugEnabled()) {
        LOG.debug("isAPO() vendor #" + requisition.getVendorHeaderGeneratedIdentifier() + "-" + requisition.getVendorDetailAssignedIdentifier());
    }
    if (requisition.getVendorHeaderGeneratedIdentifier() == null || requisition.getVendorDetailAssignedIdentifier() == null) {
        return "Vendor was not selected from the vendor database.";
    } else {
        VendorDetail vendorDetail = vendorService.getVendorDetail(requisition.getVendorHeaderGeneratedIdentifier(), requisition.getVendorDetailAssignedIdentifier());
        if (vendorDetail == null) {
            return "Error retrieving vendor from the database.";
        }
        if (StringUtils.isBlank(requisition.getVendorLine1Address()) || StringUtils.isBlank(requisition.getVendorCityName()) || StringUtils.isBlank(requisition.getVendorCountryCode())) {
            return "Requisition does not have all of the vendor address fields that are required for Purchase Order.";
        }
        requisition.setVendorRestrictedIndicator(vendorDetail.getVendorRestrictedIndicator());
        if (requisition.getVendorRestrictedIndicator() != null && requisition.getVendorRestrictedIndicator()) {
            return "Selected vendor is marked as restricted.";
        }
        if (vendorDetail.isVendorDebarred()) {
            return "Selected vendor is marked as a debarred vendor";
        }
        requisition.setVendorDetail(vendorDetail);
        if ((!PurapConstants.RequisitionSources.B2B.equals(requisitionSource)) && ObjectUtils.isNull(requisition.getVendorContractGeneratedIdentifier())) {
            Person initiator = getPersonService().getPerson(requisition.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId());
            VendorContract b2bContract = vendorService.getVendorB2BContract(vendorDetail, initiator.getCampusCode());
            if (b2bContract != null) {
                return "Standard requisition with no contract selected but a B2B contract exists for the selected vendor.";
            }
        }
        // if the vendor is selected through vendor contract is selected
        if (StringUtils.isNotBlank(requisition.getVendorContractName())) {
            boolean routeToCM = parameterService.getParameterValueAsBoolean(RequisitionDocument.class, CUPurapParameterConstants.ROUTE_REQS_WITH_EXPIRED_CONTRACT_TO_CM, Boolean.FALSE);
            if (routeToCM && vendorService.isVendorContractExpired(requisition, requisition.getVendorContractGeneratedIdentifier(), vendorDetail)) {
                return "Contracted Vendor used where the contract end date is expired.";
            }
        }
    }
    // if vendor address isn't complete, no APO
    if (StringUtils.isBlank(requisition.getVendorLine1Address()) || StringUtils.isBlank(requisition.getVendorCityName()) || StringUtils.isBlank(requisition.getVendorCountryCode()) || !postalCodeValidationService.validateAddress(requisition.getVendorCountryCode(), requisition.getVendorStateCode(), requisition.getVendorPostalCode(), "", "")) {
        return "Requistion does not contain a complete vendor address";
    }
    // These are needed for commodity codes. They are put in here so that
    // we don't have to loop through items too many times.
    String purchaseOrderRequiresCommodityCode = parameterService.getParameterValueAsString(PurchaseOrderDocument.class, PurapRuleConstants.ITEMS_REQUIRE_COMMODITY_CODE_IND);
    boolean commodityCodeRequired = purchaseOrderRequiresCommodityCode.equals("Y");
    for (Iterator iter = requisition.getItems().iterator(); iter.hasNext(); ) {
        RequisitionItem item = (RequisitionItem) iter.next();
        if (item.isItemRestrictedIndicator()) {
            return "Requisition contains an item that is marked as restricted.";
        }
        // We only need to check the commodity codes if this is an above the line item.
        if (item.getItemType().isLineItemIndicator()) {
            String commodityCodesReason = "";
            List<VendorCommodityCode> vendorCommodityCodes = commodityCodeRequired ? requisition.getVendorDetail().getVendorCommodities() : null;
            commodityCodesReason = checkAPORulesPerItemForCommodityCodes(item, vendorCommodityCodes, commodityCodeRequired);
            if (StringUtils.isNotBlank(commodityCodesReason)) {
                return commodityCodesReason;
            }
        }
        if (PurapConstants.ItemTypeCodes.ITEM_TYPE_ORDER_DISCOUNT_CODE.equals(item.getItemType().getItemTypeCode()) || PurapConstants.ItemTypeCodes.ITEM_TYPE_TRADE_IN_CODE.equals(item.getItemType().getItemTypeCode())) {
            if ((item.getItemUnitPrice() != null) && ((BigDecimal.ZERO.compareTo(item.getItemUnitPrice())) != 0)) {
                // discount or trade-in item has unit price that is not empty or zero
                return "Requisition contains a " + item.getItemType().getItemTypeDescription() + " item, so it does not qualify as an APO.";
            }
        }
    }
    if (StringUtils.isNotEmpty(requisition.getRecurringPaymentTypeCode())) {
        return "Payment type is marked as recurring.";
    }
    if ((requisition.getPurchaseOrderTotalLimit() != null) && (KualiDecimal.ZERO.compareTo(requisition.getPurchaseOrderTotalLimit()) != 0)) {
        LOG.debug("isAPO() po total limit is not null and not equal to zero; return false.");
        return "The 'PO not to exceed' amount has been entered.";
    }
    if (StringUtils.isNotEmpty(requisition.getAlternate1VendorName()) || StringUtils.isNotEmpty(requisition.getAlternate2VendorName()) || StringUtils.isNotEmpty(requisition.getAlternate3VendorName()) || StringUtils.isNotEmpty(requisition.getAlternate4VendorName()) || StringUtils.isNotEmpty(requisition.getAlternate5VendorName())) {
        LOG.debug("isAPO() alternate vendor name exists; return false.");
        return "Requisition contains additional suggested vendor names.";
    }
    if (requisition.isPostingYearNext() && !purapService.isTodayWithinApoAllowedRange()) {
        return "Requisition is set to encumber next fiscal year and approval is not within APO allowed date range.";
    }
    return "";
}
Also used : VendorDetail(org.kuali.kfs.vnd.businessobject.VendorDetail) RequisitionItem(org.kuali.kfs.module.purap.businessobject.RequisitionItem) VendorContract(org.kuali.kfs.vnd.businessobject.VendorContract) Iterator(java.util.Iterator) KualiDecimal(org.kuali.rice.core.api.util.type.KualiDecimal) Person(org.kuali.rice.kim.api.identity.Person) VendorCommodityCode(org.kuali.kfs.vnd.businessobject.VendorCommodityCode)

Example 52 with KualiDecimal

use of org.kuali.rice.core.api.util.type.KualiDecimal in project cu-kfs by CU-CommunityApps.

the class CuElectronicInvoiceHelperServiceImpl method checkQtyInvItemForNoQtyOrder.

// KFSPTS-1719 : this is for the first matched the polineitem#
private void checkQtyInvItemForNoQtyOrder(PaymentRequestDocument preqDocument, ElectronicInvoiceOrderHolder orderHolder) {
    List<PaymentRequestItem> preqItems = preqDocument.getItems();
    // non qty not in invoice yet
    List<PaymentRequestItem> nonInvItems = new ArrayList<PaymentRequestItem>();
    for (PaymentRequestItem preqItem : preqItems) {
        // This is to check the first item that matched to po line and convert to qty if inv is qty po is non-qty
        if (StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_SERVICE_CODE, preqItem.getItemTypeCode())) {
            if ((((CuPaymentRequestItemExtension) preqItem.getExtension()).getInvLineNumber() == null && ((CuElectronicInvoiceOrderHolder) orderHolder).getMisMatchItem() == null)) {
                ElectronicInvoiceItemHolder itemHolder = orderHolder.getItemByLineNumber(preqItem.getItemLineNumber());
                if (itemHolder != null) {
                    // if the poitem is not in invoice, then skip this
                    preqItem.setItemCatalogNumber(itemHolder.getCatalogNumberStripped());
                    // even if inv is non qty still set up these values.
                    // if (itemHolder.getInvoiceItemQuantity() != null &&
                    // (new
                    // KualiDecimal(itemHolder.getInvoiceItemQuantity())).isPositive())
                    // {
                    preqItem.setItemQuantity(new KualiDecimal(itemHolder.getInvoiceItemQuantity()));
                    preqItem.setItemUnitOfMeasureCode(itemHolder.getInvoiceItemUnitOfMeasureCode());
                    // don't set unit price for nonqty and see what happened
                    if (itemHolder.getInvoiceItemQuantity() != null && (new KualiDecimal(itemHolder.getInvoiceItemQuantity())).isPositive()) {
                        preqItem.setItemUnitPrice(itemHolder.getInvoiceItemUnitPrice());
                    }
                    preqItem.setPurchaseOrderItemUnitPrice(itemHolder.getInvoiceItemUnitPrice());
                } else {
                    nonInvItems.add(preqItem);
                }
            }
        }
    }
    if (!nonInvItems.isEmpty()) {
        preqDocument.getItems().removeAll(nonInvItems);
    }
}
Also used : PaymentRequestItem(org.kuali.kfs.module.purap.businessobject.PaymentRequestItem) ElectronicInvoiceItemHolder(org.kuali.kfs.module.purap.service.impl.ElectronicInvoiceItemHolder) ArrayList(java.util.ArrayList) KualiDecimal(org.kuali.rice.core.api.util.type.KualiDecimal)

Example 53 with KualiDecimal

use of org.kuali.rice.core.api.util.type.KualiDecimal in project cu-kfs by CU-CommunityApps.

the class CuElectronicInvoiceHelperServiceImpl method processAboveTheLineItem.

protected void processAboveTheLineItem(PaymentRequestItem purapItem, ElectronicInvoiceOrderHolder orderHolder) {
    LOG.info("Processing above the line item");
    ElectronicInvoiceItemHolder itemHolder = orderHolder.getItemByLineNumber(purapItem.getItemLineNumber().intValue());
    // KFSPTS-1719 : investigation
    if (((CuElectronicInvoiceOrderHolder) orderHolder).getMisMatchItem() != null) {
        itemHolder = ((CuElectronicInvoiceOrderHolder) orderHolder).getMisMatchItem();
    }
    if (itemHolder == null) {
        LOG.info("Electronic Invoice does not have item with Ref Item Line number " + purapItem.getItemLineNumber());
        return;
    }
    purapItem.setItemUnitPrice(itemHolder.getInvoiceItemUnitPrice());
    purapItem.setItemQuantity(new KualiDecimal(itemHolder.getInvoiceItemQuantity()));
    purapItem.setItemTaxAmount(new KualiDecimal(itemHolder.getTaxAmount()));
    purapItem.setItemCatalogNumber(itemHolder.getInvoiceItemCatalogNumber());
    purapItem.setItemDescription(itemHolder.getInvoiceItemDescription());
    // KFSUPGRADE-478
    if (itemHolder.getSubTotalAmount() != null) {
        purapItem.setExtendedPrice(itemHolder.getSubTotalAmount());
    } else {
        if (purapItem.getItemQuantity() != null) {
            LOG.info("Item number " + purapItem.getItemLineNumber() + " needs calculation of extended " + "price from quantity " + purapItem.getItemQuantity() + " and unit cost " + purapItem.getItemUnitPrice());
            purapItem.setExtendedPrice(purapItem.getItemQuantity().multiply(new KualiDecimal(purapItem.getItemUnitPrice())));
        } else {
            LOG.info("Item number " + purapItem.getItemLineNumber() + " has no quantity so extended price " + "equals unit price of " + purapItem.getItemUnitPrice());
            purapItem.setExtendedPrice(new KualiDecimal(purapItem.getItemUnitPrice()));
        }
    }
}
Also used : ElectronicInvoiceItemHolder(org.kuali.kfs.module.purap.service.impl.ElectronicInvoiceItemHolder) KualiDecimal(org.kuali.rice.core.api.util.type.KualiDecimal)

Example 54 with KualiDecimal

use of org.kuali.rice.core.api.util.type.KualiDecimal in project cu-kfs by CU-CommunityApps.

the class CuPurapAccountingServiceImpl method updatePreqAccountAmountsOnly.

/*
     * the calculation is based on the percentage of new total amount divided by the existing item totals.
     * The calculated percentage is high precision (20 decimal digits).
     * Then this calculated percentage is used to update each accounting line amount accordingly.
     */
private <T extends PurApAccountingLine> void updatePreqAccountAmountsOnly(List<T> sourceAccountingLines, KualiDecimal totalAmount) {
    if ((totalAmount != null) && KualiDecimal.ZERO.compareTo(totalAmount) != 0) {
        KualiDecimal accountTotal = getItemAccountTotal((List<PurApAccountingLine>) sourceAccountingLines);
        if ((!accountTotal.equals(totalAmount) || isAnyAccountLinePercentEmpty((List<PurApAccountingLine>) sourceAccountingLines)) && !accountTotal.equals(KualiDecimal.ZERO)) {
            BigDecimal tmpPercent = totalAmount.bigDecimalValue().divide(accountTotal.bigDecimalValue(), PurapConstants.CREDITMEMO_PRORATION_SCALE.intValue(), KualiDecimal.ROUND_BEHAVIOR);
            int accountNum = 0;
            accountTotal = KualiDecimal.ZERO;
            BigDecimal percentTotalRoundUp = BigDecimal.ZERO;
            for (T account : sourceAccountingLines) {
                if (accountNum++ < sourceAccountingLines.size() - 1) {
                    if (ObjectUtils.isNotNull(account.getAmount())) {
                        BigDecimal calcAmountBd = tmpPercent.multiply(account.getAmount().bigDecimalValue());
                        calcAmountBd = calcAmountBd.setScale(KualiDecimal.SCALE, KualiDecimal.ROUND_BEHAVIOR);
                        KualiDecimal calcAmount = new KualiDecimal(calcAmountBd);
                        account.setAmount(calcAmount);
                        if (ObjectUtils.isNull(account.getAccountLinePercent()) || account.getAccountLinePercent().compareTo(BigDecimal.ZERO) == 0) {
                            // Tax Item is regenerated if Treasury Manager 'calculate'
                            BigDecimal tmpAcctPercent = account.getAmount().bigDecimalValue().divide(totalAmount.bigDecimalValue(), PurapConstants.CREDITMEMO_PRORATION_SCALE.intValue(), KualiDecimal.ROUND_BEHAVIOR);
                            account.setAccountLinePercent(tmpAcctPercent.multiply(new BigDecimal(100)));
                        }
                        accountTotal = accountTotal.add(calcAmount);
                    }
                } else {
                    account.setAmount(totalAmount.subtract(accountTotal));
                    if (ObjectUtils.isNull(account.getAccountLinePercent()) || account.getAccountLinePercent().compareTo(BigDecimal.ZERO) == 0) {
                        account.setAccountLinePercent(new BigDecimal(100).subtract(percentTotalRoundUp));
                    }
                }
                percentTotalRoundUp = percentTotalRoundUp.add(account.getAccountLinePercent());
            }
        }
    } else {
        for (T account : sourceAccountingLines) {
            account.setAmount(KualiDecimal.ZERO);
        }
    }
}
Also used : PurApAccountingLine(org.kuali.kfs.module.purap.businessobject.PurApAccountingLine) KualiDecimal(org.kuali.rice.core.api.util.type.KualiDecimal) ArrayList(java.util.ArrayList) List(java.util.List) BigDecimal(java.math.BigDecimal)

Example 55 with KualiDecimal

use of org.kuali.rice.core.api.util.type.KualiDecimal in project cu-kfs by CU-CommunityApps.

the class CuPurapAccountingServiceImpl method updatePreqItemAccountAmountsOnly.

/*
     * Updates PREQ accounting line amounts only when Treasury Manager is doing 'calculate'.
     * Currently, the foundation 'updateAccountAmounts' is based on the saved accounting line percentage which is rounded to 2 decimal digits.
     * If the total amount is changed by Treasury Manager, and the calculation is based on 'percentage' saved, then it will cause some amount fraction rounding issue.
     * This is reported in KFSPTS-3644.  You can see the detail explanation of the rounding issues.
     */
private void updatePreqItemAccountAmountsOnly(PurApItem item) {
    List<PurApAccountingLine> sourceAccountingLines = item.getSourceAccountingLines();
    KualiDecimal totalAmount = item.getTotalAmount();
    if (ObjectUtils.isNull(totalAmount) || totalAmount.equals(KualiDecimal.ZERO)) {
        totalAmount = getExtendedPrice(item);
    }
    if (!totalAmount.equals(KualiDecimal.ZERO) && getItemAccountTotal(sourceAccountingLines).equals(KualiDecimal.ZERO)) {
        // item.refreshReferenceObject("sourceAccountingLines"); // this is not working
        // The item account totals can become '0' if Treasury Manager set the unit price to '0 by accident and do calculate.
        // We need to refresh the accounting line amount from DB in order to continue.
        refreshAccountAmount(item);
    }
    if (StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_MISC_CODE, item.getItemTypeCode()) || StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_FREIGHT_CODE, item.getItemTypeCode()) || StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_SHIP_AND_HAND_CODE, item.getItemTypeCode())) {
        if (totalAmount.isNonZero() && getItemAccountTotal(sourceAccountingLines).isZero()) {
            updateMiscFrtSphdAccountAmountsWithTotal(sourceAccountingLines, totalAmount);
        } else {
            updatePreqAccountAmountsOnly(sourceAccountingLines, totalAmount);
        }
    } else {
        updatePreqAccountAmountsOnly(sourceAccountingLines, totalAmount);
    }
}
Also used : PurApAccountingLine(org.kuali.kfs.module.purap.businessobject.PurApAccountingLine) KualiDecimal(org.kuali.rice.core.api.util.type.KualiDecimal)

Aggregations

KualiDecimal (org.kuali.rice.core.api.util.type.KualiDecimal)209 ArrayList (java.util.ArrayList)37 HashMap (java.util.HashMap)19 Test (org.junit.Test)19 List (java.util.List)15 SourceAccountingLine (org.kuali.kfs.sys.businessobject.SourceAccountingLine)15 CapitalAssetInformation (org.kuali.kfs.fp.businessobject.CapitalAssetInformation)14 BigDecimal (java.math.BigDecimal)13 Date (java.sql.Date)13 Iterator (java.util.Iterator)12 PurchaseOrderDocument (org.kuali.kfs.module.purap.document.PurchaseOrderDocument)12 KualiInteger (org.kuali.rice.core.api.util.type.KualiInteger)12 PaymentRequestItem (org.kuali.kfs.module.purap.businessobject.PaymentRequestItem)11 IOException (java.io.IOException)10 ParameterService (org.kuali.kfs.coreservice.framework.parameter.ParameterService)10 Map (java.util.Map)9 CapitalAccountingLines (org.kuali.kfs.fp.businessobject.CapitalAccountingLines)9 PurchaseOrderItem (org.kuali.kfs.module.purap.businessobject.PurchaseOrderItem)9 PaymentGroup (org.kuali.kfs.pdp.businessobject.PaymentGroup)9 RequisitionDocument (org.kuali.kfs.module.purap.document.RequisitionDocument)8