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;
}
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());
}
}
}
}
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;
}
}
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());
}
}
}
}
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
}
}
}
}
Aggregations