0001: /*
0002: * Copyright 2007 The Kuali Foundation.
0003: *
0004: * Licensed under the Educational Community License, Version 1.0 (the "License");
0005: * you may not use this file except in compliance with the License.
0006: * You may obtain a copy of the License at
0007: *
0008: * http://www.opensource.org/licenses/ecl1.php
0009: *
0010: * Unless required by applicable law or agreed to in writing, software
0011: * distributed under the License is distributed on an "AS IS" BASIS,
0012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013: * See the License for the specific language governing permissions and
0014: * limitations under the License.
0015: */
0016: package org.kuali.module.purap.service.impl;
0017:
0018: import java.math.BigDecimal;
0019: import java.sql.Timestamp;
0020: import java.util.ArrayList;
0021: import java.util.Date;
0022: import java.util.HashMap;
0023: import java.util.HashSet;
0024: import java.util.Iterator;
0025: import java.util.List;
0026: import java.util.Map;
0027: import java.util.Set;
0028:
0029: import org.apache.commons.lang.builder.EqualsBuilder;
0030: import org.apache.commons.lang.builder.HashCodeBuilder;
0031: import org.kuali.core.bo.user.UniversalUser;
0032: import org.kuali.core.exceptions.UserNotFoundException;
0033: import org.kuali.core.mail.InvalidAddressException;
0034: import org.kuali.core.mail.MailMessage;
0035: import org.kuali.core.service.BusinessObjectService;
0036: import org.kuali.core.service.DateTimeService;
0037: import org.kuali.core.service.DocumentService;
0038: import org.kuali.core.service.MailService;
0039: import org.kuali.core.service.UniversalUserService;
0040: import org.kuali.core.util.KualiDecimal;
0041: import org.kuali.kfs.KFSConstants;
0042: import org.kuali.kfs.service.ParameterService;
0043: import org.kuali.kfs.service.impl.ParameterConstants;
0044: import org.kuali.module.pdp.PdpConstants;
0045: import org.kuali.module.pdp.bo.Batch;
0046: import org.kuali.module.pdp.bo.CustomerProfile;
0047: import org.kuali.module.pdp.bo.PaymentAccountDetail;
0048: import org.kuali.module.pdp.bo.PaymentDetail;
0049: import org.kuali.module.pdp.bo.PaymentGroup;
0050: import org.kuali.module.pdp.bo.PaymentNoteText;
0051: import org.kuali.module.pdp.bo.PaymentStatus;
0052: import org.kuali.module.pdp.bo.PdpUser;
0053: import org.kuali.module.pdp.service.CustomerProfileService;
0054: import org.kuali.module.pdp.service.EnvironmentService;
0055: import org.kuali.module.pdp.service.PaymentDetailService;
0056: import org.kuali.module.pdp.service.PaymentFileService;
0057: import org.kuali.module.pdp.service.PaymentGroupService;
0058: import org.kuali.module.pdp.service.ReferenceService;
0059: import org.kuali.module.pdp.utilities.GeneralUtilities;
0060: import org.kuali.module.purap.PurapConstants;
0061: import org.kuali.module.purap.PurapParameterConstants;
0062: import org.kuali.module.purap.bo.AccountsPayableItemBase;
0063: import org.kuali.module.purap.bo.CreditMemoItem;
0064: import org.kuali.module.purap.bo.PaymentRequestItem;
0065: import org.kuali.module.purap.bo.PurApAccountingLine;
0066: import org.kuali.module.purap.document.AccountsPayableDocumentBase;
0067: import org.kuali.module.purap.document.CreditMemoDocument;
0068: import org.kuali.module.purap.document.PaymentRequestDocument;
0069: import org.kuali.module.purap.service.CreditMemoService;
0070: import org.kuali.module.purap.service.PaymentRequestService;
0071: import org.kuali.module.purap.service.PdpExtractService;
0072: import org.kuali.module.purap.util.VendorGroupingHelper;
0073: import org.kuali.module.vendor.VendorConstants;
0074: import org.springframework.transaction.annotation.Transactional;
0075:
0076: import edu.iu.uis.eden.exception.WorkflowException;
0077:
0078: /**
0079: * Implementation of PdpExtractService
0080: */
0081: @Transactional
0082: public class PdpExtractServiceImpl implements PdpExtractService {
0083: private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger
0084: .getLogger(PdpExtractServiceImpl.class);
0085:
0086: private PaymentRequestService paymentRequestService;
0087: private BusinessObjectService businessObjectService;
0088: private PaymentFileService paymentFileService;
0089: private ParameterService parameterService;
0090: private CustomerProfileService customerProfileService;
0091: private DateTimeService dateTimeService;
0092: private UniversalUserService universalUserService;
0093: private PaymentGroupService paymentGroupService;
0094: private PaymentDetailService paymentDetailService;
0095: private CreditMemoService creditMemoService;
0096: private ReferenceService referenceService;
0097: private DocumentService documentService;
0098: private MailService mailService;
0099: private EnvironmentService environmentService;
0100:
0101: private PaymentStatus openPaymentStatus;
0102:
0103: // This should only be set to true when testing this system. Setting this to true will run the code but
0104: // won't set the extracted date on the credit memos or payment requests
0105: boolean testMode = false;
0106:
0107: /**
0108: * @see org.kuali.module.purap.service.PdpExtractService#extractImmediatePaymentsOnly()
0109: */
0110: public void extractImmediatePaymentsOnly() {
0111: LOG.debug("extractImmediatePaymentsOnly() started");
0112:
0113: extractPayments(true);
0114: }
0115:
0116: /**
0117: * @see org.kuali.module.purap.service.PdpExtractService#extractPayments()
0118: */
0119: public void extractPayments() {
0120: LOG.debug("extractPayments() started");
0121:
0122: extractPayments(false);
0123: }
0124:
0125: private void extractPayments(boolean immediateOnly) {
0126: LOG.debug("extractPayments() started");
0127:
0128: if (openPaymentStatus == null) {
0129: openPaymentStatus = (PaymentStatus) referenceService
0130: .getCode("PaymentStatus",
0131: PdpConstants.PaymentStatusCodes.OPEN);
0132: }
0133:
0134: Date processRunDate = dateTimeService.getCurrentDate();
0135:
0136: String userId = parameterService.getParameterValue(
0137: ParameterConstants.PURCHASING_BATCH.class,
0138: PurapParameterConstants.PURAP_PDP_USER_ID);
0139: UniversalUser uuser;
0140: try {
0141: uuser = universalUserService
0142: .getUniversalUserByAuthenticationUserId(userId);
0143: } catch (UserNotFoundException e) {
0144: LOG
0145: .error("extractPayments() Unable to find user "
0146: + userId);
0147: throw new IllegalArgumentException("Unable to find user "
0148: + userId);
0149: }
0150: PdpUser puser = new PdpUser(uuser);
0151:
0152: List<String> campusesToProcess = getChartCodes(immediateOnly);
0153: for (Iterator iter = campusesToProcess.iterator(); iter
0154: .hasNext();) {
0155: String campus = (String) iter.next();
0156:
0157: extractPaymentsForCampus(campus, puser, processRunDate,
0158: immediateOnly);
0159: }
0160: }
0161:
0162: /**
0163: * Handle a single campus
0164: *
0165: * @param campusCode
0166: * @param puser
0167: * @param processRunDate
0168: */
0169: private void extractPaymentsForCampus(String campusCode,
0170: PdpUser puser, Date processRunDate, boolean immediateOnly) {
0171: LOG.debug("extractPaymentsForCampus() started for campus: "
0172: + campusCode);
0173:
0174: Batch batch = createBatch(campusCode, puser, processRunDate);
0175: Integer count = 0;
0176: BigDecimal totalAmount = new BigDecimal("0");
0177:
0178: // Do all the special ones
0179: Totals t = extractSpecialPaymentsForChart(campusCode, puser,
0180: processRunDate, batch, immediateOnly);
0181: count = count + t.count;
0182: totalAmount = totalAmount.add(t.totalAmount);
0183:
0184: if (!immediateOnly) {
0185: // Do all the regular ones (including credit memos)
0186: t = extractRegularPaymentsForChart(campusCode, puser,
0187: processRunDate, batch);
0188: count = count + t.count;
0189: totalAmount = totalAmount.add(t.totalAmount);
0190: }
0191:
0192: batch.setPaymentCount(count);
0193: batch.setPaymentTotalAmount(totalAmount);
0194: paymentFileService.saveBatch(batch);
0195: paymentFileService.sendLoadEmail(batch);
0196: }
0197:
0198: /**
0199: * Get all the payments that could be combined with credit memos
0200: *
0201: * @param campusCode
0202: * @param puser
0203: * @param processRunDate
0204: * @param batch
0205: * @return
0206: */
0207: private Totals extractRegularPaymentsForChart(String campusCode,
0208: PdpUser puser, Date processRunDate, Batch batch) {
0209: LOG.debug("START - extractRegularPaymentsForChart()");
0210: Totals t = new Totals();
0211:
0212: List<String> preqsWithOutstandingCreditMemos = new ArrayList<String>();
0213:
0214: // NEW PSEUDOCODE:
0215: // get list of all vendor id/detail IDs on eligible CMs
0216: // loop over vendor's IDs and get matching lists of CMs and PREQs
0217: // if net > 0, generate PDP payment groups and update the documents
0218: Set<VendorGroupingHelper> vendors = creditMemoService
0219: .getVendorsOnCreditMemosToExtract(campusCode);
0220:
0221: List<PaymentRequestDocument> prds = new ArrayList<PaymentRequestDocument>();
0222: List<CreditMemoDocument> cmds = new ArrayList<CreditMemoDocument>();
0223: for (VendorGroupingHelper vendor : vendors) {
0224: if (LOG.isDebugEnabled()) {
0225: LOG.debug("Processing Vendor: " + vendor);
0226: }
0227: prds.clear();
0228: cmds.clear();
0229: KualiDecimal creditMemoAmount = KualiDecimal.ZERO;
0230: KualiDecimal paymentRequestAmount = KualiDecimal.ZERO;
0231: // Get all the matching credit memos
0232: Iterator<CreditMemoDocument> cmIter = creditMemoService
0233: .getCreditMemosToExtractByVendor(campusCode, vendor);
0234: while (cmIter.hasNext()) {
0235: CreditMemoDocument cmd = cmIter.next();
0236: creditMemoAmount = creditMemoAmount.add(cmd
0237: .getCreditMemoAmount());
0238: cmds.add(cmd);
0239: if (LOG.isDebugEnabled()) {
0240: LOG.debug("Added CM to bundle: "
0241: + cmd.getDocumentNumber() + " - $"
0242: + cmd.getCreditMemoAmount());
0243: }
0244: }
0245: // get all matching payment requests
0246: Iterator<PaymentRequestDocument> pri = paymentRequestService
0247: .getPaymentRequestsToExtractByVendor(campusCode,
0248: vendor);
0249: while (pri.hasNext()) {
0250: PaymentRequestDocument prd = pri.next();
0251: paymentRequestAmount = paymentRequestAmount.add(prd
0252: .getGrandTotal());
0253: prds.add(prd);
0254: if (LOG.isDebugEnabled()) {
0255: LOG.debug("Added PREQ to bundle: "
0256: + prd.getDocumentNumber() + " - $"
0257: + prd.getGrandTotal());
0258: }
0259: }
0260: // check if there is anything left to pay
0261: if (LOG.isDebugEnabled()) {
0262: LOG.debug("Bundle Total: "
0263: + paymentRequestAmount
0264: .subtract(creditMemoAmount));
0265: }
0266: if (paymentRequestAmount.compareTo(creditMemoAmount) >= 0) {
0267: // if so, create a payment group and add the CM and PREQ documents
0268: PaymentGroup pg = buildPaymentGroup(prds, cmds, batch);
0269: if (validatePaymentGroup(pg)) {
0270: paymentGroupService.save(pg);
0271: if (LOG.isDebugEnabled()) {
0272: LOG
0273: .debug("Created PaymentGroup: "
0274: + pg.getId());
0275: }
0276:
0277: t.count++;
0278: t.totalAmount = t.totalAmount.add(pg
0279: .getNetPaymentAmount());
0280:
0281: // mark the CMs and PREQs as processed
0282: for (CreditMemoDocument cm : cmds) {
0283: updateCreditMemo(cm, puser, processRunDate);
0284: }
0285: for (PaymentRequestDocument pr : prds) {
0286: updatePaymentRequest(pr, puser, processRunDate);
0287: }
0288: } else {
0289: LOG
0290: .debug("bundle failed validation - NO BUNDLE CREATED");
0291: // stops PREQ documents from being processed by putting them on a "do not process" list
0292: // until validation problems can be resolved
0293: for (PaymentRequestDocument doc : prds) {
0294: preqsWithOutstandingCreditMemos.add(doc
0295: .getDocumentNumber());
0296: }
0297: }
0298: } else {
0299: LOG.debug("bundle net < 0 - NO BUNDLE CREATED");
0300: // put the PREQ documents in this bundle on a "do not process" list for this run
0301: // to prevent them from being picked up by the code below
0302: for (PaymentRequestDocument doc : prds) {
0303: preqsWithOutstandingCreditMemos.add(doc
0304: .getDocumentNumber());
0305: }
0306: }
0307: }
0308:
0309: LOG.debug("processing PREQs without CMs");
0310:
0311: // Get all the payment requests to process that do not have credit memos
0312: Iterator<PaymentRequestDocument> prIter = paymentRequestService
0313: .getPaymentRequestToExtractByChart(campusCode);
0314: while (prIter.hasNext()) {
0315: PaymentRequestDocument prd = prIter.next();
0316: // if in the list created above, don't create the payment group
0317: if (!preqsWithOutstandingCreditMemos.contains(prd
0318: .getDocumentNumber())) {
0319: PaymentGroup pg = processSinglePaymentRequestDocument(
0320: prd, batch, puser, processRunDate);
0321: if (LOG.isDebugEnabled()) {
0322: LOG.debug("Added PREQ to solo bundle: "
0323: + prd.getDocumentNumber() + " - $"
0324: + prd.getGrandTotal());
0325: }
0326:
0327: t.count = t.count + pg.getPaymentDetails().size();
0328: t.totalAmount = t.totalAmount.add(pg
0329: .getNetPaymentAmount());
0330: }
0331: }
0332:
0333: LOG.debug("END - extractRegularPaymentsForChart()");
0334: return t;
0335: }
0336:
0337: /**
0338: * Handle a single payment request with no credit memos
0339: *
0340: * @param prd
0341: * @param batch
0342: * @param puser
0343: * @param processRunDate
0344: * @return
0345: */
0346: private PaymentGroup processSinglePaymentRequestDocument(
0347: PaymentRequestDocument prd, Batch batch, PdpUser puser,
0348: Date processRunDate) {
0349: List<PaymentRequestDocument> prds = new ArrayList<PaymentRequestDocument>();
0350: List<CreditMemoDocument> cmds = new ArrayList<CreditMemoDocument>();
0351: prds.add(prd);
0352:
0353: PaymentGroup pg = buildPaymentGroup(prds, cmds, batch);
0354: if (validatePaymentGroup(pg)) {
0355: paymentGroupService.save(pg);
0356: updatePaymentRequest(prd, puser, processRunDate);
0357: }
0358:
0359: return pg;
0360: }
0361:
0362: /**
0363: *
0364: * This method...
0365: * @param key
0366: * @param itemsToProcess
0367: * @param typeCode
0368: * @return
0369: */
0370: private List<Payment> getByCombineKey(String key,
0371: List itemsToProcess, String typeCode) {
0372: List<Payment> p = new ArrayList<Payment>();
0373: for (Iterator iter = itemsToProcess.iterator(); iter.hasNext();) {
0374: Payment element = (Payment) iter.next();
0375: if (key.equals(element.combineKey())) {
0376: if ((typeCode == null)
0377: || (typeCode.equals(element.typeCode))) {
0378: p.add(element);
0379: }
0380: }
0381: }
0382: return p;
0383: }
0384:
0385: /**
0386: *
0387: * This method...
0388: * @param key
0389: * @param itemsToProcess
0390: * @return
0391: */
0392: private List<Payment> getByCombineKey(String key,
0393: List itemsToProcess) {
0394: return getByCombineKey(key, itemsToProcess, null);
0395: }
0396:
0397: /**
0398: * Get all the special payments for a campus and process them
0399: *
0400: * @param campusCode
0401: * @param puser
0402: * @param processRunDate
0403: * @param batch
0404: * @return
0405: */
0406: private Totals extractSpecialPaymentsForChart(String campusCode,
0407: PdpUser puser, Date processRunDate, Batch batch,
0408: boolean immediatesOnly) {
0409: Totals t = new Totals();
0410:
0411: Iterator<PaymentRequestDocument> prIter = null;
0412: if (immediatesOnly) {
0413: prIter = paymentRequestService
0414: .getImmediatePaymentRequestsToExtract(campusCode);
0415: } else {
0416: prIter = paymentRequestService
0417: .getPaymentRequestsToExtractSpecialPayments(campusCode);
0418: }
0419:
0420: while (prIter.hasNext()) {
0421: PaymentRequestDocument prd = prIter.next();
0422:
0423: PaymentGroup pg = processSinglePaymentRequestDocument(prd,
0424: batch, puser, processRunDate);
0425:
0426: t.count = t.count + pg.getPaymentDetails().size();
0427: t.totalAmount = t.totalAmount.add(pg.getNetPaymentAmount());
0428: }
0429:
0430: return t;
0431: }
0432:
0433: /**
0434: * Mark a credit memo as extracted
0435: *
0436: * @param cmd
0437: * @param puser
0438: * @param processRunDate
0439: */
0440: private void updateCreditMemo(CreditMemoDocument cmd,
0441: PdpUser puser, Date processRunDate) {
0442: if (!testMode) {
0443: try {
0444: CreditMemoDocument doc = (CreditMemoDocument) documentService
0445: .getByDocumentHeaderId(cmd.getDocumentNumber());
0446: doc.setExtractedDate(new java.sql.Date(processRunDate
0447: .getTime()));
0448: creditMemoService.saveDocumentWithoutValidation(doc);
0449: } catch (WorkflowException e) {
0450: throw new IllegalArgumentException(
0451: "Unable to retrieve credit memo: "
0452: + cmd.getDocumentNumber());
0453: }
0454: }
0455: }
0456:
0457: /**
0458: * Mark a payment request as extracted
0459: *
0460: * @param prd
0461: * @param puser
0462: * @param processRunDate
0463: */
0464: private void updatePaymentRequest(PaymentRequestDocument prd,
0465: PdpUser puser, Date processRunDate) {
0466: if (!testMode) {
0467: try {
0468: PaymentRequestDocument doc = (PaymentRequestDocument) documentService
0469: .getByDocumentHeaderId(prd.getDocumentNumber());
0470: doc.setExtractedDate(new java.sql.Date(processRunDate
0471: .getTime()));
0472: paymentRequestService
0473: .saveDocumentWithoutValidation(doc);
0474: } catch (WorkflowException e) {
0475: throw new IllegalArgumentException(
0476: "Unable to retrieve payment request: "
0477: + prd.getDocumentNumber());
0478: }
0479: }
0480: }
0481:
0482: /**
0483: * Create the PDP payment group from a list of payment requests & credit memos
0484: *
0485: * @param prds
0486: * @param cmds
0487: * @param batch
0488: * @return
0489: */
0490: private PaymentGroup buildPaymentGroup(
0491: List<PaymentRequestDocument> prds,
0492: List<CreditMemoDocument> cmds, Batch batch) {
0493:
0494: // There should always be at least one Payment Request Document in the list.
0495: PaymentGroup pg = null;
0496: if (cmds.size() > 0) {
0497: CreditMemoDocument firstCmd = cmds.get(0);
0498: pg = populatePaymentGroup(firstCmd, batch);
0499: } else {
0500: PaymentRequestDocument firstPrd = prds.get(0);
0501: pg = populatePaymentGroup(firstPrd, batch);
0502: }
0503:
0504: for (PaymentRequestDocument pr : prds) {
0505: PaymentDetail pd = populatePaymentDetail(pr, batch);
0506: pg.addPaymentDetails(pd);
0507: }
0508: for (CreditMemoDocument cm : cmds) {
0509: PaymentDetail pd = populatePaymentDetail(cm, batch);
0510: pg.addPaymentDetails(pd);
0511: }
0512:
0513: return pg;
0514: }
0515:
0516: /**
0517: *
0518: * This method...
0519: * @param pg
0520: * @return
0521: */
0522: private boolean validatePaymentGroup(PaymentGroup pg) {
0523: // Check to see if the payment group has too many note lines to be printed on a check
0524: List<PaymentDetail> payDetails = pg.getPaymentDetails();
0525:
0526: int noteLines = 0;
0527: int maxNoteLines = getMaxNoteLines();
0528:
0529: for (PaymentDetail pd : payDetails) {
0530: noteLines++; // Add one for each payment detail; summary of each detail is included on check and counts as a line
0531: noteLines += pd.getNotes().size(); // get all the possible notes for a given detail
0532: }
0533:
0534: if (noteLines > maxNoteLines) {
0535:
0536: // compile list of all doc numbers that make up payment group
0537: List<String> preqDocIds = new ArrayList<String>();
0538: List<String> cmDocIds = new ArrayList<String>();
0539:
0540: List<PaymentDetail> pds = pg.getPaymentDetails();
0541: for (PaymentDetail payDetail : pds) {
0542: if ("CM".equals(payDetail
0543: .getFinancialDocumentTypeCode())) {
0544: cmDocIds.add(payDetail.getCustPaymentDocNbr());
0545: } else {
0546: preqDocIds.add(payDetail.getCustPaymentDocNbr());
0547: }
0548: }
0549:
0550: // send warning email and prevent group from being processed by returning null
0551: sendExceedsMaxNotesWarningEmail(cmDocIds, preqDocIds,
0552: noteLines, maxNoteLines);
0553: return false;
0554: }
0555:
0556: return true;
0557: }
0558:
0559: /**
0560: *
0561: * This method...
0562: * @return
0563: */
0564: private int getMaxNoteLines() {
0565: return GeneralUtilities.getParameterInteger(parameterService,
0566: ParameterConstants.PRE_DISBURSEMENT_ALL.class,
0567: PdpConstants.ApplicationParameterKeys.MAX_NOTE_LINES);
0568: }
0569:
0570: /**
0571: * Create a PDP payment detail from a Credit Memo
0572: *
0573: * @param cmd
0574: * @param batch
0575: * @return
0576: */
0577: private PaymentDetail populatePaymentDetail(CreditMemoDocument cmd,
0578: Batch batch) {
0579: PaymentDetail pd = new PaymentDetail();
0580:
0581: String invNbr = cmd.getCreditMemoNumber();
0582: if (invNbr.length() > 25) {
0583: invNbr = invNbr.substring(0, 25);
0584: }
0585:
0586: pd.setCustPaymentDocNbr(cmd.getDocumentNumber());
0587: pd.setInvoiceNbr(invNbr);
0588: if (cmd.getPurapDocumentIdentifier() != null) {
0589: pd.setPurchaseOrderNbr(cmd.getPurapDocumentIdentifier()
0590: .toString());
0591: }
0592: if (cmd.getPurchaseOrderDocument() != null) {
0593: if (cmd.getPurchaseOrderDocument()
0594: .getRequisitionIdentifier() != null) {
0595: pd.setRequisitionNbr(cmd.getPurchaseOrderDocument()
0596: .getRequisitionIdentifier().toString());
0597: }
0598: if (cmd.getDocumentHeader().getOrganizationDocumentNumber() != null) {
0599: pd.setOrganizationDocNbr(cmd.getDocumentHeader()
0600: .getOrganizationDocumentNumber());
0601: }
0602: }
0603: pd.setFinancialDocumentTypeCode("CM");
0604: pd.setInvoiceDate(new Timestamp(cmd.getCreditMemoDate()
0605: .getTime()));
0606: pd.setOrigInvoiceAmount(cmd.getCreditMemoAmount()
0607: .bigDecimalValue().negate());
0608:
0609: pd.setNetPaymentAmount(cmd.getDocumentHeader()
0610: .getFinancialDocumentTotalAmount().bigDecimalValue()
0611: .negate());
0612:
0613: BigDecimal shippingAmount = new BigDecimal("0");
0614: BigDecimal discountAmount = new BigDecimal("0");
0615: BigDecimal creditAmount = new BigDecimal("0");
0616: BigDecimal debitAmount = new BigDecimal("0");
0617: for (Iterator iter = cmd.getItems().iterator(); iter.hasNext();) {
0618: CreditMemoItem item = (CreditMemoItem) iter.next();
0619: BigDecimal itemAmount = new BigDecimal("0");
0620: if (item.getExtendedPrice() != null) {
0621: itemAmount = item.getExtendedPrice().bigDecimalValue();
0622: }
0623: if (PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE
0624: .equals(item.getItemTypeCode())) {
0625: discountAmount = discountAmount.subtract(itemAmount);
0626: } else if (PurapConstants.ItemTypeCodes.ITEM_TYPE_SHIP_AND_HAND_CODE
0627: .equals(item.getItemTypeCode())) {
0628: shippingAmount = shippingAmount.subtract(itemAmount);
0629: } else if (PurapConstants.ItemTypeCodes.ITEM_TYPE_MIN_ORDER_CODE
0630: .equals(item.getItemTypeCode())) {
0631: debitAmount = debitAmount.subtract(itemAmount);
0632: } else if (PurapConstants.ItemTypeCodes.ITEM_TYPE_MISC_CODE
0633: .equals(item.getItemTypeCode())) {
0634: if (itemAmount.compareTo(new BigDecimal("0")) < 0) {
0635: creditAmount = creditAmount.subtract(itemAmount);
0636: } else {
0637: debitAmount = debitAmount.subtract(itemAmount);
0638: }
0639: }
0640: }
0641:
0642: pd.setInvTotDiscountAmount(discountAmount);
0643: pd.setInvTotShipAmount(shippingAmount);
0644: pd.setInvTotOtherCreditAmount(creditAmount);
0645: pd.setInvTotOtherDebitAmount(debitAmount);
0646:
0647: pd.setPrimaryCancelledPayment(Boolean.FALSE);
0648:
0649: addAccounts(cmd, pd, "CM");
0650: addNotes(cmd, pd);
0651: return pd;
0652: }
0653:
0654: /**
0655: * Create a PDP Payment Detail from a Payment Request
0656: *
0657: * @param prd
0658: * @param batch
0659: * @return
0660: */
0661: private PaymentDetail populatePaymentDetail(
0662: PaymentRequestDocument prd, Batch batch) {
0663: PaymentDetail pd = new PaymentDetail();
0664:
0665: pd.setCustPaymentDocNbr(prd.getDocumentNumber());
0666:
0667: String invNbr = prd.getInvoiceNumber();
0668: if (invNbr.length() > 25) {
0669: invNbr = invNbr.substring(0, 25);
0670: }
0671: pd.setInvoiceNbr(invNbr);
0672: if (prd.getPurapDocumentIdentifier() != null) {
0673: pd.setPurchaseOrderNbr(prd.getPurchaseOrderIdentifier()
0674: .toString());
0675: }
0676: LOG.debug("populatePaymentDetail() po id: "
0677: + prd.getPurchaseOrderIdentifier());
0678: if (prd.getPurchaseOrderDocument().getRequisitionIdentifier() != null) {
0679: pd.setRequisitionNbr(prd.getPurchaseOrderDocument()
0680: .getRequisitionIdentifier().toString());
0681: }
0682: if (prd.getDocumentHeader().getOrganizationDocumentNumber() != null) {
0683: pd.setOrganizationDocNbr(prd.getDocumentHeader()
0684: .getOrganizationDocumentNumber());
0685: }
0686: pd.setFinancialDocumentTypeCode("PREQ");
0687: pd
0688: .setInvoiceDate(new Timestamp(prd.getInvoiceDate()
0689: .getTime()));
0690: pd.setOrigInvoiceAmount(prd.getVendorInvoiceAmount()
0691: .bigDecimalValue());
0692:
0693: pd.setNetPaymentAmount(prd.getDocumentHeader()
0694: .getFinancialDocumentTotalAmount().bigDecimalValue());
0695:
0696: BigDecimal shippingAmount = new BigDecimal("0");
0697: BigDecimal discountAmount = new BigDecimal("0");
0698: BigDecimal creditAmount = new BigDecimal("0");
0699: BigDecimal debitAmount = new BigDecimal("0");
0700: for (Iterator iter = prd.getItems().iterator(); iter.hasNext();) {
0701: PaymentRequestItem item = (PaymentRequestItem) iter.next();
0702: BigDecimal itemAmount = new BigDecimal("0");
0703: if (item.getExtendedPrice() != null) {
0704: itemAmount = item.getExtendedPrice().bigDecimalValue();
0705: }
0706: if (PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE
0707: .equals(item.getItemTypeCode())) {
0708: discountAmount = discountAmount.add(itemAmount);
0709: } else if (PurapConstants.ItemTypeCodes.ITEM_TYPE_SHIP_AND_HAND_CODE
0710: .equals(item.getItemTypeCode())) {
0711: shippingAmount = shippingAmount.add(itemAmount);
0712: } else if (PurapConstants.ItemTypeCodes.ITEM_TYPE_MIN_ORDER_CODE
0713: .equals(item.getItemTypeCode())) {
0714: debitAmount = debitAmount.add(itemAmount);
0715: } else if (PurapConstants.ItemTypeCodes.ITEM_TYPE_MISC_CODE
0716: .equals(item.getItemTypeCode())) {
0717: if (itemAmount.compareTo(new BigDecimal("0")) < 0) {
0718: creditAmount = creditAmount.add(itemAmount);
0719: } else {
0720: debitAmount = debitAmount.add(itemAmount);
0721: }
0722: }
0723: }
0724:
0725: pd.setInvTotDiscountAmount(discountAmount);
0726: pd.setInvTotShipAmount(shippingAmount);
0727: pd.setInvTotOtherCreditAmount(creditAmount);
0728: pd.setInvTotOtherDebitAmount(debitAmount);
0729:
0730: pd.setPrimaryCancelledPayment(Boolean.FALSE);
0731:
0732: addAccounts(prd, pd, "PREQ");
0733: addNotes(prd, pd);
0734: return pd;
0735: }
0736:
0737: /**
0738: * Add accounts to a PDP Payment Detail
0739: *
0740: * @param prd
0741: * @param pd
0742: */
0743: private void addAccounts(AccountsPayableDocumentBase prd,
0744: PaymentDetail pd, String documentType) {
0745: // Calculate the total amount for each account across all items
0746: Map accounts = new HashMap();
0747: for (Iterator iter = prd.getItems().iterator(); iter.hasNext();) {
0748: AccountsPayableItemBase item = (AccountsPayableItemBase) iter
0749: .next();
0750: for (Iterator iterator = item.getSourceAccountingLines()
0751: .iterator(); iterator.hasNext();) {
0752: PurApAccountingLine account = (PurApAccountingLine) iterator
0753: .next();
0754: AccountingInfo ai = new AccountingInfo(account
0755: .getChartOfAccountsCode(), account
0756: .getAccountNumber(), account
0757: .getSubAccountNumber(), account
0758: .getFinancialObjectCode(), account
0759: .getFinancialSubObjectCode(), account
0760: .getOrganizationReferenceId(), account
0761: .getProjectCode());
0762:
0763: BigDecimal amt = account.getAmount().bigDecimalValue();
0764: if ("CM".equals(documentType)) {
0765: amt = amt.negate();
0766: }
0767:
0768: if (accounts.containsKey(ai)) {
0769: BigDecimal total = amt.add((BigDecimal) accounts
0770: .get(ai));
0771: accounts.put(ai, total);
0772: } else {
0773: accounts.put(ai, amt);
0774: }
0775: }
0776: }
0777:
0778: for (Iterator iter = accounts.keySet().iterator(); iter
0779: .hasNext();) {
0780: AccountingInfo ai = (AccountingInfo) iter.next();
0781: PaymentAccountDetail pad = new PaymentAccountDetail();
0782: pad.setAccountNbr(ai.account);
0783: pad.setAccountNetAmount((BigDecimal) accounts.get(ai));
0784: pad.setFinChartCode(ai.chart);
0785: pad.setFinObjectCode(ai.objectCode);
0786: pad.setFinSubObjectCode(ai.subObjectCode);
0787: pad.setOrgReferenceId(ai.orgReferenceId);
0788: pad.setProjectCode(ai.projectCode);
0789: pad.setSubAccountNbr(ai.subAccount);
0790: pd.addAccountDetail(pad);
0791: }
0792: }
0793:
0794: /**
0795: * Add Notes to a PDP Payment Detail
0796: *
0797: * @param doc
0798: * @param pd
0799: */
0800: private void addNotes(AccountsPayableDocumentBase doc,
0801: PaymentDetail pd) {
0802:
0803: int count = 1;
0804:
0805: if (doc instanceof PaymentRequestDocument) {
0806: PaymentRequestDocument prd = (PaymentRequestDocument) doc;
0807:
0808: if (prd.getSpecialHandlingInstructionLine1Text() != null) {
0809: PaymentNoteText pnt = new PaymentNoteText();
0810: pnt.setCustomerNoteLineNbr(count++);
0811: pnt.setCustomerNoteText(prd
0812: .getSpecialHandlingInstructionLine1Text());
0813: pd.addNote(pnt);
0814: }
0815: if (prd.getSpecialHandlingInstructionLine2Text() != null) {
0816: PaymentNoteText pnt = new PaymentNoteText();
0817: pnt.setCustomerNoteLineNbr(count++);
0818: pnt.setCustomerNoteText(prd
0819: .getSpecialHandlingInstructionLine2Text());
0820: pd.addNote(pnt);
0821: }
0822: if (prd.getSpecialHandlingInstructionLine3Text() != null) {
0823: PaymentNoteText pnt = new PaymentNoteText();
0824: pnt.setCustomerNoteLineNbr(count++);
0825: pnt.setCustomerNoteText(prd
0826: .getSpecialHandlingInstructionLine3Text());
0827: pd.addNote(pnt);
0828: }
0829: }
0830: if (doc.getNoteLine1Text() != null) {
0831: PaymentNoteText pnt = new PaymentNoteText();
0832: pnt.setCustomerNoteLineNbr(count++);
0833: pnt.setCustomerNoteText(doc.getNoteLine1Text());
0834: pd.addNote(pnt);
0835: }
0836: if (doc.getNoteLine2Text() != null) {
0837: PaymentNoteText pnt = new PaymentNoteText();
0838: pnt.setCustomerNoteLineNbr(count++);
0839: pnt.setCustomerNoteText(doc.getNoteLine2Text());
0840: pd.addNote(pnt);
0841: }
0842: if (doc.getNoteLine3Text() != null) {
0843: PaymentNoteText pnt = new PaymentNoteText();
0844: pnt.setCustomerNoteLineNbr(count++);
0845: pnt.setCustomerNoteText(doc.getNoteLine3Text());
0846: pd.addNote(pnt);
0847: }
0848: }
0849:
0850: /**
0851: * Populate the PDP Payment Group from fields on a payment request
0852: *
0853: * @param prd
0854: * @param batch
0855: * @return
0856: */
0857: private PaymentGroup populatePaymentGroup(
0858: PaymentRequestDocument prd, Batch batch) {
0859: LOG
0860: .debug("populatePaymentGroup() payment request documentNumber: "
0861: + prd.getDocumentNumber());
0862: PaymentGroup pg = new PaymentGroup();
0863: pg.setBatch(batch);
0864: pg.setPaymentStatus(openPaymentStatus);
0865:
0866: String postalCode = prd.getVendorPostalCode();
0867: if ("US".equals(prd.getVendorCountry())) {
0868: // Add a dash in the zip code if necessary
0869: if (postalCode.length() > 5) {
0870: postalCode = postalCode.substring(0, 5) + "-"
0871: + postalCode.substring(5);
0872: }
0873: }
0874:
0875: pg.setPayeeName(prd.getVendorName());
0876: pg.setPayeeId(prd.getVendorHeaderGeneratedIdentifier() + "-"
0877: + prd.getVendorDetailAssignedIdentifier());
0878: pg.setPayeeIdTypeCd(PdpConstants.PayeeTypeCodes.VENDOR);
0879:
0880: if (prd.getVendorDetail().getVendorHeader()
0881: .getVendorOwnershipCategoryCode() != null) {
0882: pg.setPayeeOwnerCd(prd.getVendorDetail().getVendorHeader()
0883: .getVendorOwnershipCategoryCode());
0884: }
0885:
0886: if (prd.getVendorCustomerNumber() != null) {
0887: pg.setCustomerInstitutionNumber(prd
0888: .getVendorCustomerNumber());
0889: }
0890: pg.setLine1Address(prd.getVendorLine1Address());
0891: pg.setLine2Address(prd.getVendorLine2Address());
0892: pg.setLine3Address("");
0893: pg.setLine4Address("");
0894: pg.setCity(prd.getVendorCityName());
0895: pg.setState(prd.getVendorStateCode());
0896: pg.setZipCd(postalCode);
0897: pg.setCountry(prd.getVendorCountryCode());
0898: pg.setCampusAddress(Boolean.FALSE);
0899: if (prd.getPaymentRequestPayDate() != null) {
0900: pg.setPaymentDate(new Timestamp(prd
0901: .getPaymentRequestPayDate().getTime()));
0902: }
0903: pg.setPymtAttachment(prd.getPaymentAttachmentIndicator());
0904: pg.setProcessImmediate(prd.getImmediatePaymentIndicator());
0905: pg
0906: .setPymtSpecialHandling((prd
0907: .getSpecialHandlingInstructionLine1Text() != null)
0908: || (prd
0909: .getSpecialHandlingInstructionLine2Text() != null)
0910: || (prd
0911: .getSpecialHandlingInstructionLine3Text() != null));
0912: pg.setTaxablePayment(Boolean.FALSE);
0913: pg.setNraPayment(VendorConstants.OwnerTypes.NR.equals(prd
0914: .getVendorDetail().getVendorHeader()
0915: .getVendorOwnershipCode()));
0916: pg.setCombineGroups(Boolean.TRUE);
0917: return pg;
0918: }
0919:
0920: /**
0921: *
0922: * This method...
0923: * @param cmd
0924: * @param batch
0925: * @return
0926: */
0927: private PaymentGroup populatePaymentGroup(CreditMemoDocument cmd,
0928: Batch batch) {
0929: LOG.debug("populatePaymentGroup() credit memo documentNumber: "
0930: + cmd.getDocumentNumber());
0931: PaymentGroup pg = new PaymentGroup();
0932: pg.setBatch(batch);
0933: pg.setPaymentStatus(openPaymentStatus);
0934:
0935: String postalCode = cmd.getVendorPostalCode();
0936: if ("US".equals(cmd.getVendorCountry())) {
0937: // Add a dash in the zip code if necessary
0938: if (postalCode.length() > 5) {
0939: postalCode = postalCode.substring(0, 5) + "-"
0940: + postalCode.substring(5);
0941: }
0942: }
0943:
0944: pg.setPayeeName(cmd.getVendorName());
0945: pg.setPayeeId(cmd.getVendorHeaderGeneratedIdentifier() + "-"
0946: + cmd.getVendorDetailAssignedIdentifier());
0947: pg.setPayeeIdTypeCd(PdpConstants.PayeeTypeCodes.VENDOR);
0948:
0949: if (cmd.getVendorDetail().getVendorHeader()
0950: .getVendorOwnershipCategoryCode() != null) {
0951: pg.setPayeeOwnerCd(cmd.getVendorDetail().getVendorHeader()
0952: .getVendorOwnershipCategoryCode());
0953: }
0954:
0955: if (cmd.getVendorCustomerNumber() != null) {
0956: pg.setCustomerInstitutionNumber(cmd
0957: .getVendorCustomerNumber());
0958: }
0959: pg.setLine1Address(cmd.getVendorLine1Address());
0960: pg.setLine2Address(cmd.getVendorLine2Address());
0961: pg.setLine3Address("");
0962: pg.setLine4Address("");
0963: pg.setCity(cmd.getVendorCityName());
0964: pg.setState(cmd.getVendorStateCode());
0965: pg.setZipCd(postalCode);
0966: pg.setCountry(cmd.getVendorCountryCode());
0967: pg.setCampusAddress(Boolean.FALSE);
0968: if (cmd.getCreditMemoDate() != null) {
0969: pg.setPaymentDate(new Timestamp(cmd.getCreditMemoDate()
0970: .getTime()));
0971: }
0972: pg.setPymtAttachment(Boolean.FALSE);
0973: pg.setProcessImmediate(Boolean.FALSE);
0974: pg.setPymtSpecialHandling(Boolean.FALSE);
0975: pg.setTaxablePayment(Boolean.FALSE);
0976: pg.setNraPayment(VendorConstants.OwnerTypes.NR.equals(cmd
0977: .getVendorDetail().getVendorHeader()
0978: .getVendorOwnershipCode()));
0979: pg.setCombineGroups(Boolean.TRUE);
0980: return pg;
0981: }
0982:
0983: /**
0984: * Create a new PDP batch
0985: *
0986: * @param campusCode
0987: * @param puser
0988: * @param processRunDate
0989: * @return
0990: */
0991: private Batch createBatch(String campusCode, PdpUser puser,
0992: Date processRunDate) {
0993: String orgCode = parameterService.getParameterValue(
0994: ParameterConstants.PURCHASING_BATCH.class,
0995: PurapParameterConstants.PURAP_PDP_EPIC_ORG_CODE);
0996: String subUnitCode = parameterService.getParameterValue(
0997: ParameterConstants.PURCHASING_BATCH.class,
0998: PurapParameterConstants.PURAP_PDP_EPIC_SBUNT_CODE);
0999: CustomerProfile customer = customerProfileService.get(
1000: campusCode, orgCode, subUnitCode);
1001: if (customer == null) {
1002: throw new IllegalArgumentException(
1003: "Unable to find customer profile for " + campusCode
1004: + "/" + orgCode + "/" + subUnitCode);
1005: }
1006:
1007: // Create the group for this campus
1008: Batch batch = new Batch();
1009: batch.setCustomerProfile(customer);
1010: batch.setCustomerFileCreateTimestamp(new Timestamp(
1011: processRunDate.getTime()));
1012: batch.setFileProcessTimestamp(new Timestamp(processRunDate
1013: .getTime()));
1014: batch.setPaymentFileName("extr_fr_purap");
1015: batch.setSubmiterUser(puser);
1016:
1017: // Set these for now, we will update them later
1018: batch.setPaymentCount(0);
1019: batch.setPaymentTotalAmount(new BigDecimal("0"));
1020: paymentFileService.saveBatch(batch);
1021:
1022: return batch;
1023: }
1024:
1025: /**
1026: * Find all the campuses that have payments to process
1027: *
1028: * @return
1029: */
1030: private List<String> getChartCodes(boolean immediatesOnly) {
1031: List<String> output = new ArrayList<String>();
1032:
1033: Iterator<PaymentRequestDocument> iter = null;
1034: if (immediatesOnly) {
1035: iter = paymentRequestService
1036: .getImmediatePaymentRequestsToExtract(null);
1037: } else {
1038: iter = paymentRequestService.getPaymentRequestsToExtract();
1039:
1040: }
1041: while (iter.hasNext()) {
1042: PaymentRequestDocument prd = iter.next();
1043: if (!output.contains(prd.getProcessingCampusCode())) {
1044: output.add(prd.getProcessingCampusCode());
1045: }
1046: }
1047: return output;
1048: }
1049:
1050: /**
1051: *
1052: * This method...
1053: * @param idList
1054: * @param lineTotal
1055: * @param maxNoteLines
1056: */
1057: private void sendExceedsMaxNotesWarningEmail(List<String> cmIdList,
1058: List<String> preqIdList, int lineTotal, int maxNoteLines) {
1059: LOG.debug("sendExceedsMaxNotesWarningEmail() starting");
1060:
1061: // To send email or not send email
1062: boolean noEmail = parameterService
1063: .getIndicatorParameter(
1064: ParameterConstants.PRE_DISBURSEMENT_ALL.class,
1065: PdpConstants.ApplicationParameterKeys.NO_PAYMENT_FILE_EMAIL);
1066: if (noEmail) {
1067: LOG
1068: .debug("sendExceedsMaxNotesWarningEmail() sending payment file email is disabled");
1069: return;
1070: }
1071:
1072: MailMessage message = new MailMessage();
1073:
1074: if (environmentService.isProduction()) {
1075: message
1076: .setSubject("Error: Maximum rows exceeded on payment bundle");
1077: } else {
1078: String env = environmentService.getEnvironment();
1079: message
1080: .setSubject(env
1081: + "-Error: Maximum rows exceeded on payment bundle");
1082: }
1083:
1084: StringBuffer body = new StringBuffer();
1085:
1086: // Get recipient email address
1087: String toAddresses = parameterService
1088: .getParameterValue(
1089: ParameterConstants.PRE_DISBURSEMENT_ALL.class,
1090: PdpConstants.ApplicationParameterKeys.PDP_ERROR_EXCEEDS_NOTE_LIMIT_EMAIL);
1091: String toAddressList[] = toAddresses.split(",");
1092:
1093: if (toAddressList.length > 0) {
1094: for (int i = 0; i < toAddressList.length; i++) {
1095: if (toAddressList[i] != null) {
1096: message.addToAddress(toAddressList[i].trim());
1097: }
1098: }
1099: }
1100:
1101: String ccAddresses = parameterService.getParameterValue(
1102: ParameterConstants.PRE_DISBURSEMENT_ALL.class,
1103: PdpConstants.ApplicationParameterKeys.SOFT_EDIT_CC);
1104: String ccAddressList[] = ccAddresses.split(",");
1105:
1106: for (int i = 0; i < ccAddressList.length; i++) {
1107: if (ccAddressList[i] != null) {
1108: message.addCcAddress(ccAddressList[i].trim());
1109: }
1110: }
1111:
1112: String fromAddressList[] = { mailService.getBatchMailingList() };
1113:
1114: if (fromAddressList.length > 0) {
1115: for (int i = 0; i < fromAddressList.length; i++) {
1116: if (fromAddressList[i] != null) {
1117: message.setFromAddress(fromAddressList[i].trim());
1118: }
1119: }
1120: }
1121:
1122: body
1123: .append("The positive pay bundle associated with the following credit memo(s) and payment request(s) ");
1124: body
1125: .append("exceeds the row limit. The credit memo(s) may need to be processed as several separate credit ");
1126: body
1127: .append("memos to reduce the number of rows associated with the positive pay bundle. \n\n");
1128: body.append("The Credit Memo Document Id(s) are ");
1129:
1130: int cmCount = cmIdList.size();
1131: for (String id : cmIdList) {
1132: body.append(id);
1133: if (--cmCount > 0) {
1134: body.append(", ");
1135: }
1136: }
1137:
1138: body.append(". The PREQ Document Id(s) are ");
1139:
1140: int prCount = preqIdList.size();
1141: for (String id : preqIdList) {
1142: body.append(id);
1143: if (--prCount > 0) {
1144: body.append(", ");
1145: }
1146: }
1147: body.append(". There were ").append(lineTotal).append(
1148: " lines all together, which is more than the ");
1149: body.append(maxNoteLines).append(" allowed.");
1150:
1151: message.setMessage(body.toString());
1152: try {
1153: mailService.sendMessage(message);
1154: } catch (InvalidAddressException e) {
1155: LOG
1156: .error(
1157: "sendExceedsMaxNotesWarningEmail() Invalid email address. Message not sent",
1158: e);
1159: }
1160: }
1161:
1162: /**
1163: *
1164: * This class...
1165: */
1166: class Payment {
1167: public static final String CM = "cm";
1168: public static final String PREQ = "preq";
1169:
1170: public Integer id;
1171: public String typeCode;
1172: public String campusCode;
1173: public String vendorId;
1174: public String countryCode;
1175: public String zipCode;
1176: public String customerNbr;
1177: public Object data;
1178:
1179: public Payment(Integer id, String typeCode, String campusCode,
1180: String vendorId, String countryCode, String zipCode,
1181: String customerNbr, Object data) {
1182: this .id = id;
1183: this .typeCode = typeCode;
1184: this .campusCode = campusCode;
1185: this .vendorId = vendorId;
1186: this .countryCode = countryCode;
1187: if ((zipCode != null) && (zipCode.length() > 5)) {
1188: this .zipCode = zipCode.substring(0, 5);
1189: } else {
1190: this .zipCode = zipCode;
1191: }
1192: this .customerNbr = customerNbr;
1193: this .data = data;
1194: }
1195:
1196: public boolean combine(Payment p) {
1197: return combineKey().equals(p.combineKey());
1198: }
1199:
1200: public String combineKey() {
1201: return campusCode + "~" + vendorId + "~" + customerNbr
1202: + "~" + countryCode + "~" + zipCode;
1203: }
1204:
1205: private String key() {
1206: return campusCode + "~" + vendorId + "~" + customerNbr
1207: + "~" + countryCode + "~" + zipCode + "~"
1208: + typeCode + "~" + id;
1209: }
1210:
1211: public int hashCode() {
1212: return new HashCodeBuilder(3, 5).append(key()).toHashCode();
1213: }
1214:
1215: public boolean equals(Object obj) {
1216: if (!(obj instanceof AccountingInfo)) {
1217: return false;
1218: }
1219: AccountingInfo this obj = (AccountingInfo) obj;
1220: return new EqualsBuilder().append(key(), this obj.key())
1221: .isEquals();
1222: }
1223: }
1224:
1225: class Totals {
1226: public Integer count = 0;
1227: public BigDecimal totalAmount = new BigDecimal("0");
1228: }
1229:
1230: class AccountingInfo {
1231: private String chart;
1232: private String account;
1233: private String subAccount;
1234: private String objectCode;
1235: private String subObjectCode;
1236: private String orgReferenceId;
1237: private String projectCode;
1238:
1239: public AccountingInfo(String c, String a, String s, String o,
1240: String so, String or, String pc) {
1241: setChart(c);
1242: setAccount(a);
1243: setSubAccount(s);
1244: setObjectCode(o);
1245: setSubObjectCode(so);
1246: setOrgReferenceId(or);
1247: setProjectCode(pc);
1248: }
1249:
1250: public void setAccount(String account) {
1251: this .account = account;
1252: }
1253:
1254: public void setChart(String chart) {
1255: this .chart = chart;
1256: }
1257:
1258: public void setObjectCode(String objectCode) {
1259: this .objectCode = objectCode;
1260: }
1261:
1262: public void setOrgReferenceId(String orgReferenceId) {
1263: this .orgReferenceId = orgReferenceId;
1264: }
1265:
1266: public void setProjectCode(String projectCode) {
1267: if (projectCode == null) {
1268: this .projectCode = KFSConstants.getDashProjectCode();
1269: } else {
1270: this .projectCode = projectCode;
1271: }
1272: }
1273:
1274: public void setSubAccount(String subAccount) {
1275: if (subAccount == null) {
1276: this .subAccount = KFSConstants
1277: .getDashSubAccountNumber();
1278: } else {
1279: this .subAccount = subAccount;
1280: }
1281: }
1282:
1283: public void setSubObjectCode(String subObjectCode) {
1284: if (subObjectCode == null) {
1285: this .subObjectCode = KFSConstants
1286: .getDashFinancialSubObjectCode();
1287: } else {
1288: this .subObjectCode = subObjectCode;
1289: }
1290: }
1291:
1292: private String key() {
1293: return chart + "~" + account + "~" + subAccount + "~"
1294: + objectCode + "~" + subObjectCode + "~"
1295: + orgReferenceId + "~" + projectCode;
1296: }
1297:
1298: public int hashCode() {
1299: return new HashCodeBuilder(3, 5).append(key()).toHashCode();
1300: }
1301:
1302: public boolean equals(Object obj) {
1303: if (!(obj instanceof AccountingInfo)) {
1304: return false;
1305: }
1306: AccountingInfo this obj = (AccountingInfo) obj;
1307: return new EqualsBuilder().append(key(), this obj.key())
1308: .isEquals();
1309: }
1310: }
1311:
1312: // Dependencies
1313:
1314: public void setPaymentFileService(PaymentFileService pfs) {
1315: paymentFileService = pfs;
1316: }
1317:
1318: public void setPaymentRequestService(PaymentRequestService prs) {
1319: paymentRequestService = prs;
1320: }
1321:
1322: public void setCustomerProfileService(
1323: CustomerProfileService customerProfileService) {
1324: this .customerProfileService = customerProfileService;
1325: }
1326:
1327: public void setDateTimeService(DateTimeService dateTimeService) {
1328: this .dateTimeService = dateTimeService;
1329: }
1330:
1331: public void setUniversalUserService(
1332: UniversalUserService universalUserService) {
1333: this .universalUserService = universalUserService;
1334: }
1335:
1336: public void setPaymentDetailService(
1337: PaymentDetailService paymentDetailService) {
1338: this .paymentDetailService = paymentDetailService;
1339: }
1340:
1341: public void setPaymentGroupService(
1342: PaymentGroupService paymentGroupService) {
1343: this .paymentGroupService = paymentGroupService;
1344: }
1345:
1346: public void setCreditMemoService(CreditMemoService cms) {
1347: this .creditMemoService = cms;
1348: }
1349:
1350: public void setBusinessObjectService(BusinessObjectService bos) {
1351: this .businessObjectService = bos;
1352: }
1353:
1354: public void setParameterService(ParameterService parameterService) {
1355: this .parameterService = parameterService;
1356: }
1357:
1358: public void setReferenceService(ReferenceService rs) {
1359: referenceService = rs;
1360: }
1361:
1362: public void setDocumentService(DocumentService ds) {
1363: documentService = ds;
1364: }
1365:
1366: public void setMailService(MailService ms) {
1367: mailService = ms;
1368: }
1369:
1370: public void setEnvironmentService(EnvironmentService es) {
1371: environmentService = es;
1372: }
1373:
1374: }
|