Search in sources :

Example 81 with KualiDecimal

use of org.kuali.rice.core.api.util.type.KualiDecimal 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 82 with KualiDecimal

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

the class CuExtractPaymentServiceImpl method writeExtractCheckFile.

@Override
protected void writeExtractCheckFile(PaymentStatus extractedStatus, PaymentProcess p, String filename, Integer processId) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    Date processDate = dateTimeService.getCurrentDate();
    BufferedWriter os = null;
    BufferedWriter osI = null;
    boolean wroteImmediateHeaderRecords = false;
    boolean wroteCheckHeaderRecords = false;
    String immediateFilename = filename.replace("check", "check_immediate");
    String checkFilename = filename;
    boolean first = true;
    boolean isImmediate = false;
    // customer profile, then change the filename to append the RP-Upload prefix.
    if (isResearchParticipantExtractFile(processId)) {
        String checkFilePrefix = this.kualiConfigurationService.getPropertyValueAsString(PdpKeyConstants.ExtractPayment.CHECK_FILENAME);
        checkFilePrefix = MessageFormat.format(checkFilePrefix, new Object[] { null });
        checkFilePrefix = PdpConstants.RESEARCH_PARTICIPANT_FILE_PREFIX + KFSConstants.DASH + checkFilePrefix;
        filename = getOutputFile(checkFilePrefix, processDate);
    }
    try {
        List<String> notificationEmailAddresses = this.getBankPaymentFileNotificationEmailAddresses();
        writeExtractCheckFileMellonBankFastTrack(extractedStatus, p, filename, processId, notificationEmailAddresses);
        List<String> bankCodes = paymentGroupService.getDistinctBankCodesForProcessAndType(processId, PdpConstants.DisbursementTypeCodes.CHECK);
        for (String bankCode : bankCodes) {
            List<Integer> disbNbrs = paymentGroupService.getDisbursementNumbersByDisbursementTypeAndBankCode(processId, PdpConstants.DisbursementTypeCodes.CHECK, bankCode);
            for (Iterator<Integer> iter = disbNbrs.iterator(); iter.hasNext(); ) {
                Integer disbursementNbr = iter.next();
                first = true;
                KualiDecimal totalNetAmount = new KualiDecimal(0);
                // this seems wasteful, but since the total net amount is needed on the first payment detail...it's needed
                Iterator<PaymentDetail> i2 = paymentDetailService.getByDisbursementNumber(disbursementNbr, processId, PdpConstants.DisbursementTypeCodes.CHECK, bankCode);
                while (i2.hasNext()) {
                    PaymentDetail pd = i2.next();
                    totalNetAmount = totalNetAmount.add(pd.getNetPaymentAmount());
                }
                List<KualiInteger> paymentGroupIdsSaved = new ArrayList<KualiInteger>();
                Iterator<PaymentDetail> paymentDetails = paymentDetailService.getByDisbursementNumber(disbursementNbr, processId, PdpConstants.DisbursementTypeCodes.CHECK, bankCode);
                while (paymentDetails.hasNext()) {
                    PaymentDetail detail = paymentDetails.next();
                    PaymentGroup group = detail.getPaymentGroup();
                    if (!testMode) {
                        if (!paymentGroupIdsSaved.contains(group.getId())) {
                            group.setDisbursementDate(new java.sql.Date(processDate.getTime()));
                            group.setPaymentStatus(extractedStatus);
                            this.businessObjectService.save(group);
                            paymentGroupIdsSaved.add(group.getId());
                        }
                    }
                    isImmediate = group.getProcessImmediate();
                    if (first && !isImmediate) {
                        if (!wroteCheckHeaderRecords) {
                            os = new BufferedWriter(new FileWriter(checkFilename));
                            os.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
                            writeOpenTagAttribute(os, 0, "checks", "processId", processId.toString(), "campusCode", p.getCampusCode());
                            wroteCheckHeaderRecords = true;
                        }
                        writeOpenTagAttribute(os, 2, "check", "disbursementNbr", group.getDisbursementNbr().toString());
                        // Write check level information
                        writeBank(os, 4, group.getBank());
                        writeTag(os, 4, "disbursementDate", sdf.format(processDate));
                        writeTag(os, 4, "netAmount", totalNetAmount.toString());
                        writePayee(os, 4, group);
                        writeTag(os, 4, "campusAddressIndicator", group.getCampusAddress().booleanValue() ? "Y" : "N");
                        writeTag(os, 4, "attachmentIndicator", group.getPymtAttachment().booleanValue() ? "Y" : "N");
                        writeTag(os, 4, "specialHandlingIndicator", group.getPymtSpecialHandling().booleanValue() ? "Y" : "N");
                        writeTag(os, 4, "immediatePaymentIndicator", group.getProcessImmediate().booleanValue() ? "Y" : "N");
                        writeTag(os, 4, "customerUnivNbr", group.getCustomerInstitutionNumber());
                        writeTag(os, 4, "paymentDate", sdf.format(group.getPaymentDate()));
                        // Write customer profile information
                        CustomerProfile cp = group.getBatch().getCustomerProfile();
                        writeCustomerProfile(os, 4, cp);
                        writeOpenTag(os, 4, "payments");
                        first = false;
                    }
                    if (first && isImmediate) {
                        if (!wroteImmediateHeaderRecords) {
                            osI = new BufferedWriter(new FileWriter(immediateFilename));
                            osI.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
                            writeOpenTagAttribute(osI, 0, "checks", "processId", processId.toString(), "campusCode", p.getCampusCode());
                            wroteImmediateHeaderRecords = true;
                        }
                        writeOpenTagAttribute(osI, 2, "check", "disbursementNbr", group.getDisbursementNbr().toString());
                        // Write check level information
                        writeBank(osI, 4, group.getBank());
                        writeTag(osI, 4, "disbursementDate", sdf.format(processDate));
                        writeTag(osI, 4, "netAmount", totalNetAmount.toString());
                        writePayee(osI, 4, group);
                        writeTag(osI, 4, "campusAddressIndicator", group.getCampusAddress().booleanValue() ? "Y" : "N");
                        writeTag(osI, 4, "attachmentIndicator", group.getPymtAttachment().booleanValue() ? "Y" : "N");
                        writeTag(osI, 4, "specialHandlingIndicator", group.getPymtSpecialHandling().booleanValue() ? "Y" : "N");
                        writeTag(osI, 4, "immediatePaymentIndicator", group.getProcessImmediate().booleanValue() ? "Y" : "N");
                        writeTag(osI, 4, "customerUnivNbr", group.getCustomerInstitutionNumber());
                        writeTag(osI, 4, "paymentDate", sdf.format(group.getPaymentDate()));
                        // Write customer profile information
                        CustomerProfile cp = group.getBatch().getCustomerProfile();
                        writeCustomerProfile(osI, 4, cp);
                        writeOpenTag(osI, 4, "payments");
                        first = false;
                    }
                    if (!isImmediate && wroteCheckHeaderRecords) {
                        writeOpenTag(os, 6, "payment");
                        writeTag(os, 8, "purchaseOrderNbr", detail.getPurchaseOrderNbr());
                        writeTag(os, 8, "invoiceNbr", detail.getInvoiceNbr());
                        writeTag(os, 8, "requisitionNbr", detail.getRequisitionNbr());
                        writeTag(os, 8, "custPaymentDocNbr", detail.getCustPaymentDocNbr());
                        writeTag(os, 8, "invoiceDate", sdf.format(detail.getInvoiceDate()));
                        writeTag(os, 8, "origInvoiceAmount", detail.getOrigInvoiceAmount().toString());
                        writeTag(os, 8, "netPaymentAmount", detail.getNetPaymentAmount().toString());
                        writeTag(os, 8, "invTotDiscountAmount", detail.getInvTotDiscountAmount().toString());
                        writeTag(os, 8, "invTotShipAmount", detail.getInvTotShipAmount().toString());
                        writeTag(os, 8, "invTotOtherDebitAmount", detail.getInvTotOtherDebitAmount().toString());
                        writeTag(os, 8, "invTotOtherCreditAmount", detail.getInvTotOtherCreditAmount().toString());
                        writeOpenTag(os, 8, "notes");
                        for (Iterator ix = detail.getNotes().iterator(); ix.hasNext(); ) {
                            PaymentNoteText note = (PaymentNoteText) ix.next();
                            writeTag(os, 10, "note", note.getCustomerNoteText());
                        }
                        writeCloseTag(os, 8, "notes");
                        writeCloseTag(os, 6, "payment");
                    }
                    if (isImmediate && wroteImmediateHeaderRecords) {
                        writeOpenTag(osI, 6, "payment");
                        writeTag(osI, 8, "purchaseOrderNbr", detail.getPurchaseOrderNbr());
                        writeTag(osI, 8, "invoiceNbr", detail.getInvoiceNbr());
                        writeTag(osI, 8, "requisitionNbr", detail.getRequisitionNbr());
                        writeTag(osI, 8, "custPaymentDocNbr", detail.getCustPaymentDocNbr());
                        writeTag(osI, 8, "invoiceDate", sdf.format(detail.getInvoiceDate()));
                        writeTag(osI, 8, "origInvoiceAmount", detail.getOrigInvoiceAmount().toString());
                        writeTag(osI, 8, "netPaymentAmount", detail.getNetPaymentAmount().toString());
                        writeTag(osI, 8, "invTotDiscountAmount", detail.getInvTotDiscountAmount().toString());
                        writeTag(osI, 8, "invTotShipAmount", detail.getInvTotShipAmount().toString());
                        writeTag(osI, 8, "invTotOtherDebitAmount", detail.getInvTotOtherDebitAmount().toString());
                        writeTag(osI, 8, "invTotOtherCreditAmount", detail.getInvTotOtherCreditAmount().toString());
                        writeOpenTag(osI, 8, "notes");
                        for (Iterator ix = detail.getNotes().iterator(); ix.hasNext(); ) {
                            PaymentNoteText note = (PaymentNoteText) ix.next();
                            writeTag(osI, 10, "note", note.getCustomerNoteText());
                        }
                        writeCloseTag(osI, 8, "notes");
                        writeCloseTag(osI, 6, "payment");
                    }
                }
                if (wroteCheckHeaderRecords && !isImmediate) {
                    writeCloseTag(os, 4, "payments");
                    writeCloseTag(os, 2, "check");
                }
                if (wroteImmediateHeaderRecords && isImmediate) {
                    writeCloseTag(osI, 4, "payments");
                    writeCloseTag(osI, 2, "check");
                }
            }
        }
    } catch (IOException ie) {
        LOG.error("extractChecks() Problem reading file:  " + filename, ie);
        throw new IllegalArgumentException("Error writing to output file: " + ie.getMessage());
    } finally {
        // Close file
        if (os != null) {
            try {
                writeCloseTag(os, 0, "checks");
                os.close();
                // An XML file containing these records are NEVER sent to anyone at this time.
                renameFile(checkFilename, checkFilename + ".NOT_USED");
                createDoneFile(checkFilename + ".NOT_USED");
            } catch (IOException ie) {
            // Not much we can do now
            }
        }
        if (osI != null) {
            try {
                writeCloseTag(osI, 0, "checks");
                osI.close();
                // An XML file containing these records are ONLY used for local check printing.
                renameFile(immediateFilename, immediateFilename + ".READY");
                createDoneFile(immediateFilename + ".READY");
            } catch (IOException ie) {
                // Not much we can do now
                LOG.error("IOException encountered in writeExtractCheckFile.  Message is: " + ie.getMessage());
            }
        }
    }
}
Also used : KualiInteger(org.kuali.rice.core.api.util.type.KualiInteger) FileWriter(java.io.FileWriter) ArrayList(java.util.ArrayList) BufferedWriter(java.io.BufferedWriter) PaymentDetail(org.kuali.kfs.pdp.businessobject.PaymentDetail) PaymentNoteText(org.kuali.kfs.pdp.businessobject.PaymentNoteText) Iterator(java.util.Iterator) KualiDecimal(org.kuali.rice.core.api.util.type.KualiDecimal) PaymentGroup(org.kuali.kfs.pdp.businessobject.PaymentGroup) CustomerProfile(org.kuali.kfs.pdp.businessobject.CustomerProfile) IOException(java.io.IOException) Date(java.util.Date) KualiInteger(org.kuali.rice.core.api.util.type.KualiInteger) SimpleDateFormat(java.text.SimpleDateFormat)

