Source Code Cross Referenced for PaymentRequestServiceImpl.java in  » ERP-CRM-Financial » Kuali-Financial-System » org » kuali » module » purap » service » impl » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » ERP CRM Financial » Kuali Financial System » org.kuali.module.purap.service.impl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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.Date;
0020:        import java.sql.Timestamp;
0021:        import java.util.ArrayList;
0022:        import java.util.Calendar;
0023:        import java.util.Collection;
0024:        import java.util.HashMap;
0025:        import java.util.Iterator;
0026:        import java.util.List;
0027:        import java.util.Map;
0028:
0029:        import org.apache.commons.collections.CollectionUtils;
0030:        import org.apache.commons.lang.StringUtils;
0031:        import org.kuali.core.bo.DocumentHeader;
0032:        import org.kuali.core.bo.Note;
0033:        import org.kuali.core.bo.user.UniversalUser;
0034:        import org.kuali.core.exceptions.ValidationException;
0035:        import org.kuali.core.service.BusinessObjectService;
0036:        import org.kuali.core.service.DataDictionaryService;
0037:        import org.kuali.core.service.DateTimeService;
0038:        import org.kuali.core.service.DocumentService;
0039:        import org.kuali.core.service.KualiConfigurationService;
0040:        import org.kuali.core.service.NoteService;
0041:        import org.kuali.core.util.GlobalVariables;
0042:        import org.kuali.core.util.KualiDecimal;
0043:        import org.kuali.core.util.ObjectUtils;
0044:        import org.kuali.kfs.KFSPropertyConstants;
0045:        import org.kuali.kfs.bo.SourceAccountingLine;
0046:        import org.kuali.kfs.context.SpringContext;
0047:        import org.kuali.kfs.rule.event.DocumentSystemSaveEvent;
0048:        import org.kuali.kfs.service.ParameterService;
0049:        import org.kuali.kfs.service.impl.ParameterConstants;
0050:        import org.kuali.module.purap.PurapConstants;
0051:        import org.kuali.module.purap.PurapKeyConstants;
0052:        import org.kuali.module.purap.PurapParameterConstants;
0053:        import org.kuali.module.purap.PurapWorkflowConstants;
0054:        import org.kuali.module.purap.PurapConstants.PREQDocumentsStrings;
0055:        import org.kuali.module.purap.PurapConstants.PaymentRequestStatuses;
0056:        import org.kuali.module.purap.PurapWorkflowConstants.NodeDetails;
0057:        import org.kuali.module.purap.PurapWorkflowConstants.PaymentRequestDocument.NodeDetailEnum;
0058:        import org.kuali.module.purap.bo.AutoApproveExclude;
0059:        import org.kuali.module.purap.bo.ItemType;
0060:        import org.kuali.module.purap.bo.NegativePaymentRequestApprovalLimit;
0061:        import org.kuali.module.purap.bo.PaymentRequestAccount;
0062:        import org.kuali.module.purap.bo.PaymentRequestItem;
0063:        import org.kuali.module.purap.bo.PurApAccountingLine;
0064:        import org.kuali.module.purap.bo.PurchaseOrderItem;
0065:        import org.kuali.module.purap.dao.PaymentRequestDao;
0066:        import org.kuali.module.purap.document.AccountsPayableDocument;
0067:        import org.kuali.module.purap.document.CreditMemoDocument;
0068:        import org.kuali.module.purap.document.PaymentRequestDocument;
0069:        import org.kuali.module.purap.document.PurchaseOrderDocument;
0070:        import org.kuali.module.purap.rule.event.ContinueAccountsPayableEvent;
0071:        import org.kuali.module.purap.service.AccountsPayableService;
0072:        import org.kuali.module.purap.service.NegativePaymentRequestApprovalLimitService;
0073:        import org.kuali.module.purap.service.PaymentRequestService;
0074:        import org.kuali.module.purap.service.PurApWorkflowIntegrationService;
0075:        import org.kuali.module.purap.service.PurapAccountingService;
0076:        import org.kuali.module.purap.service.PurapService;
0077:        import org.kuali.module.purap.service.PurchaseOrderService;
0078:        import org.kuali.module.purap.util.ExpiredOrClosedAccountEntry;
0079:        import org.kuali.module.purap.util.PurApItemUtils;
0080:        import org.kuali.module.purap.util.VendorGroupingHelper;
0081:        import org.kuali.module.vendor.bo.PaymentTermType;
0082:        import org.springframework.transaction.annotation.Transactional;
0083:
0084:        import edu.iu.uis.eden.exception.WorkflowException;
0085:
0086:        /**
0087:         * This class provides services of use to a payment request document
0088:         */
0089:        @Transactional
0090:        public class PaymentRequestServiceImpl implements  PaymentRequestService {
0091:            private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger
0092:                    .getLogger(PaymentRequestServiceImpl.class);
0093:
0094:            private DateTimeService dateTimeService;
0095:            private DocumentService documentService;
0096:            private NoteService noteService;
0097:            private PurapService purapService;
0098:            private PaymentRequestDao paymentRequestDao;
0099:            private PurchaseOrderService purchaseOrderService;
0100:            private ParameterService parameterService;
0101:            private KualiConfigurationService configurationService;
0102:            private NegativePaymentRequestApprovalLimitService negativePaymentRequestApprovalLimitService;
0103:            private PurapAccountingService purapAccountingService;
0104:            private BusinessObjectService businessObjectService;
0105:            private PurApWorkflowIntegrationService purapWorkflowIntegrationService;
0106:
0107:            public void setDateTimeService(DateTimeService dateTimeService) {
0108:                this .dateTimeService = dateTimeService;
0109:            }
0110:
0111:            public void setParameterService(ParameterService parameterService) {
0112:                this .parameterService = parameterService;
0113:            }
0114:
0115:            public void setConfigurationService(
0116:                    KualiConfigurationService configurationService) {
0117:                this .configurationService = configurationService;
0118:            }
0119:
0120:            public void setDocumentService(DocumentService documentService) {
0121:                this .documentService = documentService;
0122:            }
0123:
0124:            public void setNoteService(NoteService noteService) {
0125:                this .noteService = noteService;
0126:            }
0127:
0128:            public void setPurapService(PurapService purapService) {
0129:                this .purapService = purapService;
0130:            }
0131:
0132:            public void setPaymentRequestDao(PaymentRequestDao paymentRequestDao) {
0133:                this .paymentRequestDao = paymentRequestDao;
0134:            }
0135:
0136:            public void setPurchaseOrderService(
0137:                    PurchaseOrderService purchaseOrderService) {
0138:                this .purchaseOrderService = purchaseOrderService;
0139:            }
0140:
0141:            public void setNegativePaymentRequestApprovalLimitService(
0142:                    NegativePaymentRequestApprovalLimitService negativePaymentRequestApprovalLimitService) {
0143:                this .negativePaymentRequestApprovalLimitService = negativePaymentRequestApprovalLimitService;
0144:            }
0145:
0146:            public void setPurapAccountingService(
0147:                    PurapAccountingService purapAccountingService) {
0148:                this .purapAccountingService = purapAccountingService;
0149:            }
0150:
0151:            public void setBusinessObjectService(
0152:                    BusinessObjectService businessObjectService) {
0153:                this .businessObjectService = businessObjectService;
0154:            }
0155:
0156:            public void setPurapWorkflowIntegrationService(
0157:                    PurApWorkflowIntegrationService purapWorkflowIntegrationService) {
0158:                this .purapWorkflowIntegrationService = purapWorkflowIntegrationService;
0159:            }
0160:
0161:            /**
0162:             * @see org.kuali.module.purap.server.PaymentRequestService.getPaymentRequestsToExtractByCM()
0163:             */
0164:            public Iterator<PaymentRequestDocument> getPaymentRequestsToExtractByCM(
0165:                    String campusCode, CreditMemoDocument cmd) {
0166:                LOG.debug("getPaymentRequestsByCM() started");
0167:
0168:                return paymentRequestDao.getPaymentRequestsToExtract(
0169:                        campusCode, null, null, cmd
0170:                                .getVendorHeaderGeneratedIdentifier(), cmd
0171:                                .getVendorDetailAssignedIdentifier());
0172:            }
0173:
0174:            public Iterator<PaymentRequestDocument> getPaymentRequestsToExtractByVendor(
0175:                    String campusCode, VendorGroupingHelper vendor) {
0176:                LOG.debug("getPaymentRequestsByVendor() started");
0177:
0178:                return paymentRequestDao.getPaymentRequestsToExtractForVendor(
0179:                        campusCode, vendor);
0180:            }
0181:
0182:            /**
0183:             * @see org.kuali.module.purap.server.PaymentRequestService.getPaymentRequestsToExtract()
0184:             */
0185:            public Iterator<PaymentRequestDocument> getPaymentRequestsToExtract() {
0186:                LOG.debug("getPaymentRequestsToExtract() started");
0187:
0188:                return paymentRequestDao.getPaymentRequestsToExtract(false,
0189:                        null);
0190:            }
0191:
0192:            /**
0193:             * @see org.kuali.module.purap.service.PaymentRequestService#getPaymentRequestsToExtractSpecialPayments(java.lang.String)
0194:             */
0195:            public Iterator<PaymentRequestDocument> getPaymentRequestsToExtractSpecialPayments(
0196:                    String chartCode) {
0197:                LOG
0198:                        .debug("getPaymentRequestsToExtractSpecialPayments() started");
0199:
0200:                return paymentRequestDao.getPaymentRequestsToExtract(true,
0201:                        chartCode);
0202:            }
0203:
0204:            /**
0205:             * @see org.kuali.module.purap.service.PaymentRequestService#getImmediatePaymentRequestsToExtract(java.lang.String)
0206:             */
0207:            public Iterator<PaymentRequestDocument> getImmediatePaymentRequestsToExtract(
0208:                    String chartCode) {
0209:                LOG.debug("getImmediatePaymentRequestsToExtract() started");
0210:
0211:                return paymentRequestDao
0212:                        .getImmediatePaymentRequestsToExtract(chartCode);
0213:            }
0214:
0215:            /**
0216:             * @see org.kuali.module.purap.service.PaymentRequestService#getPaymentRequestToExtractByChart(java.lang.String)
0217:             */
0218:            public Iterator<PaymentRequestDocument> getPaymentRequestToExtractByChart(
0219:                    String chartCode) {
0220:                LOG.debug("getPaymentRequestToExtractByChart() started");
0221:
0222:                return paymentRequestDao.getPaymentRequestsToExtract(false,
0223:                        chartCode);
0224:            }
0225:
0226:            /**
0227:             * @see org.kuali.module.purap.service.PaymentRequestService.autoApprovePaymentRequests()
0228:             */
0229:            public boolean autoApprovePaymentRequests() {
0230:                boolean hadErrorAtLeastOneError = true;
0231:                // should objects from existing user session be copied over
0232:                List<PaymentRequestDocument> docs = paymentRequestDao
0233:                        .getEligibleForAutoApproval();
0234:                if (docs != null) {
0235:                    String samt = parameterService
0236:                            .getParameterValue(
0237:                                    PaymentRequestDocument.class,
0238:                                    PurapParameterConstants.PURAP_DEFAULT_NEGATIVE_PAYMENT_REQUEST_APPROVAL_LIMIT);
0239:                    KualiDecimal defaultMinimumLimit = new KualiDecimal(samt);
0240:                    for (PaymentRequestDocument paymentRequestDocument : docs) {
0241:                        hadErrorAtLeastOneError |= !autoApprovePaymentRequest(
0242:                                paymentRequestDocument, defaultMinimumLimit);
0243:                    }
0244:                }
0245:                return hadErrorAtLeastOneError;
0246:            }
0247:
0248:            /**
0249:             * @see org.kuali.module.purap.service.PaymentRequestService#autoApprovePaymentRequest(org.kuali.module.purap.document.PaymentRequestDocument, org.kuali.core.util.KualiDecimal)
0250:             */
0251:            public boolean autoApprovePaymentRequest(
0252:                    PaymentRequestDocument doc, KualiDecimal defaultMinimumLimit) {
0253:                if (isEligibleForAutoApproval(doc, defaultMinimumLimit)) {
0254:                    try {
0255:                        purapService.updateStatus(doc,
0256:                                PaymentRequestStatuses.AUTO_APPROVED);
0257:                        documentService.blanketApproveDocument(doc,
0258:                                "auto-approving: Total is below threshold.",
0259:                                null);
0260:                    } catch (WorkflowException we) {
0261:                        LOG.error(
0262:                                "Exception encountered when approving document number "
0263:                                        + doc.getDocumentNumber() + ".", we);
0264:                        return false;
0265:                    }
0266:                }
0267:                return true;
0268:            }
0269:
0270:            /**
0271:             * Determines whether or not a payment request document can be automatically approved. FYI - If fiscal reviewers are
0272:             * allowed to save account changes without the full account validation running then this method must call full account
0273:             * validation to make sure auto approver is not blanket approving an invalid document according the the accounts on the items
0274:             * 
0275:             * @param document             The payment request document to be determined whether it can be automatically approved.
0276:             * @param defaultMinimumLimit  The amount to be used as the minimum amount if no limit was found or the default is
0277:             *                             less than the limit.
0278:             * @return                     boolean true if the payment request document is eligible for auto approval.
0279:             */
0280:            private boolean isEligibleForAutoApproval(
0281:                    PaymentRequestDocument document,
0282:                    KualiDecimal defaultMinimumLimit) {
0283:                // check to make sure the payment request isn't scheduled to stop in tax review.
0284:                if (purapWorkflowIntegrationService
0285:                        .willDocumentStopAtGivenFutureRouteNode(
0286:                                document,
0287:                                PurapWorkflowConstants.PaymentRequestDocument.NodeDetailEnum.VENDOR_TAX_REVIEW)) {
0288:                    return false;
0289:                }
0290:
0291:                // This minimum will be set to the minimum limit derived from all
0292:                // accounting lines on the document. If no limit is determined, the
0293:                // default will be used.
0294:                KualiDecimal minimumAmount = null;
0295:
0296:                // Iterate all source accounting lines on the document, deriving a
0297:                // minimum limit from each according to chart, chart and account, and
0298:                // chart and organization.
0299:                for (SourceAccountingLine line : purapAccountingService
0300:                        .generateSummary(document.getItems())) {
0301:                    // check to make sure the account is in the auto approve exclusion list
0302:                    Map<String, String> autoApproveMap = new HashMap<String, String>();
0303:                    autoApproveMap.put("chartOfAccountsCode", line
0304:                            .getChartOfAccountsCode());
0305:                    autoApproveMap
0306:                            .put("accountNumber", line.getAccountNumber());
0307:                    AutoApproveExclude autoApproveExclude = (AutoApproveExclude) businessObjectService
0308:                            .findByPrimaryKey(AutoApproveExclude.class,
0309:                                    autoApproveMap);
0310:                    if (autoApproveExclude != null) {
0311:                        return false;
0312:                    }
0313:
0314:                    minimumAmount = getMinimumLimitAmount(
0315:                            negativePaymentRequestApprovalLimitService
0316:                                    .findByChart(line.getChartOfAccountsCode()),
0317:                            minimumAmount);
0318:                    minimumAmount = getMinimumLimitAmount(
0319:                            negativePaymentRequestApprovalLimitService
0320:                                    .findByChartAndAccount(line
0321:                                            .getChartOfAccountsCode(), line
0322:                                            .getAccountNumber()), minimumAmount);
0323:                    minimumAmount = getMinimumLimitAmount(
0324:                            negativePaymentRequestApprovalLimitService
0325:                                    .findByChartAndOrganization(line
0326:                                            .getChartOfAccountsCode(), line
0327:                                            .getOrganizationReferenceId()),
0328:                            minimumAmount);
0329:                }
0330:
0331:                // If no limit was found or the default is less than the limit, the default limit is used.
0332:                if (ObjectUtils.isNull(minimumAmount)
0333:                        || defaultMinimumLimit.compareTo(minimumAmount) < 0) {
0334:                    minimumAmount = defaultMinimumLimit;
0335:                }
0336:
0337:                // The document is eligible for auto-approval if the document total is below the limit.
0338:                if (document.getDocumentHeader()
0339:                        .getFinancialDocumentTotalAmount().isLessThan(
0340:                                minimumAmount)) {
0341:                    return true;
0342:                }
0343:
0344:                return false;
0345:            }
0346:
0347:            /**
0348:             * This method iterates a collection of negative payment request approval limits and returns the minimum of a given minimum
0349:             * amount and the least among the limits in the collection.
0350:             * 
0351:             * @param limits         The collection of NegativePaymentRequestApprovalLimit to be used in determining the minimum limit amount.
0352:             * @param minimumAmount  The amount to be compared with the collection of NegativePaymentRequestApprovalLimit to determine the
0353:             *                       minimum limit amount.
0354:             * @return               The minimum of the given minimum amount and the least among the limits in the collection.
0355:             */
0356:            private KualiDecimal getMinimumLimitAmount(
0357:                    Collection<NegativePaymentRequestApprovalLimit> limits,
0358:                    KualiDecimal minimumAmount) {
0359:                for (NegativePaymentRequestApprovalLimit limit : limits) {
0360:                    KualiDecimal amount = limit
0361:                            .getNegativePaymentRequestApprovalLimitAmount();
0362:                    if (null == minimumAmount) {
0363:                        minimumAmount = amount;
0364:                    } else if (minimumAmount.isGreaterThan(amount)) {
0365:                        minimumAmount = amount;
0366:                    }
0367:                }
0368:                return minimumAmount;
0369:            }
0370:
0371:            /**
0372:             * Retrieves a list of payment request documents with the given vendor id and invoice number.
0373:             * 
0374:             * @param vendorHeaderGeneratedId  The vendor header generated id.
0375:             * @param vendorDetailAssignedId   The vendor detail assigned id.
0376:             * @param invoiceNumber            The invoice number as entered by AP.
0377:             * @return                         List of payment request document.
0378:             */
0379:            public List getPaymentRequestsByVendorNumberInvoiceNumber(
0380:                    Integer vendorHeaderGeneratedId,
0381:                    Integer vendorDetailAssignedId, String invoiceNumber) {
0382:                LOG
0383:                        .debug("getActivePaymentRequestsByVendorNumberInvoiceNumber() started");
0384:                return paymentRequestDao
0385:                        .getActivePaymentRequestsByVendorNumberInvoiceNumber(
0386:                                vendorHeaderGeneratedId,
0387:                                vendorDetailAssignedId, invoiceNumber);
0388:            }
0389:
0390:            /**
0391:             * @see org.kuali.module.purap.service.PaymentRequestService#paymentRequestDuplicateMessages(org.kuali.module.purap.document.PaymentRequestDocument)
0392:             */
0393:            public HashMap<String, String> paymentRequestDuplicateMessages(
0394:                    PaymentRequestDocument document) {
0395:                HashMap<String, String> msgs;
0396:                msgs = new HashMap<String, String>();
0397:
0398:                Integer purchaseOrderId = document.getPurchaseOrderIdentifier();
0399:
0400:                if (ObjectUtils.isNotNull(document.getInvoiceDate())) {
0401:                    if (purapService.isDateAYearBeforeToday(document
0402:                            .getInvoiceDate())) {
0403:                        msgs
0404:                                .put(
0405:                                        PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION,
0406:                                        configurationService
0407:                                                .getPropertyString(PurapKeyConstants.MESSAGE_INVOICE_DATE_A_YEAR_OR_MORE_PAST));
0408:                    }
0409:                }
0410:                PurchaseOrderDocument po = document.getPurchaseOrderDocument();
0411:
0412:                if (po != null) {
0413:                    Integer vendorDetailAssignedId = po
0414:                            .getVendorDetailAssignedIdentifier();
0415:                    Integer vendorHeaderGeneratedId = po
0416:                            .getVendorHeaderGeneratedIdentifier();
0417:
0418:                    List<PaymentRequestDocument> preqs = getPaymentRequestsByVendorNumberInvoiceNumber(
0419:                            vendorHeaderGeneratedId, vendorDetailAssignedId,
0420:                            document.getInvoiceNumber());
0421:
0422:                    if (preqs.size() > 0) {
0423:                        boolean addedMessage = false;
0424:                        boolean foundCanceledPostApprove = false; // cancelled
0425:                        boolean foundCanceledPreApprove = false; // voided
0426:                        for (PaymentRequestDocument testPREQ : preqs) {
0427:                            if (StringUtils
0428:                                    .equals(
0429:                                            testPREQ.getStatusCode(),
0430:                                            PaymentRequestStatuses.CANCELLED_POST_AP_APPROVE)) {
0431:                                foundCanceledPostApprove |= true;
0432:                            } else if (StringUtils
0433:                                    .equals(
0434:                                            testPREQ.getStatusCode(),
0435:                                            PaymentRequestStatuses.CANCELLED_IN_PROCESS)) {
0436:                                foundCanceledPreApprove |= true;
0437:                            } else {
0438:                                msgs
0439:                                        .put(
0440:                                                PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION,
0441:                                                configurationService
0442:                                                        .getPropertyString(PurapKeyConstants.MESSAGE_DUPLICATE_INVOICE));
0443:                                addedMessage = true;
0444:                                break;
0445:                            }
0446:                        }
0447:                        // Custom error message for duplicates related to cancelled/voided PREQs
0448:                        if (!addedMessage) {
0449:                            if (foundCanceledPostApprove
0450:                                    && foundCanceledPreApprove) {
0451:                                msgs
0452:                                        .put(
0453:                                                PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION,
0454:                                                configurationService
0455:                                                        .getPropertyString(PurapKeyConstants.MESSAGE_DUPLICATE_INVOICE_CANCELLEDORVOIDED));
0456:                            } else if (foundCanceledPreApprove) {
0457:                                msgs
0458:                                        .put(
0459:                                                PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION,
0460:                                                configurationService
0461:                                                        .getPropertyString(PurapKeyConstants.MESSAGE_DUPLICATE_INVOICE_VOIDED));
0462:                            } else if (foundCanceledPostApprove) {
0463:                                // messages.add("errors.duplicate.vendor.invoice.cancelled");
0464:                                msgs
0465:                                        .put(
0466:                                                PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION,
0467:                                                configurationService
0468:                                                        .getPropertyString(PurapKeyConstants.MESSAGE_DUPLICATE_INVOICE_CANCELLED));
0469:                            }
0470:                        }
0471:                    }
0472:
0473:                    // Check that the invoice date and invoice total amount entered are not on any existing non-cancelled PREQs for this PO
0474:                    preqs = getPaymentRequestsByPOIdInvoiceAmountInvoiceDate(
0475:                            purchaseOrderId, document.getVendorInvoiceAmount(),
0476:                            document.getInvoiceDate());
0477:                    if (preqs.size() > 0) {
0478:                        boolean addedMessage = false;
0479:                        boolean foundCanceledPostApprove = false; // cancelled
0480:                        boolean foundCanceledPreApprove = false; // voided
0481:                        msgs
0482:                                .put(
0483:                                        PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION,
0484:                                        configurationService
0485:                                                .getPropertyString(PurapKeyConstants.MESSAGE_DUPLICATE_INVOICE_DATE_AMOUNT));
0486:                        for (PaymentRequestDocument testPREQ : preqs) {
0487:                            if (StringUtils
0488:                                    .equalsIgnoreCase(
0489:                                            testPREQ.getStatusCode(),
0490:                                            PaymentRequestStatuses.CANCELLED_POST_AP_APPROVE)) {
0491:                                foundCanceledPostApprove |= true;
0492:                            } else if (StringUtils
0493:                                    .equalsIgnoreCase(
0494:                                            testPREQ.getStatusCode(),
0495:                                            PaymentRequestStatuses.CANCELLED_IN_PROCESS)) {
0496:                                foundCanceledPreApprove |= true;
0497:                            } else {
0498:                                msgs
0499:                                        .put(
0500:                                                PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION,
0501:                                                configurationService
0502:                                                        .getPropertyString(PurapKeyConstants.MESSAGE_DUPLICATE_INVOICE_DATE_AMOUNT));
0503:                                addedMessage = true;
0504:                                break;
0505:                            }
0506:                        }
0507:
0508:                        // Custom error message for duplicates related to cancelled/voided PREQs
0509:                        if (!addedMessage) {
0510:                            if (foundCanceledPostApprove
0511:                                    && foundCanceledPreApprove) {
0512:                                msgs
0513:                                        .put(
0514:                                                PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION,
0515:                                                configurationService
0516:                                                        .getPropertyString(PurapKeyConstants.MESSAGE_DUPLICATE_INVOICE_DATE_AMOUNT_CANCELLEDORVOIDED));
0517:                            } else if (foundCanceledPreApprove) {
0518:                                msgs
0519:                                        .put(
0520:                                                PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION,
0521:                                                configurationService
0522:                                                        .getPropertyString(PurapKeyConstants.MESSAGE_DUPLICATE_INVOICE_DATE_AMOUNT_VOIDED));
0523:                                addedMessage = true;
0524:                            } else if (foundCanceledPostApprove) {
0525:                                msgs
0526:                                        .put(
0527:                                                PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION,
0528:                                                configurationService
0529:                                                        .getPropertyString(PurapKeyConstants.MESSAGE_DUPLICATE_INVOICE_DATE_AMOUNT_CANCELLED));
0530:                                addedMessage = true;
0531:                            }
0532:
0533:                        }
0534:                    }
0535:                }
0536:                return msgs;
0537:            }
0538:
0539:            /**
0540:             * @see org.kuali.module.purap.service.PaymentRequestService#getPaymentRequestByDocumentNumber(java.lang.String)
0541:             */
0542:            public PaymentRequestDocument getPaymentRequestByDocumentNumber(
0543:                    String documentNumber) {
0544:                LOG.debug("getPaymentRequestByDocumentNumber() started");
0545:
0546:                if (ObjectUtils.isNotNull(documentNumber)) {
0547:                    try {
0548:                        PaymentRequestDocument doc = (PaymentRequestDocument) documentService
0549:                                .getByDocumentHeaderId(documentNumber);
0550:                        return doc;
0551:                    } catch (WorkflowException e) {
0552:                        String errorMessage = "Error getting payment request document from document service";
0553:                        LOG.error("getPaymentRequestByDocumentNumber() "
0554:                                + errorMessage, e);
0555:                        throw new RuntimeException(errorMessage, e);
0556:                    }
0557:                }
0558:                return null;
0559:            }
0560:
0561:            /**
0562:             * @see org.kuali.module.purap.service.PaymentRequestService#getPaymentRequestById(java.lang.Integer)
0563:             */
0564:            public PaymentRequestDocument getPaymentRequestById(Integer poDocId) {
0565:                return getPaymentRequestByDocumentNumber(paymentRequestDao
0566:                        .getDocumentNumberByPaymentRequestId(poDocId));
0567:            }
0568:
0569:            /**
0570:             * @see org.kuali.module.purap.service.PaymentRequestService#getPaymentRequestsByPurchaseOrderId(java.lang.Integer)
0571:             */
0572:            public List<PaymentRequestDocument> getPaymentRequestsByPurchaseOrderId(
0573:                    Integer poDocId) {
0574:                List<PaymentRequestDocument> preqs = new ArrayList<PaymentRequestDocument>();
0575:                List<String> docNumbers = paymentRequestDao
0576:                        .getDocumentNumbersByPurchaseOrderId(poDocId);
0577:                for (String docNumber : docNumbers) {
0578:                    PaymentRequestDocument preq = getPaymentRequestByDocumentNumber(docNumber);
0579:                    if (ObjectUtils.isNotNull(preq)) {
0580:                        preqs.add(preq);
0581:                    }
0582:                }
0583:                return preqs;
0584:            }
0585:
0586:            /**
0587:             * @see org.kuali.module.purap.service.CreditMemoService#saveDocumentWithoutValidation(org.kuali.module.purap.document.CreditMemoDocument)
0588:             */
0589:            public void saveDocumentWithoutValidation(
0590:                    PaymentRequestDocument document) {
0591:                try {
0592:                    documentService.saveDocument(document,
0593:                            DocumentSystemSaveEvent.class);
0594:                } catch (WorkflowException we) {
0595:                    String errorMsg = "Error saving document # "
0596:                            + document.getDocumentHeader().getDocumentNumber()
0597:                            + " " + we.getMessage();
0598:                    LOG.error(errorMsg, we);
0599:                    throw new RuntimeException(errorMsg, we);
0600:                }
0601:            }
0602:
0603:            /**
0604:             * @see org.kuali.module.purap.service.PaymentRequestService#getPaymentRequestsByPOIdInvoiceAmountInvoiceDate(java.lang.Integer, org.kuali.core.util.KualiDecimal, java.sql.Date)
0605:             */
0606:            public List getPaymentRequestsByPOIdInvoiceAmountInvoiceDate(
0607:                    Integer poId, KualiDecimal invoiceAmount, Date invoiceDate) {
0608:                LOG
0609:                        .debug("getPaymentRequestsByPOIdInvoiceAmountInvoiceDate() started");
0610:                return paymentRequestDao
0611:                        .getActivePaymentRequestsByPOIdInvoiceAmountInvoiceDate(
0612:                                poId, invoiceAmount, invoiceDate);
0613:            }
0614:
0615:            /**
0616:             * @see org.kuali.module.purap.service.PaymentRequestService#isInvoiceDateAfterToday(java.sql.Date)
0617:             */
0618:            public boolean isInvoiceDateAfterToday(Date invoiceDate) {
0619:                // Check invoice date to make sure it is today or before
0620:                Calendar now = Calendar.getInstance();
0621:                now.set(Calendar.HOUR, 11);
0622:                now.set(Calendar.MINUTE, 59);
0623:                now.set(Calendar.SECOND, 59);
0624:                now.set(Calendar.MILLISECOND, 59);
0625:                Timestamp nowTime = new Timestamp(now.getTimeInMillis());
0626:                Calendar invoiceDateC = Calendar.getInstance();
0627:                invoiceDateC.setTime(invoiceDate);
0628:                // set time to midnight
0629:                invoiceDateC.set(Calendar.HOUR, 0);
0630:                invoiceDateC.set(Calendar.MINUTE, 0);
0631:                invoiceDateC.set(Calendar.SECOND, 0);
0632:                invoiceDateC.set(Calendar.MILLISECOND, 0);
0633:                Timestamp invoiceDateTime = new Timestamp(invoiceDateC
0634:                        .getTimeInMillis());
0635:                return ((invoiceDateTime.compareTo(nowTime)) > 0);
0636:            }
0637:
0638:            /**
0639:             * @see org.kuali.module.purap.service.PaymentRequestService#calculatePayDate(java.sql.Date, org.kuali.module.vendor.bo.PaymentTermType)
0640:             */
0641:            public Date calculatePayDate(Date invoiceDate, PaymentTermType terms) {
0642:                LOG.debug("calculatePayDate() started");
0643:                // calculate the invoice + processed calendar
0644:                Calendar invoicedDateCalendar = dateTimeService
0645:                        .getCalendar(invoiceDate);
0646:                Calendar processedDateCalendar = dateTimeService
0647:                        .getCurrentCalendar();
0648:                // add default number of days to processed
0649:                processedDateCalendar.add(Calendar.DAY_OF_MONTH,
0650:                        PurapConstants.PREQ_PAY_DATE_DEFAULT_NUMBER_OF_DAYS);
0651:
0652:                if (ObjectUtils.isNull(terms)
0653:                        || StringUtils.isEmpty(terms
0654:                                .getVendorPaymentTermsCode())) {
0655:                    invoicedDateCalendar
0656:                            .add(
0657:                                    Calendar.DAY_OF_MONTH,
0658:                                    PurapConstants.PREQ_PAY_DATE_EMPTY_TERMS_DEFAULT_DAYS);
0659:                    return returnLaterDate(invoicedDateCalendar,
0660:                            processedDateCalendar);
0661:                }
0662:
0663:                Integer discountDueNumber = terms.getVendorDiscountDueNumber();
0664:                Integer netDueNumber = terms.getVendorNetDueNumber();
0665:                if (ObjectUtils.isNotNull(discountDueNumber)) {
0666:                    String discountDueTypeDescription = terms
0667:                            .getVendorDiscountDueTypeDescription();
0668:                    paymentTermsDateCalculation(discountDueTypeDescription,
0669:                            invoicedDateCalendar, discountDueNumber);
0670:                } else if (ObjectUtils.isNotNull(netDueNumber)) {
0671:                    String netDueTypeDescription = terms
0672:                            .getVendorNetDueTypeDescription();
0673:                    paymentTermsDateCalculation(netDueTypeDescription,
0674:                            invoicedDateCalendar, netDueNumber);
0675:                } else {
0676:                    throw new RuntimeException(
0677:                            "Neither discount or net number were specified for this payment terms type");
0678:                }
0679:
0680:                // return the later date
0681:                return returnLaterDate(invoicedDateCalendar,
0682:                        processedDateCalendar);
0683:            }
0684:
0685:            /**
0686:             * Returns whichever date is later, the invoicedDateCalendar or the processedDateCalendar.
0687:             * 
0688:             * @param invoicedDateCalendar   One of the dates to be used in determining which date is later.
0689:             * @param processedDateCalendar  The other date to be used in determining which date is later.
0690:             * @return                       The date which is the later of the two given dates in the input parameters.
0691:             */
0692:            private Date returnLaterDate(Calendar invoicedDateCalendar,
0693:                    Calendar processedDateCalendar) {
0694:                if (invoicedDateCalendar.after(processedDateCalendar)) {
0695:                    return new Date(invoicedDateCalendar.getTimeInMillis());
0696:                } else {
0697:                    return new Date(processedDateCalendar.getTimeInMillis());
0698:                }
0699:            }
0700:
0701:            /**
0702:             * Calculates the paymentTermsDate given the dueTypeDescription, invoicedDateCalendar and
0703:             * the dueNumber.
0704:             * 
0705:             * @param dueTypeDescription    The due type description of the payment term.
0706:             * @param invoicedDateCalendar  The Calendar object of the invoice date.
0707:             * @param discountDueNumber     Either the vendorDiscountDueNumber or the vendorDiscountDueNumber of the payment term.
0708:             */
0709:            private void paymentTermsDateCalculation(String dueTypeDescription,
0710:                    Calendar invoicedDateCalendar, Integer dueNumber) {
0711:
0712:                if (StringUtils.equals(dueTypeDescription,
0713:                        PurapConstants.PREQ_PAY_DATE_DATE)) {
0714:                    // date specified set to date in next month
0715:                    invoicedDateCalendar.add(Calendar.MONTH, 1);
0716:                    invoicedDateCalendar.set(Calendar.DAY_OF_MONTH, dueNumber
0717:                            .intValue());
0718:                } else if (StringUtils.equals(
0719:                        PurapConstants.PREQ_PAY_DATE_DAYS, dueTypeDescription)) {
0720:                    // days specified go forward that number
0721:                    invoicedDateCalendar.add(Calendar.DAY_OF_MONTH, dueNumber
0722:                            .intValue());
0723:                } else {
0724:                    // improper string
0725:                    throw new RuntimeException(
0726:                            "missing payment terms description or not properly enterred on payment term maintenance doc");
0727:                }
0728:            }
0729:
0730:            /**
0731:             * @see org.kuali.module.purap.service.PaymentRequestService#calculatePaymentRequest(org.kuali.module.purap.document.PaymentRequestDocument, boolean)
0732:             */
0733:            public void calculatePaymentRequest(
0734:                    PaymentRequestDocument paymentRequest,
0735:                    boolean updateDiscount) {
0736:                LOG.debug("calculatePaymentRequest() started");
0737:
0738:                if (ObjectUtils.isNull(paymentRequest
0739:                        .getPaymentRequestPayDate())) {
0740:                    paymentRequest.setPaymentRequestPayDate(calculatePayDate(
0741:                            paymentRequest.getInvoiceDate(), paymentRequest
0742:                                    .getVendorPaymentTerms()));
0743:                }
0744:
0745:                if (updateDiscount) {
0746:                    calculateDiscount(paymentRequest);
0747:                }
0748:
0749:                distributeAccounting(paymentRequest);
0750:            }
0751:
0752:            /**
0753:             * Calculates the discount item for this paymentRequest.
0754:             * 
0755:             * @param paymentRequestDocument  The payment request document whose discount to be calculated.
0756:             */
0757:            private void calculateDiscount(
0758:                    PaymentRequestDocument paymentRequestDocument) {
0759:                PaymentRequestItem discountItem = findDiscountItem(paymentRequestDocument);
0760:                // find out if we really need the discount item
0761:                PaymentTermType pt = paymentRequestDocument
0762:                        .getVendorPaymentTerms();
0763:                if ((pt != null)
0764:                        && (pt.getVendorPaymentTermsPercent() != null)
0765:                        && (BigDecimal.ZERO.compareTo(pt
0766:                                .getVendorPaymentTermsPercent()) != 0)) {
0767:                    if (discountItem == null) {
0768:                        // set discountItem and add to items
0769:                        // this is probably not the best way of doing it but should work for now if we start excluding discount from below
0770:                        // we will need to manually add
0771:                        SpringContext.getBean(PurapService.class)
0772:                                .addBelowLineItems(paymentRequestDocument);
0773:                        discountItem = findDiscountItem(paymentRequestDocument);
0774:                    }
0775:                    // discount item should no longer be null, update if necessary
0776:                    if (discountItem.getExtendedPrice().isZero()) {
0777:                        KualiDecimal totalCost = paymentRequestDocument
0778:                                .getTotalDollarAmountAboveLineItems();
0779:                        BigDecimal discountAmount = pt
0780:                                .getVendorPaymentTermsPercent()
0781:                                .multiply(totalCost.bigDecimalValue())
0782:                                .multiply(
0783:                                        new BigDecimal(
0784:                                                PurapConstants.PREQ_DISCOUNT_MULT));
0785:                        // do we really need to set both, not positive, but probably won't hurt
0786:                        discountItem.setItemUnitPrice(discountAmount.setScale(
0787:                                2, KualiDecimal.ROUND_BEHAVIOR));
0788:                        discountItem.setExtendedPrice(new KualiDecimal(
0789:                                discountAmount));
0790:                    }
0791:                } else { // no discount
0792:                    if (discountItem != null) {
0793:                        paymentRequestDocument.getItems().remove(discountItem);
0794:                    }
0795:                }
0796:
0797:            }
0798:
0799:            /**
0800:             * Finds the discount item of the payment request document.
0801:             * 
0802:             * @param paymentRequestDocument  The payment request document to be used to find the discount item.
0803:             * @return                        The discount item if it exists.
0804:             */
0805:            private PaymentRequestItem findDiscountItem(
0806:                    PaymentRequestDocument paymentRequestDocument) {
0807:                PaymentRequestItem discountItem = null;
0808:                for (PaymentRequestItem preqItem : (List<PaymentRequestItem>) paymentRequestDocument
0809:                        .getItems()) {
0810:                    if (StringUtils
0811:                            .equals(
0812:                                    preqItem.getItemTypeCode(),
0813:                                    PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE)) {
0814:                        discountItem = preqItem;
0815:                        break;
0816:                    }
0817:                }
0818:                return discountItem;
0819:            }
0820:
0821:            /**
0822:             * Distributes accounts for a payment request document.
0823:             * 
0824:             * @param paymentRequestDocument
0825:             */
0826:            private void distributeAccounting(
0827:                    PaymentRequestDocument paymentRequestDocument) {
0828:                // update the account amounts before doing any distribution
0829:                SpringContext.getBean(PurapAccountingService.class)
0830:                        .updateAccountAmounts(paymentRequestDocument);
0831:
0832:                for (PaymentRequestItem item : (List<PaymentRequestItem>) paymentRequestDocument
0833:                        .getItems()) {
0834:                    KualiDecimal totalAmount = KualiDecimal.ZERO;
0835:                    List<PurApAccountingLine> distributedAccounts = null;
0836:                    List<SourceAccountingLine> summaryAccounts = null;
0837:
0838:                    // skip above the line
0839:                    if (item.getItemType().isItemTypeAboveTheLineIndicator()) {
0840:                        continue;
0841:                    }
0842:
0843:                    if ((item.getSourceAccountingLines().isEmpty())
0844:                            && (ObjectUtils.isNotNull(item.getExtendedPrice()))
0845:                            && (KualiDecimal.ZERO.compareTo(item
0846:                                    .getExtendedPrice()) != 0)) {
0847:                        if ((StringUtils
0848:                                .equals(
0849:                                        PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE,
0850:                                        item.getItemType().getItemTypeCode()))
0851:                                && (paymentRequestDocument.getGrandTotal() != null)
0852:                                && ((KualiDecimal.ZERO
0853:                                        .compareTo(paymentRequestDocument
0854:                                                .getGrandTotal()) != 0))) {
0855:
0856:                            totalAmount = paymentRequestDocument
0857:                                    .getGrandTotal();
0858:
0859:                            summaryAccounts = SpringContext.getBean(
0860:                                    PurapAccountingService.class)
0861:                                    .generateSummary(
0862:                                            paymentRequestDocument.getItems());
0863:
0864:                            distributedAccounts = SpringContext.getBean(
0865:                                    PurapAccountingService.class)
0866:                                    .generateAccountDistributionForProration(
0867:                                            summaryAccounts, totalAmount,
0868:                                            PurapConstants.PRORATION_SCALE,
0869:                                            PaymentRequestAccount.class);
0870:
0871:                        } else {
0872:
0873:                            PurchaseOrderItem poi = item.getPurchaseOrderItem();
0874:                            if ((poi != null)
0875:                                    && (poi.getSourceAccountingLines() != null)
0876:                                    && (!(poi.getSourceAccountingLines()
0877:                                            .isEmpty()))
0878:                                    && (poi.getExtendedPrice() != null)
0879:                                    && ((KualiDecimal.ZERO.compareTo(poi
0880:                                            .getExtendedPrice())) != 0)) {
0881:                                // use accounts from purchase order item matching this item
0882:                                // account list of current item is already empty
0883:                                item.generateAccountListFromPoItemAccounts(poi
0884:                                        .getSourceAccountingLines());
0885:                            } else {
0886:                                totalAmount = paymentRequestDocument
0887:                                        .getPurchaseOrderDocument()
0888:                                        .getTotalDollarAmountAboveLineItems();
0889:                                SpringContext
0890:                                        .getBean(PurapAccountingService.class)
0891:                                        .updateAccountAmounts(
0892:                                                paymentRequestDocument
0893:                                                        .getPurchaseOrderDocument());
0894:                                summaryAccounts = SpringContext
0895:                                        .getBean(PurapAccountingService.class)
0896:                                        .generateSummary(
0897:                                                PurApItemUtils
0898:                                                        .getAboveTheLineOnly(paymentRequestDocument
0899:                                                                .getPurchaseOrderDocument()
0900:                                                                .getItems()));
0901:                                distributedAccounts = SpringContext
0902:                                        .getBean(PurapAccountingService.class)
0903:                                        .generateAccountDistributionForProration(
0904:                                                summaryAccounts, totalAmount,
0905:                                                new Integer("6"),
0906:                                                PaymentRequestAccount.class);
0907:                            }
0908:
0909:                        }
0910:                        if (CollectionUtils.isNotEmpty(distributedAccounts)
0911:                                && CollectionUtils.isEmpty(item
0912:                                        .getSourceAccountingLines())) {
0913:                            item.setSourceAccountingLines(distributedAccounts);
0914:                        }
0915:                    }
0916:                    // update the item
0917:                    purapAccountingService.updateItemAccountAmounts(item);
0918:                }
0919:                // update again now that distribute is finished. (Note: we may not need this anymore now that I added updateItem line above
0920:                purapAccountingService
0921:                        .updateAccountAmounts(paymentRequestDocument);
0922:            }
0923:
0924:            /**
0925:             * @see org.kuali.module.purap.service.PaymentRequestService#addHoldOnPaymentRequest(org.kuali.module.purap.document.PaymentRequestDocument,
0926:             *      java.lang.String)
0927:             */
0928:            public void addHoldOnPaymentRequest(
0929:                    PaymentRequestDocument document, String note)
0930:                    throws Exception {
0931:                // save the note
0932:                Note noteObj = documentService.createNoteFromDocument(document,
0933:                        note);
0934:                documentService.addNoteToDocument(document, noteObj);
0935:                noteService.save(noteObj);
0936:
0937:                // retrieve and save with hold indicator set to true
0938:                PaymentRequestDocument preqDoc = getPaymentRequestByDocumentNumber(paymentRequestDao
0939:                        .getDocumentNumberByPaymentRequestId(document
0940:                                .getPurapDocumentIdentifier()));
0941:                preqDoc.setHoldIndicator(true);
0942:                preqDoc.setLastActionPerformedByUniversalUserId(GlobalVariables
0943:                        .getUserSession().getUniversalUser()
0944:                        .getPersonUniversalIdentifier());
0945:                saveDocumentWithoutValidation(preqDoc);
0946:
0947:                // must also save it on the incoming document
0948:                document.setHoldIndicator(true);
0949:                document
0950:                        .setLastActionPerformedByUniversalUserId(GlobalVariables
0951:                                .getUserSession().getUniversalUser()
0952:                                .getPersonUniversalIdentifier());
0953:            }
0954:
0955:            /**
0956:             * @see org.kuali.module.purap.service.PaymentRequestService#removeHoldOnPaymentRequest(org.kuali.module.purap.document.PaymentRequestDocument)
0957:             */
0958:            public void removeHoldOnPaymentRequest(
0959:                    PaymentRequestDocument document, String note)
0960:                    throws Exception {
0961:                // save the note
0962:                Note noteObj = documentService.createNoteFromDocument(document,
0963:                        note);
0964:                documentService.addNoteToDocument(document, noteObj);
0965:                noteService.save(noteObj);
0966:
0967:                // retrieve and save with hold indicator set to false
0968:                PaymentRequestDocument preqDoc = getPaymentRequestByDocumentNumber(paymentRequestDao
0969:                        .getDocumentNumberByPaymentRequestId(document
0970:                                .getPurapDocumentIdentifier()));
0971:                preqDoc.setHoldIndicator(false);
0972:                preqDoc.setLastActionPerformedByUniversalUserId(null);
0973:                saveDocumentWithoutValidation(preqDoc);
0974:
0975:                // must also save it on the incoming document
0976:                document.setHoldIndicator(false);
0977:                document.setLastActionPerformedByUniversalUserId(null);
0978:            }
0979:
0980:            /**
0981:             * @see org.kuali.module.purap.service.PaymentRequestService#canHoldPaymentRequest(org.kuali.module.purap.document.PaymentRequestDocument,
0982:             *      org.kuali.core.bo.user.UniversalUser)
0983:             */
0984:            public boolean canHoldPaymentRequest(
0985:                    PaymentRequestDocument document, UniversalUser user) {
0986:                boolean canHold = false;
0987:
0988:                String accountsPayableGroup = SpringContext
0989:                        .getBean(ParameterService.class)
0990:                        .getParameterValue(
0991:                                ParameterConstants.PURCHASING_DOCUMENT.class,
0992:                                PurapParameterConstants.Workgroups.WORKGROUP_ACCOUNTS_PAYABLE);
0993:
0994:                /*
0995:                 * The user is an approver of the document, The user is a member of the Accounts Payable group
0996:                 */
0997:                if (document.isHoldIndicator() == false
0998:                        && document.getPaymentRequestedCancelIndicator() == false
0999:                        && ((document.getDocumentHeader().hasWorkflowDocument() && (document
1000:                                .getDocumentHeader().getWorkflowDocument()
1001:                                .stateIsEnroute() && document
1002:                                .getDocumentHeader().getWorkflowDocument()
1003:                                .isApprovalRequested())) || (user
1004:                                .isMember(accountsPayableGroup) && document
1005:                                .getExtractedDate() == null))
1006:                        && (!PurapConstants.PaymentRequestStatuses.STATUSES_DISALLOWING_HOLD
1007:                                .contains(document.getStatusCode()))) {
1008:
1009:                    canHold = true;
1010:                }
1011:
1012:                return canHold;
1013:            }
1014:
1015:            /**
1016:             * @see org.kuali.module.purap.service.PaymentRequestService#canRemoveHoldPaymentRequest(org.kuali.module.purap.document.PaymentRequestDocument,
1017:             *      org.kuali.core.bo.user.UniversalUser)
1018:             */
1019:            public boolean canRemoveHoldPaymentRequest(
1020:                    PaymentRequestDocument document, UniversalUser user) {
1021:                boolean canRemoveHold = false;
1022:
1023:                String accountsPayableSupervisorGroup = SpringContext
1024:                        .getBean(ParameterService.class)
1025:                        .getParameterValue(
1026:                                ParameterConstants.PURCHASING_DOCUMENT.class,
1027:                                PurapParameterConstants.Workgroups.WORKGROUP_ACCOUNTS_PAYABLE_SUPERVISOR);
1028:
1029:                /*
1030:                 * The user is the person who put the preq on hold The user is a member of the AP Supervisor group
1031:                 */
1032:                if (document.isHoldIndicator()
1033:                        && (user
1034:                                .getPersonUniversalIdentifier()
1035:                                .equals(
1036:                                        document
1037:                                                .getLastActionPerformedByUniversalUserId()) || user
1038:                                .isMember(accountsPayableSupervisorGroup))
1039:                        && (!PurapConstants.PaymentRequestStatuses.STATUSES_DISALLOWING_REMOVE_HOLD
1040:                                .contains(document.getStatusCode()))) {
1041:
1042:                    canRemoveHold = true;
1043:                }
1044:                return canRemoveHold;
1045:            }
1046:
1047:            /**
1048:             * @see org.kuali.module.purap.service.PaymentRequestService#addHoldOnPaymentRequest(org.kuali.module.purap.document.PaymentRequestDocument,
1049:             *      java.lang.String)
1050:             */
1051:            public void requestCancelOnPaymentRequest(
1052:                    PaymentRequestDocument document, String note)
1053:                    throws Exception {
1054:                // save the note
1055:                Note noteObj = documentService.createNoteFromDocument(document,
1056:                        note);
1057:                documentService.addNoteToDocument(document, noteObj);
1058:                noteService.save(noteObj);
1059:
1060:                // retrieve and save with hold indicator set to true
1061:                PaymentRequestDocument preqDoc = getPaymentRequestByDocumentNumber(paymentRequestDao
1062:                        .getDocumentNumberByPaymentRequestId(document
1063:                                .getPurapDocumentIdentifier()));
1064:                preqDoc.setPaymentRequestedCancelIndicator(true);
1065:                preqDoc.setLastActionPerformedByUniversalUserId(GlobalVariables
1066:                        .getUserSession().getUniversalUser()
1067:                        .getPersonUniversalIdentifier());
1068:                preqDoc
1069:                        .setAccountsPayableRequestCancelIdentifier(GlobalVariables
1070:                                .getUserSession().getUniversalUser()
1071:                                .getPersonUniversalIdentifier());
1072:                saveDocumentWithoutValidation(preqDoc);
1073:
1074:                // must also save it on the incoming document
1075:                document.setPaymentRequestedCancelIndicator(true);
1076:                document
1077:                        .setLastActionPerformedByUniversalUserId(GlobalVariables
1078:                                .getUserSession().getUniversalUser()
1079:                                .getPersonUniversalIdentifier());
1080:                document
1081:                        .setAccountsPayableRequestCancelIdentifier(GlobalVariables
1082:                                .getUserSession().getUniversalUser()
1083:                                .getPersonUniversalIdentifier());
1084:            }
1085:
1086:            /**
1087:             * @see org.kuali.module.purap.service.PaymentRequestService#removeHoldOnPaymentRequest(org.kuali.module.purap.document.PaymentRequestDocument)
1088:             */
1089:            public void removeRequestCancelOnPaymentRequest(
1090:                    PaymentRequestDocument document, String note)
1091:                    throws Exception {
1092:                // save the note
1093:                Note noteObj = documentService.createNoteFromDocument(document,
1094:                        note);
1095:                documentService.addNoteToDocument(document, noteObj);
1096:                noteService.save(noteObj);
1097:
1098:                // retrieve and save with hold indicator set to false
1099:                PaymentRequestDocument preqDoc = getPaymentRequestByDocumentNumber(paymentRequestDao
1100:                        .getDocumentNumberByPaymentRequestId(document
1101:                                .getPurapDocumentIdentifier()));
1102:                clearRequestCancelFields(preqDoc);
1103:                saveDocumentWithoutValidation(preqDoc);
1104:
1105:                // must also save it on the incoming document
1106:                clearRequestCancelFields(document);
1107:            }
1108:
1109:            /**
1110:             * Clears the request cancel fields.
1111:             * 
1112:             * @param document  The payment request document whose request cancel fields to be cleared.
1113:             */
1114:            private void clearRequestCancelFields(
1115:                    PaymentRequestDocument document) {
1116:                document.setPaymentRequestedCancelIndicator(false);
1117:                document.setLastActionPerformedByUniversalUserId(null);
1118:                document.setAccountsPayableRequestCancelIdentifier(null);
1119:            }
1120:
1121:            /**
1122:             * @see org.kuali.module.purap.service.PaymentRequestService#isExtracted(org.kuali.module.purap.document.PaymentRequestDocument)
1123:             */
1124:            public boolean isExtracted(PaymentRequestDocument document) {
1125:                return (ObjectUtils.isNull(document.getExtractedDate()) ? false
1126:                        : true);
1127:            }
1128:
1129:            /**
1130:             * @see org.kuali.module.purap.service.PaymentRequestService#canHoldPaymentRequest(org.kuali.module.purap.document.PaymentRequestDocument,
1131:             *      org.kuali.core.bo.user.UniversalUser)
1132:             */
1133:            public boolean canUserRequestCancelOnPaymentRequest(
1134:                    PaymentRequestDocument document, UniversalUser user) {
1135:
1136:                /*
1137:                 * The user is an approver of the document,
1138:                 */
1139:                if (document.getPaymentRequestedCancelIndicator() == false
1140:                        && document.isHoldIndicator() == false
1141:                        && document.getExtractedDate() == null
1142:                        && (document.getDocumentHeader().hasWorkflowDocument() && (document
1143:                                .getDocumentHeader().getWorkflowDocument()
1144:                                .stateIsEnroute() && document
1145:                                .getDocumentHeader().getWorkflowDocument()
1146:                                .isApprovalRequested()))
1147:                        && (!PurapConstants.PaymentRequestStatuses.STATUSES_DISALLOWING_REQUEST_CANCEL
1148:                                .contains(document.getStatusCode()))) {
1149:                    return true;
1150:                }
1151:                return false;
1152:            }
1153:
1154:            /**
1155:             * This method determines if a user has permission to remove a request for cancel on a payment request document.
1156:             * 
1157:             * @see org.kuali.module.purap.service.PaymentRequestService#canRemoveHoldPaymentRequest(org.kuali.module.purap.document.PaymentRequestDocument,
1158:             *      org.kuali.core.bo.user.UniversalUser)
1159:             */
1160:            public boolean canUserRemoveRequestCancelOnPaymentRequest(
1161:                    PaymentRequestDocument document, UniversalUser user) {
1162:                String accountsPayableSupervisorGroup = SpringContext
1163:                        .getBean(ParameterService.class)
1164:                        .getParameterValue(
1165:                                ParameterConstants.PURCHASING_DOCUMENT.class,
1166:                                PurapParameterConstants.Workgroups.WORKGROUP_ACCOUNTS_PAYABLE_SUPERVISOR);
1167:
1168:                /*
1169:                 * The user is the person who requested a cancel on the preq The user is a member of the AP Supervisor group
1170:                 */
1171:                if (document.getPaymentRequestedCancelIndicator()
1172:                        && (user
1173:                                .getPersonUniversalIdentifier()
1174:                                .equals(
1175:                                        document
1176:                                                .getLastActionPerformedByUniversalUserId()) || user
1177:                                .isMember(accountsPayableSupervisorGroup))
1178:                        && (!PurapConstants.PaymentRequestStatuses.STATUSES_DISALLOWING_REQUEST_CANCEL
1179:                                .contains(document.getStatusCode()))) {
1180:                    return true;
1181:                }
1182:                return false;
1183:            }
1184:
1185:            /**
1186:             * @see org.kuali.module.purap.service.PaymentRequestService#cancelExtractedPaymentRequest(org.kuali.module.purap.document.PaymentRequestDocument, java.lang.String)
1187:             */
1188:            public void cancelExtractedPaymentRequest(
1189:                    PaymentRequestDocument paymentRequest, String note) {
1190:                LOG.debug("cancelExtractedPaymentRequest() started");
1191:                if (PaymentRequestStatuses.CANCELLED_STATUSES
1192:                        .contains(paymentRequest.getStatusCode())) {
1193:                    LOG.debug("cancelExtractedPaymentRequest() ended");
1194:                    return;
1195:                }
1196:
1197:                try {
1198:                    Note cancelNote = documentService.createNoteFromDocument(
1199:                            paymentRequest, note);
1200:                    documentService.addNoteToDocument(paymentRequest,
1201:                            cancelNote);
1202:                    SpringContext.getBean(NoteService.class).save(cancelNote);
1203:                } catch (Exception e) {
1204:                    throw new RuntimeException(
1205:                            PurapConstants.REQ_UNABLE_TO_CREATE_NOTE + " " + e);
1206:                }
1207:
1208:                //cancel extracted should not reopen PO
1209:                paymentRequest.setReopenPurchaseOrderIndicator(false);
1210:
1211:                SpringContext.getBean(AccountsPayableService.class)
1212:                        .cancelAccountsPayableDocument(paymentRequest, ""); // Performs save, so no explicit save is necessary
1213:                LOG.debug("cancelExtractedPaymentRequest() PREQ "
1214:                        + paymentRequest.getPurapDocumentIdentifier()
1215:                        + " Cancelled Without Workflow");
1216:                LOG.debug("cancelExtractedPaymentRequest() ended");
1217:            }
1218:
1219:            /**
1220:             * @see org.kuali.module.purap.service.PaymentRequestService#resetExtractedPaymentRequest(org.kuali.module.purap.document.PaymentRequestDocument, java.lang.String)
1221:             */
1222:            public void resetExtractedPaymentRequest(
1223:                    PaymentRequestDocument paymentRequest, String note) {
1224:                LOG.debug("resetExtractedPaymentRequest() started");
1225:                if (PaymentRequestStatuses.CANCELLED_STATUSES
1226:                        .contains(paymentRequest.getStatusCode())) {
1227:                    LOG.debug("resetExtractedPaymentRequest() ended");
1228:                    return;
1229:                }
1230:                paymentRequest.setExtractedDate(null);
1231:                paymentRequest.setPaymentPaidDate(null);
1232:                String noteText = "This Payment Request is being reset for extraction by PDP "
1233:                        + note;
1234:                try {
1235:                    Note resetNote = documentService.createNoteFromDocument(
1236:                            paymentRequest, noteText);
1237:                    documentService
1238:                            .addNoteToDocument(paymentRequest, resetNote);
1239:                    SpringContext.getBean(NoteService.class).save(resetNote);
1240:                } catch (Exception e) {
1241:                    throw new RuntimeException(
1242:                            PurapConstants.REQ_UNABLE_TO_CREATE_NOTE + " " + e);
1243:                }
1244:                this .saveDocumentWithoutValidation(paymentRequest);
1245:                LOG.debug("resetExtractedPaymentRequest() PREQ "
1246:                        + paymentRequest.getPurapDocumentIdentifier()
1247:                        + " Reset from Extracted status");
1248:            }
1249:
1250:            /**
1251:             * @see org.kuali.module.purap.service.PaymentRequestService#populatePaymentRequest(org.kuali.module.purap.document.PaymentRequestDocument)
1252:             */
1253:            public void populatePaymentRequest(
1254:                    PaymentRequestDocument paymentRequestDocument) {
1255:
1256:                PurchaseOrderDocument purchaseOrderDocument = paymentRequestDocument
1257:                        .getPurchaseOrderDocument();
1258:
1259:                // make a call to search for expired/closed accounts
1260:                HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList = SpringContext
1261:                        .getBean(AccountsPayableService.class)
1262:                        .getExpiredOrClosedAccountList(paymentRequestDocument);
1263:
1264:                paymentRequestDocument.populatePaymentRequestFromPurchaseOrder(
1265:                        purchaseOrderDocument, expiredOrClosedAccountList);
1266:
1267:                paymentRequestDocument
1268:                        .getDocumentHeader()
1269:                        .setFinancialDocumentDescription(
1270:                                createPreqDocumentDescription(
1271:                                        paymentRequestDocument
1272:                                                .getPurchaseOrderIdentifier(),
1273:                                        paymentRequestDocument.getVendorName()));
1274:
1275:                // write a note for expired/closed accounts if any exist and add a message stating there were expired/closed accounts at the
1276:                // top of the document
1277:                SpringContext.getBean(AccountsPayableService.class)
1278:                        .generateExpiredOrClosedAccountNote(
1279:                                paymentRequestDocument,
1280:                                expiredOrClosedAccountList);
1281:
1282:                // set indicator so a message is displayed for accounts that were replaced due to expired/closed status
1283:                if (!expiredOrClosedAccountList.isEmpty()) {
1284:                    paymentRequestDocument
1285:                            .setContinuationAccountIndicator(true);
1286:                }
1287:
1288:                // add discount item
1289:                calculateDiscount(paymentRequestDocument);
1290:                // distribute accounts (i.e. proration)
1291:                distributeAccounting(paymentRequestDocument);
1292:
1293:            }
1294:
1295:            /**
1296:             * A helper method to create the description for the payment request document.
1297:             * 
1298:             * @param purchaseOrderIdentifier  The purchase order identifier to be used as part of the description.
1299:             * @param vendorName               The vendor name to be used as part of the description.
1300:             * @return                         The resulting description string for the payment request document.
1301:             */
1302:            private String createPreqDocumentDescription(
1303:                    Integer purchaseOrderIdentifier, String vendorName) {
1304:                StringBuffer descr = new StringBuffer("");
1305:                descr.append("PO: ");
1306:                descr.append(purchaseOrderIdentifier);
1307:                descr.append(" Vendor: ");
1308:                descr.append(StringUtils.trimToEmpty(vendorName));
1309:
1310:                int noteTextMaxLength = SpringContext.getBean(
1311:                        DataDictionaryService.class).getAttributeMaxLength(
1312:                        DocumentHeader.class,
1313:                        KFSPropertyConstants.FINANCIAL_DOCUMENT_DESCRIPTION)
1314:                        .intValue();
1315:                if (noteTextMaxLength >= descr.length()) {
1316:                    return descr.toString();
1317:                } else {
1318:                    return descr.toString().substring(0, noteTextMaxLength);
1319:                }
1320:            }
1321:
1322:            /**
1323:             * @see org.kuali.module.purap.service.PaymentRequestService#populateAndSavePaymentRequest(org.kuali.module.purap.document.PaymentRequestDocument)
1324:             */
1325:            public void populateAndSavePaymentRequest(
1326:                    PaymentRequestDocument preq) throws WorkflowException {
1327:                try {
1328:                    preq
1329:                            .setStatusCode(PurapConstants.PaymentRequestStatuses.IN_PROCESS);
1330:                    documentService.saveDocument(preq,
1331:                            ContinueAccountsPayableEvent.class);
1332:                } catch (ValidationException ve) {
1333:                    preq
1334:                            .setStatusCode(PurapConstants.PaymentRequestStatuses.INITIATE);
1335:                } catch (WorkflowException we) {
1336:                    preq
1337:                            .setStatusCode(PurapConstants.PaymentRequestStatuses.INITIATE);
1338:                    String errorMsg = "Error saving document # "
1339:                            + preq.getDocumentHeader().getDocumentNumber()
1340:                            + " " + we.getMessage();
1341:                    LOG.error(errorMsg, we);
1342:                    throw new RuntimeException(errorMsg, we);
1343:                }
1344:            }
1345:
1346:            /**
1347:             * @see org.kuali.module.purap.service.PaymentRequestService#deleteSummaryAccounts(java.lang.Integer)
1348:             */
1349:            public void deleteSummaryAccounts(Integer purapDocumentIdentifier) {
1350:                paymentRequestDao
1351:                        .deleteSummaryAccounts(purapDocumentIdentifier);
1352:            }
1353:
1354:            /**
1355:             * If the full document entry has been completed and the status of the related purchase order document is closed, return true,
1356:             * otherwise return false.
1357:             * 
1358:             * @param apDoc  The AccountsPayableDocument to be determined whether its purchase order should be reversed.
1359:             * @return       boolean true if the purchase order should be reversed.
1360:             * @see          org.kuali.module.purap.service.AccountsPayableDocumentSpecificService#shouldPurchaseOrderBeReversed
1361:             *               (org.kuali.module.purap.document.AccountsPayableDocument)
1362:             */
1363:            public boolean shouldPurchaseOrderBeReversed(
1364:                    AccountsPayableDocument apDoc) {
1365:                PurchaseOrderDocument po = apDoc.getPurchaseOrderDocument();
1366:                if (ObjectUtils.isNull(po)) {
1367:                    throw new RuntimeException(
1368:                            "po should never be null on PREQ");
1369:                }
1370:                // if past full entry and already closed return true
1371:                if (purapService.isFullDocumentEntryCompleted(apDoc)
1372:                        && StringUtils.equalsIgnoreCase(
1373:                                PurapConstants.PurchaseOrderStatuses.CLOSED, po
1374:                                        .getStatusCode())) {
1375:                    return true;
1376:                }
1377:                return false;
1378:            }
1379:
1380:            /**
1381:             * @see org.kuali.module.purap.service.AccountsPayableDocumentSpecificService#getUniversalUserForCancel(org.kuali.module.purap.document.AccountsPayableDocument)
1382:             */
1383:            public UniversalUser getUniversalUserForCancel(
1384:                    AccountsPayableDocument apDoc) {
1385:                PaymentRequestDocument preqDoc = (PaymentRequestDocument) apDoc;
1386:                UniversalUser user = null;
1387:                if (preqDoc.isPaymentRequestedCancelIndicator()) {
1388:                    user = preqDoc.getLastActionPerformedByUser();
1389:                }
1390:                return user;
1391:            }
1392:
1393:            /**
1394:             * @see org.kuali.module.purap.service.AccountsPayableDocumentSpecificService#takePurchaseOrderCancelAction(org.kuali.module.purap.document.AccountsPayableDocument)
1395:             */
1396:            public void takePurchaseOrderCancelAction(
1397:                    AccountsPayableDocument apDoc) {
1398:                PaymentRequestDocument preqDocument = (PaymentRequestDocument) apDoc;
1399:                if (preqDocument.isReopenPurchaseOrderIndicator()) {
1400:                    String docType = PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_REOPEN_DOCUMENT;
1401:                    purchaseOrderService
1402:                            .createAndRoutePotentialChangeDocument(
1403:                                    preqDocument.getPurchaseOrderDocument()
1404:                                            .getDocumentNumber(),
1405:                                    docType,
1406:                                    "reopened by Credit Memo "
1407:                                            + apDoc
1408:                                                    .getPurapDocumentIdentifier()
1409:                                            + "cancel",
1410:                                    new ArrayList(),
1411:                                    PurapConstants.PurchaseOrderStatuses.PENDING_REOPEN);
1412:                }
1413:            }
1414:
1415:            /**
1416:             * @see org.kuali.module.purap.service.AccountsPayableDocumentSpecificService#updateStatusByNode(java.lang.String,
1417:             *      org.kuali.module.purap.document.AccountsPayableDocument)
1418:             */
1419:            public String updateStatusByNode(String currentNodeName,
1420:                    AccountsPayableDocument apDoc) {
1421:                return updateStatusByNode(currentNodeName,
1422:                        (PaymentRequestDocument) apDoc);
1423:            }
1424:
1425:            /**
1426:             * Updates the status of the payment request document.
1427:             * 
1428:             * @param currentNodeName  The current node name.
1429:             * @param preqDoc          The payment request document whose status to be updated.
1430:             * @return                 The canceled status code.
1431:             */
1432:            private String updateStatusByNode(String currentNodeName,
1433:                    PaymentRequestDocument preqDoc) {
1434:                // remove request cancel if necessary
1435:                clearRequestCancelFields(preqDoc);
1436:
1437:                // update the status on the document
1438:
1439:                String cancelledStatusCode = "";
1440:                if (StringUtils.isEmpty(currentNodeName)) {
1441:                    // if empty probably not coming from workflow
1442:                    cancelledStatusCode = PurapConstants.PaymentRequestStatuses.CANCELLED_POST_AP_APPROVE;
1443:                } else {
1444:                    NodeDetails currentNode = NodeDetailEnum
1445:                            .getNodeDetailEnumByName(currentNodeName);
1446:                    if (ObjectUtils.isNotNull(currentNode)) {
1447:                        cancelledStatusCode = currentNode
1448:                                .getDisapprovedStatusCode();
1449:                    }
1450:                }
1451:
1452:                if (StringUtils.isNotBlank(cancelledStatusCode)) {
1453:                    purapService.updateStatus(preqDoc, cancelledStatusCode);
1454:                    saveDocumentWithoutValidation(preqDoc);
1455:                    return cancelledStatusCode;
1456:                } else {
1457:                    logAndThrowRuntimeException("No status found to set for document being disapproved in node '"
1458:                            + currentNodeName + "'");
1459:                }
1460:                return cancelledStatusCode;
1461:            }
1462:
1463:            /**
1464:             * @see org.kuali.module.purap.service.PaymentRequestService#markPaid(org.kuali.module.purap.document.PaymentRequestDocument,
1465:             *      java.sql.Date)
1466:             */
1467:            public void markPaid(PaymentRequestDocument pr, Date processDate) {
1468:                LOG.debug("markPaid() started");
1469:
1470:                pr.setPaymentPaidDate(processDate);
1471:                saveDocumentWithoutValidation(pr);
1472:            }
1473:
1474:            /**
1475:             * @see org.kuali.module.purap.service.PaymentRequestService#hasDiscountItem(org.kuali.module.purap.document.PaymentRequestDocument)
1476:             */
1477:            public boolean hasDiscountItem(PaymentRequestDocument preq) {
1478:                return ObjectUtils.isNotNull(findDiscountItem(preq));
1479:            }
1480:
1481:            /**
1482:             * @see org.kuali.module.purap.service.AccountsPayableDocumentSpecificService#poItemEligibleForAp(org.kuali.module.purap.document.AccountsPayableDocument, org.kuali.module.purap.bo.PurchaseOrderItem)
1483:             */
1484:            public boolean poItemEligibleForAp(AccountsPayableDocument apDoc,
1485:                    PurchaseOrderItem poi) {
1486:                if (ObjectUtils.isNull(poi)) {
1487:                    throw new RuntimeException(
1488:                            "item null in purchaseOrderItemEligibleForPayment ... this should never happen");
1489:                }
1490:                // if the po item is not active... skip it
1491:                if (!poi.isItemActiveIndicator()) {
1492:                    return false;
1493:                }
1494:
1495:                ItemType poiType = poi.getItemType();
1496:
1497:                if (poiType.isQuantityBasedGeneralLedgerIndicator()) {
1498:                    if (poi.getItemQuantity().isGreaterThan(
1499:                            poi.getItemInvoicedTotalQuantity())) {
1500:                        return true;
1501:                    }
1502:                    return false;
1503:                } else { // not quantity based
1504:                    if (poi.getItemOutstandingEncumberedAmount().isGreaterThan(
1505:                            KualiDecimal.ZERO)) {
1506:                        return true;
1507:                    }
1508:                    return false;
1509:                }
1510:            }
1511:
1512:            /**
1513:             * Records the specified error message into the Log file and throws a runtime exception.
1514:             * 
1515:             * @param errorMessage the error message to be logged.
1516:             */
1517:            protected void logAndThrowRuntimeException(String errorMessage) {
1518:                this .logAndThrowRuntimeException(errorMessage, null);
1519:            }
1520:
1521:            /**
1522:             * Records the specified error message into the Log file and throws the specified runtime exception.
1523:             * 
1524:             * @param errorMessage the specified error message.
1525:             * @param e the specified runtime exception.
1526:             */
1527:            protected void logAndThrowRuntimeException(String errorMessage,
1528:                    Exception e) {
1529:                if (ObjectUtils.isNotNull(e)) {
1530:                    LOG.error(errorMessage, e);
1531:                    throw new RuntimeException(errorMessage, e);
1532:                } else {
1533:                    LOG.error(errorMessage);
1534:                    throw new RuntimeException(errorMessage);
1535:                }
1536:            }
1537:
1538:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.