001: /*
002: * Copyright 2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.opensource.org/licenses/ecl1.php
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.kuali.module.purap.rules;
017:
018: import static org.kuali.kfs.KFSConstants.GL_CREDIT_CODE;
019:
020: import java.util.List;
021:
022: import org.apache.commons.lang.StringUtils;
023: import org.kuali.core.document.Document;
024: import org.kuali.core.exceptions.ValidationException;
025: import org.kuali.core.rule.event.ApproveDocumentEvent;
026: import org.kuali.core.util.GlobalVariables;
027: import org.kuali.core.util.ObjectUtils;
028: import org.kuali.kfs.KFSConstants;
029: import org.kuali.kfs.bo.AccountingLine;
030: import org.kuali.kfs.bo.GeneralLedgerPendingEntry;
031: import org.kuali.kfs.context.SpringContext;
032: import org.kuali.kfs.document.AccountingDocument;
033: import org.kuali.module.purap.PurapKeyConstants;
034: import org.kuali.module.purap.PurapPropertyConstants;
035: import org.kuali.module.purap.PurapWorkflowConstants;
036: import org.kuali.module.purap.PurapConstants.PODocumentsStrings;
037: import org.kuali.module.purap.PurapConstants.PREQDocumentsStrings;
038: import org.kuali.module.purap.PurapConstants.PaymentRequestStatuses;
039: import org.kuali.module.purap.PurapConstants.PurapDocTypeCodes;
040: import org.kuali.module.purap.PurapConstants.PurchaseOrderStatuses;
041: import org.kuali.module.purap.document.PaymentRequestDocument;
042: import org.kuali.module.purap.document.PurchaseOrderDocument;
043: import org.kuali.module.purap.service.PaymentRequestService;
044: import org.kuali.module.purap.service.PurapGeneralLedgerService;
045: import org.kuali.module.purap.service.PurchaseOrderService;
046:
047: /**
048: * Rules for Purchase Order Close Document creation.
049: */
050: public class PurchaseOrderCloseDocumentRule extends
051: PurchasingDocumentRuleBase {
052:
053: /**
054: * @see org.kuali.module.financial.rules.TransactionalDocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.core.document.Document)
055: */
056: @Override
057: protected boolean processCustomRouteDocumentBusinessRules(
058: Document document) {
059: boolean isValid = true;
060: PurchaseOrderDocument poDocument = (PurchaseOrderDocument) document;
061: return isValid &= processValidation(poDocument);
062: }
063:
064: /**
065: * @see org.kuali.core.rules.DocumentRuleBase#processCustomSaveDocumentBusinessRules(org.kuali.core.document.Document)
066: */
067: @Override
068: protected boolean processCustomSaveDocumentBusinessRules(
069: Document document) {
070: boolean isValid = true;
071: PurchaseOrderDocument poDocument = (PurchaseOrderDocument) document;
072: return isValid &= processValidation(poDocument);
073: }
074:
075: /**
076: * @see org.kuali.core.rules.DocumentRuleBase#processCustomApproveDocumentBusinessRules(org.kuali.core.rule.event.ApproveDocumentEvent)
077: */
078: @Override
079: protected boolean processCustomApproveDocumentBusinessRules(
080: ApproveDocumentEvent approveEvent) {
081: boolean isValid = true;
082: PurchaseOrderDocument poDocument = (PurchaseOrderDocument) approveEvent
083: .getDocument();
084: return isValid;
085: }
086:
087: /**
088: * Central method to control the processing of rule checks. Checks that the purchase order document is not null, that it is in
089: * the correct status, and delegates further rule checking.
090: *
091: * @param document A PurchaseOrderDocument. (Not a PurchaseOrderCloseDocument at this point.)
092: * @return True if the document passes all the validations.
093: */
094: public boolean processValidation(PurchaseOrderDocument document) {
095: boolean valid = true;
096: // Check that the PO is not null
097: if (ObjectUtils.isNull(document)) {
098: throw new ValidationException(
099: "Purchase Order Close document was null on validation.");
100: } else {
101: PurchaseOrderDocument currentPO = SpringContext.getBean(
102: PurchaseOrderService.class)
103: .getCurrentPurchaseOrder(
104: document.getPurapDocumentIdentifier());
105:
106: // The PO must be in OPEN status.
107: if (!StringUtils.equalsIgnoreCase(
108: currentPO.getStatusCode(),
109: PurchaseOrderStatuses.PENDING_CLOSE)
110: && !StringUtils.equalsIgnoreCase(currentPO
111: .getStatusCode(),
112: PurchaseOrderStatuses.OPEN)) {
113: valid = false;
114: GlobalVariables
115: .getErrorMap()
116: .putError(
117: PurapPropertyConstants.STATUS_CODE,
118: PurapKeyConstants.ERROR_PURCHASE_ORDER_STATUS_NOT_REQUIRED_STATUS,
119: PurchaseOrderStatuses.OPEN);
120: } else {
121: valid &= processPaymentRequestRules(document);
122: }
123: }
124: return valid;
125: }
126:
127: /**
128: * Processes validation rules having to do with any payment requests that the given purchase order may have. Specifically,
129: * validates that at least one payment request exists, and makes furthur checks about the status of such payment requests.
130: *
131: * @param document A PurchaseOrderDocument
132: * @return True if the document passes all the validations.
133: */
134: public boolean processPaymentRequestRules(
135: PurchaseOrderDocument document) {
136: boolean valid = true;
137: // The PO must have at least one PREQ against it.
138: Integer poDocId = document.getPurapDocumentIdentifier();
139: List<PaymentRequestDocument> pReqs = SpringContext.getBean(
140: PaymentRequestService.class)
141: .getPaymentRequestsByPurchaseOrderId(poDocId);
142: if (ObjectUtils.isNotNull(pReqs)) {
143: if (pReqs.size() == 0) {
144: valid = false;
145: GlobalVariables
146: .getErrorMap()
147: .putError(
148: PurapPropertyConstants.PURAP_DOC_ID,
149: PurapKeyConstants.ERROR_PURCHASE_ORDER_CLOSE_NO_PREQ,
150: PODocumentsStrings.OPEN_STATUS);
151: } else {
152: boolean checkInProcess = true;
153: boolean hasInProcess = false;
154:
155: for (PaymentRequestDocument pReq : pReqs) {
156: // skip exception docs
157: if (pReq.getDocumentHeader().getWorkflowDocument()
158: .stateIsException()) {
159: continue;
160: }
161: // NOTE for below, this could/should be changed to look at the first route level after full entry instead of
162: // being tied to AwaitingFiscal (in case full entry is moved)
163: // look for a doc that is currently routing, that will probably be the one that called this close if called from
164: // preq (with close po box)
165: if (StringUtils
166: .equalsIgnoreCase(
167: pReq.getStatusCode(),
168: PaymentRequestStatuses.AWAITING_FISCAL_REVIEW)
169: && !StringUtils
170: .equalsIgnoreCase(
171: pReq
172: .getDocumentHeader()
173: .getWorkflowDocument()
174: .getCurrentRouteNodeNames(),
175: PurapWorkflowConstants.PaymentRequestDocument.NodeDetailEnum.ACCOUNT_REVIEW
176: .getName())) {
177: // terminate the search since this close doc is probably being called by this doc, a doc should never be In
178: // Process and enroute in any other case
179: checkInProcess = false;
180: break;
181: }
182: if (StringUtils.equalsIgnoreCase(pReq
183: .getStatusCode(),
184: PaymentRequestStatuses.IN_PROCESS)) {
185: hasInProcess = true;
186: }
187: }
188: if (checkInProcess && hasInProcess) {
189: valid = false;
190: GlobalVariables
191: .getErrorMap()
192: .putError(
193: PurapPropertyConstants.PURAP_DOC_ID,
194: PurapKeyConstants.ERROR_PURCHASE_ORDER_CLOSE_PREQ_IN_PROCESS,
195: PREQDocumentsStrings.IN_PROCESS);
196: }
197: }
198: }
199:
200: return valid;
201: }
202:
203: /**
204: * @see org.kuali.module.purap.rules.PurapAccountingDocumentRuleBase#customizeExplicitGeneralLedgerPendingEntry(org.kuali.kfs.document.AccountingDocument,
205: * org.kuali.kfs.bo.AccountingLine, org.kuali.kfs.bo.GeneralLedgerPendingEntry)
206: */
207: @Override
208: protected void customizeExplicitGeneralLedgerPendingEntry(
209: AccountingDocument accountingDocument,
210: AccountingLine accountingLine,
211: GeneralLedgerPendingEntry explicitEntry) {
212: super .customizeExplicitGeneralLedgerPendingEntry(
213: accountingDocument, accountingLine, explicitEntry);
214: PurchaseOrderDocument po = (PurchaseOrderDocument) accountingDocument;
215:
216: SpringContext.getBean(PurapGeneralLedgerService.class)
217: .customizeGeneralLedgerPendingEntry(po, accountingLine,
218: explicitEntry, po.getPurapDocumentIdentifier(),
219: GL_CREDIT_CODE, PurapDocTypeCodes.PO_DOCUMENT,
220: true);
221:
222: // don't think i should have to override this, but default isn't getting the right PO doc
223: explicitEntry
224: .setFinancialDocumentTypeCode(PurapDocTypeCodes.PO_CLOSE_DOCUMENT);
225: explicitEntry
226: .setFinancialDocumentApprovedCode(KFSConstants.PENDING_ENTRY_APPROVED_STATUS_CODE.APPROVED);
227: }
228: }
|