Example 83 with KualiDecimal

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

the class CuExtractPaymentServiceImpl method writePaymentDetailToAchFile.

/*
     * New method created due to refactoring the code from ExtractPaymentServiceImpl and AchBundlerExtractPaymnetServiceImpl
     */
protected void writePaymentDetailToAchFile(BufferedWriter os, PaymentGroup paymentGroup, PaymentDetail paymentDetail, Map<String, Integer> unitCounts, Map<String, KualiDecimal> unitTotals, SimpleDateFormat sdf) throws IOException {
    try {
        writeOpenTag(os, 6, "payment");
        // Write detail info
        writeTag(os, 8, "purchaseOrderNbr", paymentDetail.getPurchaseOrderNbr());
        writeTag(os, 8, "invoiceNbr", paymentDetail.getInvoiceNbr());
        writeTag(os, 8, "requisitionNbr", paymentDetail.getRequisitionNbr());
        writeTag(os, 8, "custPaymentDocNbr", paymentDetail.getCustPaymentDocNbr());
        writeTag(os, 8, "invoiceDate", sdf.format(paymentDetail.getInvoiceDate()));
        writeTag(os, 8, "origInvoiceAmount", paymentDetail.getOrigInvoiceAmount().toString());
        writeTag(os, 8, "netPaymentAmount", paymentDetail.getNetPaymentAmount().toString());
        writeTag(os, 8, "invTotDiscountAmount", paymentDetail.getInvTotDiscountAmount().toString());
        writeTag(os, 8, "invTotShipAmount", paymentDetail.getInvTotShipAmount().toString());
        writeTag(os, 8, "invTotOtherDebitAmount", paymentDetail.getInvTotOtherDebitAmount().toString());
        writeTag(os, 8, "invTotOtherCreditAmount", paymentDetail.getInvTotOtherCreditAmount().toString());
        writeOpenTag(os, 8, "notes");
        for (Iterator i = paymentDetail.getNotes().iterator(); i.hasNext(); ) {
            PaymentNoteText note = (PaymentNoteText) i.next();
            writeTag(os, 10, "note", updateNoteLine(escapeString(note.getCustomerNoteText())));
        }
        writeCloseTag(os, 8, "notes");
        writeCloseTag(os, 6, "payment");
        String unit = paymentGroup.getBatch().getCustomerProfile().getChartCode() + "-" + paymentGroup.getBatch().getCustomerProfile().getUnitCode() + "-" + paymentGroup.getBatch().getCustomerProfile().getSubUnitCode();
        Integer count = 1;
        if (unitCounts.containsKey(unit)) {
            count = 1 + unitCounts.get(unit);
        }
        unitCounts.put(unit, count);
        KualiDecimal unitTotal = paymentDetail.getNetPaymentAmount();
        if (unitTotals.containsKey(unit)) {
            unitTotal = paymentDetail.getNetPaymentAmount().add(unitTotals.get(unit));
        }
        unitTotals.put(unit, unitTotal);
    } catch (IOException ioe) {
        LOG.error("writePaymentDetailToAchFile(): Problem writing to file - IOException caught and rethrown.");
        throw ioe;
    }
}
Also used : KualiInteger(org.kuali.rice.core.api.util.type.KualiInteger) PaymentNoteText(org.kuali.kfs.pdp.businessobject.PaymentNoteText) Iterator(java.util.Iterator) KualiDecimal(org.kuali.rice.core.api.util.type.KualiDecimal) IOException(java.io.IOException)

