001: /*
002: * Copyright 2006-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:
017: package org.kuali.module.gl.document;
018:
019: import java.util.ArrayList;
020: import java.util.Collections;
021: import java.util.Iterator;
022: import java.util.LinkedHashMap;
023: import java.util.List;
024:
025: import org.kuali.core.document.AmountTotaling;
026: import org.kuali.core.document.TransactionalDocumentBase;
027: import org.kuali.core.service.BusinessObjectService;
028: import org.kuali.core.service.DateTimeService;
029: import org.kuali.core.util.KualiDecimal;
030: import org.kuali.kfs.KFSConstants;
031: import org.kuali.kfs.KFSPropertyConstants;
032: import org.kuali.kfs.context.SpringContext;
033: import org.kuali.module.gl.bo.CorrectionChangeGroup;
034: import org.kuali.module.gl.bo.OriginEntryFull;
035: import org.kuali.module.gl.bo.OriginEntryGroup;
036: import org.kuali.module.gl.bo.OriginEntrySource;
037: import org.kuali.module.gl.service.CorrectionDocumentService;
038: import org.kuali.module.gl.service.OriginEntryGroupService;
039: import org.kuali.module.gl.service.OriginEntryService;
040: import org.kuali.module.gl.service.ReportService;
041: import org.kuali.module.gl.service.ScrubberService;
042:
043: import edu.iu.uis.eden.clientapp.vo.DocumentRouteLevelChangeVO;
044:
045: /**
046: *
047: * The General Ledger Correction Document, a document that allows editing and processing of
048: * origin entry groups and the origin entries within them.
049: *
050: */
051: public class CorrectionDocument extends TransactionalDocumentBase
052: implements AmountTotaling {
053: private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger
054: .getLogger(CorrectionDocument.class);
055:
056: private String correctionTypeCode; // CorrectionDocumentService.CORRECTION_TYPE_MANUAL or
057: // CorrectionDocumentService.CORRECTION_TYPE_CRITERIA or
058: // CorrectionDocumentService.CORRECTION_TYPE_REMOVE_GROUP_FROM_PROCESSING
059: private boolean correctionSelection; // false if all input rows should be in the output, true if only selected rows should be
060: // in the output
061: private boolean correctionFileDelete; // false if the file should be processed by scrubber, true if the file should not be
062: // processed by scrubber
063: private Integer correctionRowCount; // Row count in output group
064: private KualiDecimal correctionDebitTotalAmount; // Debit amount total in output group
065: private KualiDecimal correctionCreditTotalAmount; // Credit amount total in output group
066: private KualiDecimal correctionBudgetTotalAmount; // Budget amount total in output group
067: private String correctionInputFileName; // File name if uploaded
068: private String correctionOutputFileName; // Not used
069: private String correctionScriptText; // Not used
070: private Integer correctionInputGroupId; // Group ID that has input data
071: private Integer correctionOutputGroupId; // Group ID that has output data
072: private Integer correctionChangeGroupNextLineNumber;
073:
074: private List<CorrectionChangeGroup> correctionChangeGroup;
075:
076: public CorrectionDocument() {
077: super ();
078: correctionChangeGroupNextLineNumber = new Integer(0);
079:
080: correctionChangeGroup = new ArrayList<CorrectionChangeGroup>();
081: }
082:
083: /**
084: * Returns a Map representation of the primary key of this document
085: *
086: * @return a Map that represents the database key of this document
087: * @see org.kuali.core.bo.BusinessObjectBase#toStringMapper()
088: */
089: @Override
090: protected LinkedHashMap toStringMapper() {
091: LinkedHashMap m = new LinkedHashMap();
092: m
093: .put(KFSPropertyConstants.DOCUMENT_NUMBER,
094: this .documentNumber);
095: return m;
096: }
097:
098: /**
099: * Returns the editing method to use on the origin entries in the document, either "Manual Edit,"
100: * "Using Criteria," "Remove Group from Processing," or "Not Available"
101: *
102: * @return the String representation of the method this document is using
103: */
104: public String getMethod() {
105: if (CorrectionDocumentService.CORRECTION_TYPE_MANUAL
106: .equals(correctionTypeCode)) {
107: return "Manual Edit";
108: } else if (CorrectionDocumentService.CORRECTION_TYPE_CRITERIA
109: .equals(correctionTypeCode)) {
110: return "Using Criteria";
111: } else if (CorrectionDocumentService.CORRECTION_TYPE_REMOVE_GROUP_FROM_PROCESSING
112: .equals(correctionTypeCode)) {
113: return "Remove Group from Processing";
114: } else {
115: return KFSConstants.NOT_AVAILABLE_STRING;
116: }
117: }
118:
119: /**
120: * Returns the source of the origin entries this document uses: either an uploaded file of origin entries
121: * or the database
122: *
123: * @return a String with the name of the system in use
124: */
125: public String getSystem() {
126: if (correctionInputFileName != null) {
127: return "File Upload";
128: } else {
129: return "Database";
130: }
131: }
132:
133: /**
134: *
135: * This method...
136: * @param ccg
137: */
138: public void addCorrectionChangeGroup(CorrectionChangeGroup ccg) {
139: ccg.setDocumentNumber(documentNumber);
140: ccg
141: .setCorrectionChangeGroupLineNumber(correctionChangeGroupNextLineNumber++);
142: correctionChangeGroup.add(ccg);
143: }
144:
145: /**
146: *
147: * This method...
148: * @param changeNumber
149: */
150: public void removeCorrectionChangeGroup(int changeNumber) {
151: for (Iterator iter = correctionChangeGroup.iterator(); iter
152: .hasNext();) {
153: CorrectionChangeGroup element = (CorrectionChangeGroup) iter
154: .next();
155: if (changeNumber == element
156: .getCorrectionChangeGroupLineNumber().intValue()) {
157: iter.remove();
158: }
159: }
160: }
161:
162: /**
163: *
164: * This method...
165: * @param groupNumber
166: * @return
167: */
168: public CorrectionChangeGroup getCorrectionChangeGroupItem(
169: int groupNumber) {
170: for (Iterator iter = correctionChangeGroup.iterator(); iter
171: .hasNext();) {
172: CorrectionChangeGroup element = (CorrectionChangeGroup) iter
173: .next();
174: if (groupNumber == element
175: .getCorrectionChangeGroupLineNumber().intValue()) {
176: return element;
177: }
178: }
179:
180: CorrectionChangeGroup ccg = new CorrectionChangeGroup(
181: documentNumber, groupNumber);
182: correctionChangeGroup.add(ccg);
183:
184: return ccg;
185: }
186:
187: /**
188: * If the document final, change the process flag on the output origin entry group (if necessary)
189: *
190: * @see org.kuali.core.document.DocumentBase#handleRouteStatusChange()
191: */
192: @Override
193: public void handleRouteStatusChange() {
194: LOG.debug("handleRouteStatusChange() started");
195: super .handleRouteStatusChange();
196:
197: CorrectionDocumentService correctionDocumentService = SpringContext
198: .getBean(CorrectionDocumentService.class);
199: OriginEntryGroupService originEntryGroupService = SpringContext
200: .getBean(OriginEntryGroupService.class);
201:
202: String docId = getDocumentHeader().getDocumentNumber();
203: CorrectionDocument doc = correctionDocumentService
204: .findByCorrectionDocumentHeaderId(docId);
205:
206: if (getDocumentHeader().getWorkflowDocument().stateIsFinal()) {
207: String correctionType = doc.getCorrectionTypeCode();
208: if (CorrectionDocumentService.CORRECTION_TYPE_REMOVE_GROUP_FROM_PROCESSING
209: .equals(correctionType)) {
210: SpringContext.getBean(OriginEntryGroupService.class)
211: .dontProcessGroup(
212: doc.getCorrectionInputGroupId());
213: } else if (CorrectionDocumentService.CORRECTION_TYPE_MANUAL
214: .equals(correctionType)
215: || CorrectionDocumentService.CORRECTION_TYPE_CRITERIA
216: .equals(correctionType)) {
217: OriginEntryGroup outputGroup = originEntryGroupService
218: .getExactMatchingEntryGroup(doc
219: .getCorrectionOutputGroupId()
220: .intValue());
221: if (!doc.getCorrectionFileDelete()) {
222: LOG
223: .debug("handleRouteStatusChange() Mark group as to be processed");
224: outputGroup.setProcess(true);
225: originEntryGroupService.save(outputGroup);
226: }
227: } else {
228: LOG.error("GLCP doc " + doc.getDocumentNumber()
229: + " has an unknown correction type code: "
230: + correctionType);
231: }
232: }
233: }
234:
235: /**
236: * Constant for the workgroup approval routing level
237: */
238: private static final Integer WORKGROUP_APPROVAL_ROUTE_LEVEL = new Integer(
239: 1);
240:
241: /**
242: * Waits for the event of the route level changing to "Approve" and at that point, saving all the entries as origin entries in a newly created
243: * origin entry group, then scrubbing those entries
244: *
245: * @param cahnge a representation of the route level changed that just occurred
246: * @see org.kuali.core.document.DocumentBase#handleRouteLevelChange(edu.iu.uis.eden.clientapp.vo.DocumentRouteLevelChangeVO)
247: */
248: @Override
249: public void handleRouteLevelChange(DocumentRouteLevelChangeVO change) {
250: super .handleRouteLevelChange(change);
251: if (WORKGROUP_APPROVAL_ROUTE_LEVEL.equals(change
252: .getNewRouteLevel())) {
253: String correctionType = getCorrectionTypeCode();
254: if (CorrectionDocumentService.CORRECTION_TYPE_MANUAL
255: .equals(correctionType)
256: || CorrectionDocumentService.CORRECTION_TYPE_CRITERIA
257: .equals(correctionType)) {
258: String docId = getDocumentHeader().getDocumentNumber();
259: // this code is performed asynchronously
260:
261: // First, save the origin entries to the origin entry table
262: DateTimeService dateTimeService = SpringContext
263: .getBean(DateTimeService.class);
264: OriginEntryService originEntryService = SpringContext
265: .getBean(OriginEntryService.class);
266: CorrectionDocumentService correctionDocumentService = SpringContext
267: .getBean(CorrectionDocumentService.class);
268:
269: Iterator<OriginEntryFull> outputEntries = correctionDocumentService
270: .retrievePersistedOutputOriginEntriesAsIterator(this );
271:
272: // Create output group
273: java.sql.Date today = dateTimeService
274: .getCurrentSqlDate();
275: // Scrub is set to false when the document is initiated. When the document is final, it will be changed to true
276: OriginEntryGroup oeg = originEntryService.copyEntries(
277: today,
278: OriginEntrySource.GL_CORRECTION_PROCESS_EDOC,
279: true, false, true, outputEntries);
280:
281: // Now, run the reports
282: ReportService reportService = SpringContext
283: .getBean(ReportService.class);
284: ScrubberService scrubberService = SpringContext
285: .getBean(ScrubberService.class);
286:
287: setCorrectionOutputGroupId(oeg.getId());
288: // not using the document service to save because it touches workflow, just save the doc BO as a regular BO
289: SpringContext.getBean(BusinessObjectService.class)
290: .save(this );
291:
292: LOG.debug("handleRouteStatusChange() Run reports");
293:
294: reportService.correctionOnlineReport(this , today);
295:
296: // Run the scrubber on this group to generate a bunch of reports. The scrubber won't save anything when running it
297: // this way.
298: scrubberService.scrubGroupReportOnly(oeg, docId);
299: }
300: }
301: }
302:
303: /**
304: * Returns the total dollar amount associated with this document
305: *
306: * @return if credit total is zero, debit total, otherwise credit total
307: */
308: public KualiDecimal getTotalDollarAmount() {
309: return getCorrectionCreditTotalAmount().add(
310: getCorrectionDebitTotalAmount());
311: }
312:
313: /**
314: * Sets this document's document number, but also sets the document number on all children objects
315: *
316: * @param documentNumber the document number for this document
317: * @see org.kuali.core.document.DocumentBase#setDocumentNumber(java.lang.String)
318: */
319: @Override
320: public void setDocumentNumber(String documentNumber) {
321: super .setDocumentNumber(documentNumber);
322:
323: for (Iterator iter = correctionChangeGroup.iterator(); iter
324: .hasNext();) {
325: CorrectionChangeGroup element = (CorrectionChangeGroup) iter
326: .next();
327: element.setDocumentNumber(documentNumber);
328: }
329: }
330:
331: public String getCorrectionTypeCode() {
332: return correctionTypeCode;
333: }
334:
335: public void setCorrectionTypeCode(String correctionTypeCode) {
336: this .correctionTypeCode = correctionTypeCode;
337: }
338:
339: public boolean getCorrectionSelection() {
340: return correctionSelection;
341: }
342:
343: public void setCorrectionSelection(boolean correctionSelection) {
344: this .correctionSelection = correctionSelection;
345: }
346:
347: public boolean getCorrectionFileDelete() {
348: return correctionFileDelete;
349: }
350:
351: public void setCorrectionFileDelete(boolean correctionFileDelete) {
352: this .correctionFileDelete = correctionFileDelete;
353: }
354:
355: public Integer getCorrectionRowCount() {
356: return correctionRowCount;
357: }
358:
359: public void setCorrectionRowCount(Integer correctionRowCount) {
360: this .correctionRowCount = correctionRowCount;
361: }
362:
363: public Integer getCorrectionChangeGroupNextLineNumber() {
364: return correctionChangeGroupNextLineNumber;
365: }
366:
367: public void setCorrectionChangeGroupNextLineNumber(
368: Integer correctionChangeGroupNextLineNumber) {
369: this .correctionChangeGroupNextLineNumber = correctionChangeGroupNextLineNumber;
370: }
371:
372: public KualiDecimal getCorrectionDebitTotalAmount() {
373: return correctionDebitTotalAmount;
374: }
375:
376: public void setCorrectionDebitTotalAmount(
377: KualiDecimal correctionDebitTotalAmount) {
378: this .correctionDebitTotalAmount = correctionDebitTotalAmount;
379: }
380:
381: public KualiDecimal getCorrectionCreditTotalAmount() {
382: return correctionCreditTotalAmount;
383: }
384:
385: public void setCorrectionCreditTotalAmount(
386: KualiDecimal correctionCreditTotalAmount) {
387: this .correctionCreditTotalAmount = correctionCreditTotalAmount;
388: }
389:
390: public KualiDecimal getCorrectionBudgetTotalAmount() {
391: return correctionBudgetTotalAmount;
392: }
393:
394: public void setCorrectionBudgetTotalAmount(
395: KualiDecimal correctionBudgetTotalAmount) {
396: this .correctionBudgetTotalAmount = correctionBudgetTotalAmount;
397: }
398:
399: public String getCorrectionInputFileName() {
400: return correctionInputFileName;
401: }
402:
403: public void setCorrectionInputFileName(
404: String correctionInputFileName) {
405: this .correctionInputFileName = correctionInputFileName;
406: }
407:
408: public String getCorrectionOutputFileName() {
409: return correctionOutputFileName;
410: }
411:
412: public void setCorrectionOutputFileName(
413: String correctionOutputFileName) {
414: this .correctionOutputFileName = correctionOutputFileName;
415: }
416:
417: public List<CorrectionChangeGroup> getCorrectionChangeGroup() {
418: Collections.sort(correctionChangeGroup);
419: return correctionChangeGroup;
420: }
421:
422: public void setCorrectionChangeGroup(
423: List<CorrectionChangeGroup> correctionChangeGroup) {
424: this .correctionChangeGroup = correctionChangeGroup;
425: }
426:
427: public Integer getCorrectionInputGroupId() {
428: return correctionInputGroupId;
429: }
430:
431: public void setCorrectionInputGroupId(Integer correctionInputGroupId) {
432: this .correctionInputGroupId = correctionInputGroupId;
433: }
434:
435: public Integer getCorrectionOutputGroupId() {
436: return correctionOutputGroupId;
437: }
438:
439: public void setCorrectionOutputGroupId(
440: Integer correctionOutputGroupId) {
441: this.correctionOutputGroupId = correctionOutputGroupId;
442: }
443: }
|