Example 84 with KualiDecimal

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

the class CuExtractPaymentServiceImpl method writeExtractBundledAchFile.

/**
 * A custom method that goes through and extracts all pending ACH payments and bundles them by payee/disbursement nbr.
 * Changes made to this method due to re-factoring the code so that common pieces could be used
 * by both ExtractPaymentServiceImpl.writeExtractAchFile and AchBundlerExtractPaymentServiceImpl.writeExtractBundledAchFile
 * as well as incorporating the Mellon file creation.
 * --Added the call to method writeExtractAchFileMellonBankFastTrack
 * --Added the call to writePayeeSpecificsToAchFile for re-factored code
 * --Added the call to writePaymentDetailToAchFile for re-factored code
 * --Made the "finally" clause match the ExtractPaymentServiceImpl.writeExtractAchFile finally so that the XML files are named the same regardless of which routine is invoked.
 * --Added call to get the parameterized bank notification email addresses
 *
 * @param extractedStatus
 * @param filename
 * @param processDate
 * @param sdf
 */
protected void writeExtractBundledAchFile(PaymentStatus extractedStatus, String filename, Date processDate, SimpleDateFormat sdf) {
    LOG.info("writeExtractBundledAchFile started.");
    BufferedWriter os = null;
    try {
        List<String> notificationEmailAddresses = getBankPaymentFileNotificationEmailAddresses();
        // Writes out the BNY Mellon Fast Track formatted file for ACH payments.
        // We need to do this first since the status is set in this method which
        // causes the writeExtractAchFileMellonBankFastTrack method to not find anything.
        writeExtractAchFileMellonBankFastTrack(extractedStatus, filename, processDate, sdf, notificationEmailAddresses);
        // totals for summary
        Map<String, Integer> unitCounts = new HashMap<String, Integer>();
        Map<String, KualiDecimal> unitTotals = new HashMap<String, KualiDecimal>();
        os = new BufferedWriter(new FileWriter(filename));
        os.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        writeOpenTag(os, 0, "achPayments");
        HashSet<String> bankCodes = getAchBundlerHelperService().getDistinctBankCodesForPendingAchPayments();
        for (String bankCode : bankCodes) {
            HashSet<Integer> disbNbrs = getAchBundlerHelperService().getDistinctDisbursementNumbersForPendingAchPaymentsByBankCode(bankCode);
            for (Iterator<Integer> iter = disbNbrs.iterator(); iter.hasNext(); ) {
                Integer disbursementNbr = iter.next();
                boolean first = true;
                KualiDecimal totalNetAmount = new KualiDecimal(0);
                // this seems wasteful, but since the total net amount is needed on the first payment detail...it's needed
                Iterator<PaymentDetail> i2 = getAchBundlerHelperService().getPendingAchPaymentDetailsByDisbursementNumberAndBank(disbursementNbr, bankCode);
                while (i2.hasNext()) {
                    PaymentDetail pd = i2.next();
                    totalNetAmount = totalNetAmount.add(pd.getNetPaymentAmount());
                }
                Iterator<PaymentDetail> paymentDetails = getAchBundlerHelperService().getPendingAchPaymentDetailsByDisbursementNumberAndBank(disbursementNbr, bankCode);
                while (paymentDetails.hasNext()) {
                    PaymentDetail paymentDetail = paymentDetails.next();
                    PaymentGroup paymentGroup = paymentDetail.getPaymentGroup();
                    if (!testMode) {
                        paymentGroup.setDisbursementDate(new java.sql.Date(processDate.getTime()));
                        paymentGroup.setPaymentStatus(extractedStatus);
                        businessObjectService.save(paymentGroup);
                    }
                    if (first) {
                        writePayeeSpecificsToAchFile(os, paymentGroup, processDate, sdf);
                        writeOpenTag(os, 4, "payments");
                    }
                    writePaymentDetailToAchFile(os, paymentGroup, paymentDetail, unitCounts, unitTotals, sdf);
                    first = false;
                }
                writeCloseTag(os, 4, "payments");
                // open for this tag is in method writePayeeSpecificsToAchFile
                writeCloseTag(os, 2, "ach");
            }
        }
        writeCloseTag(os, 0, "achPayments");
        getPaymentFileEmailService().sendAchSummaryEmail(unitCounts, unitTotals, dateTimeService.getCurrentDate());
    } catch (IOException ie) {
        LOG.error("MOD: extractAchFile() Problem reading file:  " + filename, ie);
        throw new IllegalArgumentException("Error writing to output file: " + ie.getMessage());
    } finally {
        // Close file
        if (os != null) {
            try {
                os.close();
                // Need to do this at the end to indicate that the file is NOT USED after it is closed.
                renameFile(filename, filename + ".NOT_USED");
            } catch (IOException ie) {
                // Not much we can do now
                LOG.error("IOException encountered in writeExtractBundledAchFile.  Message is: " + ie.getMessage());
            }
        }
    }
}
Also used : PaymentGroup(org.kuali.kfs.pdp.businessobject.PaymentGroup) HashMap(java.util.HashMap) FileWriter(java.io.FileWriter) IOException(java.io.IOException) BufferedWriter(java.io.BufferedWriter) KualiInteger(org.kuali.rice.core.api.util.type.KualiInteger) PaymentDetail(org.kuali.kfs.pdp.businessobject.PaymentDetail) KualiDecimal(org.kuali.rice.core.api.util.type.KualiDecimal)

Example 85 with KualiDecimal

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

the class CuExtractPaymentServiceImpl method writeExtractAchFile.

@Override
protected void writeExtractAchFile(PaymentStatus extractedStatus, String filename, Date processDate, SimpleDateFormat sdf) {
    BufferedWriter os = null;
    try {
        List<String> notificationEmailAddresses = this.getBankPaymentFileNotificationEmailAddresses();
        // Writes out the BNY Mellon Fast Track formatted file for ACH payments.  We need to do this first since the status is set in this method which
        // causes the writeExtractAchFileMellonBankFastTrack method to not find anything.
        writeExtractAchFileMellonBankFastTrack(extractedStatus, filename, processDate, sdf, notificationEmailAddresses);
        // totals for summary
        Map<String, Integer> unitCounts = new HashMap<String, Integer>();
        Map<String, KualiDecimal> unitTotals = new HashMap<String, KualiDecimal>();
        Iterator iter = paymentGroupService.getByDisbursementTypeStatusCode(PdpConstants.DisbursementTypeCodes.ACH, PdpConstants.PaymentStatusCodes.PENDING_ACH);
        if (iter.hasNext()) {
            OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(filename), "UTF-8");
            os = new BufferedWriter(writer);
            os.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
            writeOpenTag(os, 0, "achPayments");
            while (iter.hasNext()) {
                PaymentGroup paymentGroup = (PaymentGroup) iter.next();
                if (!testMode) {
                    paymentGroup.setDisbursementDate(new java.sql.Date(processDate.getTime()));
                    paymentGroup.setPaymentStatus(extractedStatus);
                    businessObjectService.save(paymentGroup);
                }
                writePayeeSpecificsToAchFile(os, paymentGroup, processDate, sdf);
                // Write all payment level information
                writeOpenTag(os, 4, "payments");
                List<PaymentDetail> pdList = paymentGroup.getPaymentDetails();
                for (PaymentDetail paymentDetail : pdList) {
                    writePaymentDetailToAchFile(os, paymentGroup, paymentDetail, unitCounts, unitTotals, sdf);
                }
                writeCloseTag(os, 4, "payments");
                writeCloseTag(os, 2, "ach");
            }
            writeCloseTag(os, 0, "achPayments");
            paymentFileEmailService.sendAchSummaryEmail(unitCounts, unitTotals, dateTimeService.getCurrentDate());
        }
    } catch (IOException ie) {
        LOG.error("extractAchPayments() Problem reading file:  " + filename, ie);
        throw new IllegalArgumentException("Error writing to output file: " + ie.getMessage());
    } finally {
        // Close file
        if (os != null) {
            try {
                os.close();
            } catch (IOException ie) {
            // Not much we can do now
            }
        }
    }
}
Also used : PaymentGroup(org.kuali.kfs.pdp.businessobject.PaymentGroup) HashMap(java.util.HashMap) IOException(java.io.IOException) BufferedWriter(java.io.BufferedWriter) KualiInteger(org.kuali.rice.core.api.util.type.KualiInteger) PaymentDetail(org.kuali.kfs.pdp.businessobject.PaymentDetail) FileOutputStream(java.io.FileOutputStream) Iterator(java.util.Iterator) KualiDecimal(org.kuali.rice.core.api.util.type.KualiDecimal) OutputStreamWriter(java.io.OutputStreamWriter)

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