001 /*
002 * Copyright 2011 The Kuali Foundation.
003 *
004 * Licensed under the Educational Community License, Version 2.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/ecl2.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.kfs.module.bc.document.service.impl;
017
018
019 import java.io.BufferedReader;
020 import java.io.ByteArrayOutputStream;
021 import java.io.IOException;
022 import java.io.InputStream;
023 import java.io.InputStreamReader;
024 import java.util.ArrayList;
025 import java.util.HashMap;
026 import java.util.List;
027 import java.util.Map;
028
029 import org.apache.commons.lang.StringUtils;
030 import org.kuali.kfs.coa.businessobject.ObjectCode;
031 import org.kuali.kfs.coa.businessobject.SubObjectCode;
032 import org.kuali.kfs.integration.ld.LaborLedgerObject;
033 import org.kuali.kfs.integration.ld.LaborModuleService;
034 import org.kuali.kfs.module.bc.BCConstants;
035 import org.kuali.kfs.module.bc.BCConstants.RequestImportFileType;
036 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionFundingLock;
037 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionHeader;
038 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionLockStatus;
039 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionMonthly;
040 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionRequestMove;
041 import org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionGeneralLedger;
042 import org.kuali.kfs.module.bc.document.BudgetConstructionDocument;
043 import org.kuali.kfs.module.bc.document.dataaccess.ImportRequestDao;
044 import org.kuali.kfs.module.bc.document.service.BenefitsCalculationService;
045 import org.kuali.kfs.module.bc.document.service.BudgetDocumentService;
046 import org.kuali.kfs.module.bc.document.service.BudgetParameterService;
047 import org.kuali.kfs.module.bc.document.service.BudgetRequestImportService;
048 import org.kuali.kfs.module.bc.document.service.LockService;
049 import org.kuali.kfs.module.bc.util.BudgetParameterFinder;
050 import org.kuali.kfs.module.bc.util.ImportRequestFileParsingHelper;
051 import org.kuali.kfs.sys.KFSConstants;
052 import org.kuali.kfs.sys.KFSPropertyConstants;
053 import org.kuali.kfs.sys.context.SpringContext;
054 import org.kuali.kfs.sys.service.NonTransactional;
055 import org.kuali.kfs.sys.service.OptionsService;
056 import org.kuali.rice.kew.exception.WorkflowException;
057 import org.kuali.rice.kim.bo.Person;
058 import org.kuali.rice.kim.util.KimConstants;
059 import org.kuali.rice.kns.document.authorization.TransactionalDocumentAuthorizer;
060 import org.kuali.rice.kns.service.BusinessObjectService;
061 import org.kuali.rice.kns.service.DictionaryValidationService;
062 import org.kuali.rice.kns.service.DocumentHelperService;
063 import org.kuali.rice.kns.service.DocumentService;
064 import org.kuali.rice.kns.util.KNSConstants;
065 import org.kuali.rice.kns.util.KualiInteger;
066 import org.springframework.transaction.annotation.Transactional;
067
068 import com.lowagie.text.Document;
069 import com.lowagie.text.DocumentException;
070 import com.lowagie.text.Paragraph;
071 import com.lowagie.text.pdf.PdfWriter;
072
073 /**
074 * Contains services relevent to the budget construction import request process
075 */
076
077 public class BudgetRequestImportServiceImpl implements BudgetRequestImportService {
078 private BusinessObjectService businessObjectService;
079 private ImportRequestDao importRequestDao;
080 private DictionaryValidationService dictionaryValidationService;
081 private LockService lockService;
082 private BudgetDocumentService budgetDocumentService;
083 private LaborModuleService laborModuleService;
084 private BudgetParameterService budgetParameterService;
085 private OptionsService optionsService;
086 private DocumentHelperService documentHelperService;
087 private DocumentService documentService;
088
089 private static final org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory.getLog(BudgetRequestImportServiceImpl.class);
090
091 /**
092 * @see org.kuali.kfs.module.bc.document.service.BudgetRequestImportService#generatePdf(java.util.List, java.io.ByteArrayOutputStream)
093 */
094 @NonTransactional
095 public void generatePdf(List<String> errorMessages, ByteArrayOutputStream baos) throws DocumentException {
096 Document document = new Document();
097 PdfWriter.getInstance(document, baos);
098 document.open();
099
100 for (String error : errorMessages) {
101 document.add(new Paragraph(error));
102 }
103
104 document.close();
105 }
106
107 /**
108 * @see org.kuali.kfs.module.bc.document.service.BudgetRequestImportService#processImportFile(java.io.InputStream, java.lang.String,
109 * java.lang.String, java.lang.String)
110 */
111 @Transactional
112 public List processImportFile(InputStream fileImportStream, String principalId, String fieldSeperator, String textDelimiter, String fileType, Integer budgetYear) throws IOException {
113 List fileErrorList = new ArrayList();
114
115 deleteBudgetConstructionMoveRecords(principalId);
116
117 BudgetConstructionRequestMove budgetConstructionRequestMove = new BudgetConstructionRequestMove();
118
119 BufferedReader fileReader = new BufferedReader(new InputStreamReader(fileImportStream));
120 int currentLine = 1;
121 while (fileReader.ready()) {
122 String line = StringUtils.strip(fileReader.readLine());
123 boolean isAnnualFile = (fileType.equalsIgnoreCase(RequestImportFileType.ANNUAL.toString())) ? true : false;
124
125 if (StringUtils.isNotBlank(line)) {
126 budgetConstructionRequestMove = ImportRequestFileParsingHelper.parseLine(line, fieldSeperator, textDelimiter, isAnnualFile);
127
128 // check if there were errors parsing the line
129 if (budgetConstructionRequestMove == null) {
130 fileErrorList.add(BCConstants.REQUEST_IMPORT_FILE_PROCESSING_ERROR_MESSAGE_GENERIC + " " + currentLine + ".");
131 // clean out table since file processing has stopped
132 deleteBudgetConstructionMoveRecords(principalId);
133 return fileErrorList;
134 }
135
136 String lineValidationError = validateLine(budgetConstructionRequestMove, currentLine, isAnnualFile);
137
138 if ( StringUtils.isNotEmpty(lineValidationError) ) {
139 fileErrorList.add(lineValidationError);
140 // clean out table since file processing has stopped
141 deleteBudgetConstructionMoveRecords(principalId);
142 return fileErrorList;
143 }
144
145 // set default values
146 if (StringUtils.isBlank(budgetConstructionRequestMove.getSubAccountNumber())) {
147 budgetConstructionRequestMove.setSubAccountNumber(KFSConstants.getDashSubAccountNumber());
148 }
149
150 if (StringUtils.isBlank(budgetConstructionRequestMove.getFinancialSubObjectCode())) {
151 budgetConstructionRequestMove.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
152 }
153 //set object type code
154 List revenueObjectTypesParamValues = BudgetParameterFinder.getRevenueObjectTypes();
155 List expenditureObjectTypesParamValues = BudgetParameterFinder.getExpenditureObjectTypes();
156 ObjectCode objectCode = getObjectCode(budgetConstructionRequestMove, budgetYear);
157 if (objectCode != null) {
158 if ( expenditureObjectTypesParamValues.contains(objectCode.getFinancialObjectTypeCode()) ) {
159 budgetConstructionRequestMove.setFinancialObjectTypeCode(optionsService.getOptions(budgetYear).getFinObjTypeExpenditureexpCd());
160 } else if ( revenueObjectTypesParamValues.contains(objectCode.getFinancialObjectTypeCode()) ) {
161 budgetConstructionRequestMove.setFinancialObjectTypeCode(optionsService.getOptions(budgetYear).getFinObjectTypeIncomecashCode());
162 }
163 }
164
165 //check for duplicate key exception, since it requires a different error message
166 Map searchCriteria = new HashMap();
167 searchCriteria.put("principalId", principalId);
168 searchCriteria.put("chartOfAccountsCode", budgetConstructionRequestMove.getChartOfAccountsCode());
169 searchCriteria.put("accountNumber", budgetConstructionRequestMove.getAccountNumber());
170 searchCriteria.put("subAccountNumber", budgetConstructionRequestMove.getSubAccountNumber());
171 searchCriteria.put("financialObjectCode", budgetConstructionRequestMove.getFinancialObjectCode());
172 searchCriteria.put("financialSubObjectCode", budgetConstructionRequestMove.getFinancialSubObjectCode());
173 if ( this.businessObjectService.countMatching(BudgetConstructionRequestMove.class, searchCriteria) != 0 ) {
174 LOG.error("Move table store error, import aborted");
175 fileErrorList.add("Duplicate Key for " + budgetConstructionRequestMove.getErrorLinePrefixForLogFile());
176 fileErrorList.add("Move table store error, import aborted");
177 deleteBudgetConstructionMoveRecords(principalId);
178
179 return fileErrorList;
180 }
181 try {
182 budgetConstructionRequestMove.setPrincipalId(principalId);
183 importRequestDao.save(budgetConstructionRequestMove, false);
184 }
185 catch (RuntimeException e) {
186 LOG.error("Move table store error, import aborted");
187 fileErrorList.add("Move table store error, import aborted");
188 return fileErrorList;
189 }
190 }
191
192 currentLine++;
193 }
194
195 return fileErrorList;
196 }
197
198
199 /**
200 * Sets the business object service
201 *
202 * @param businessObjectService
203 */
204 @NonTransactional
205 public void setBusinessObjectService(BusinessObjectService businessObjectService) {
206 this.businessObjectService = businessObjectService;
207 }
208
209 /**
210 * @see org.kuali.kfs.module.bc.document.service.BudgetRequestImportService#validateData()
211 */
212 @Transactional
213 public List<String> validateData(Integer budgetYear, String principalId) {
214 Map searchCriteria = new HashMap();
215 searchCriteria.put("principalId", principalId);
216 List<BudgetConstructionRequestMove> dataToValidateList = new ArrayList<BudgetConstructionRequestMove>(businessObjectService.findMatching(BudgetConstructionRequestMove.class, searchCriteria));
217 List<String> errorMessages = new ArrayList<String>();
218
219 Map<String, BudgetConstructionHeader> retrievedHeaders = new HashMap<String, BudgetConstructionHeader>();
220
221 for (BudgetConstructionRequestMove record : dataToValidateList) {
222 boolean validLine = true;
223 //KFSMI-798 - refreshNonUpdatableReferences() used instead of refresh(),
224 //BudgetConstructionRequestMove does not have any updatable references
225 record.refreshNonUpdateableReferences();
226
227 String accountKey = record.getChartOfAccountsCode() + record.getAccountNumber();
228 BudgetConstructionHeader budgetConstructionHeader = null;
229 if (retrievedHeaders.containsKey(accountKey)) {
230 budgetConstructionHeader = retrievedHeaders.get(accountKey);
231 }
232 else {
233 budgetConstructionHeader = importRequestDao.getHeaderRecord(record, budgetYear);
234 retrievedHeaders.put(accountKey, budgetConstructionHeader);
235 }
236
237 SubObjectCode subObjectCode = getSubObjectCode(record, budgetYear);
238 String code = record.getFinancialObjectTypeCode();
239 LaborLedgerObject laborObject = this.laborModuleService.retrieveLaborLedgerObject(budgetYear, record.getChartOfAccountsCode(), record.getFinancialObjectCode());
240 ObjectCode objectCode = getObjectCode(record, budgetYear);
241
242 if (budgetConstructionHeader == null) {
243 record.setRequestUpdateErrorCode(BCConstants.RequestImportErrorCode.DATA_VALIDATION_NO_BUDGETED_ACCOUNT_SUB_ACCOUNT_ERROR_CODE.getErrorCode());
244 errorMessages.add(record.getErrorLinePrefixForLogFile() + " " + BCConstants.RequestImportErrorCode.DATA_VALIDATION_NO_BUDGETED_ACCOUNT_SUB_ACCOUNT_ERROR_CODE.getMessage());
245 }
246
247 else if (!record.getAccount().isActive()) {
248 record.setRequestUpdateErrorCode(BCConstants.RequestImportErrorCode.DATA_VALIDATION_ACCOUNT_CLOSED_ERROR_CODE.getErrorCode());
249 errorMessages.add(record.getErrorLinePrefixForLogFile() + " " + BCConstants.RequestImportErrorCode.DATA_VALIDATION_ACCOUNT_CLOSED_ERROR_CODE.getMessage());
250 }
251
252 else if (record.getAccount().isExpired()) {
253 record.setRequestUpdateErrorCode(BCConstants.RequestImportErrorCode.DATA_VALIDATION_ACCOUNT_EXPIRED_ERROR_CODE.getErrorCode());
254 errorMessages.add(record.getErrorLinePrefixForLogFile() + " " + BCConstants.RequestImportErrorCode.DATA_VALIDATION_ACCOUNT_EXPIRED_ERROR_CODE.getMessage());
255 }
256
257 else if (!record.getSubAccountNumber().equalsIgnoreCase(KFSConstants.getDashSubAccountNumber()) && !record.getSubAccount().isActive()) {
258 record.setRequestUpdateErrorCode(BCConstants.RequestImportErrorCode.DATA_VALIDATION_SUB_ACCOUNT_INACTIVE_ERROR_CODE.getErrorCode());
259 errorMessages.add(record.getErrorLinePrefixForLogFile() + " " + BCConstants.RequestImportErrorCode.DATA_VALIDATION_SUB_ACCOUNT_INACTIVE_ERROR_CODE.getMessage());
260 }
261
262 // null object type
263 else if (StringUtils.isBlank(record.getFinancialObjectTypeCode())) {
264 record.setRequestUpdateErrorCode(BCConstants.RequestImportErrorCode.DATA_VALIDATION_OBJECT_TYPE_NULL_ERROR_CODE.getErrorCode());
265 errorMessages.add(record.getErrorLinePrefixForLogFile() + " " + BCConstants.RequestImportErrorCode.DATA_VALIDATION_OBJECT_TYPE_INVALID_ERROR_CODE.getMessage());
266 }
267
268 // inactive object code
269 else if (objectCode != null && !objectCode.isActive()) {
270 record.setRequestUpdateErrorCode(BCConstants.RequestImportErrorCode.DATA_VALIDATION_OBJECT_CODE_INACTIVE_ERROR_CODE.getErrorCode());
271 errorMessages.add(record.getErrorLinePrefixForLogFile() + " " + BCConstants.RequestImportErrorCode.DATA_VALIDATION_OBJECT_CODE_INACTIVE_ERROR_CODE.getMessage());
272 }
273
274 // compensation object codes COMP
275 else if (laborObject != null && (laborObject.isDetailPositionRequiredIndicator() || laborObject.getFinancialObjectFringeOrSalaryCode().equals(BCConstants.LABOR_OBJECT_FRINGE_CODE))) {
276 record.setRequestUpdateErrorCode(BCConstants.RequestImportErrorCode.DATA_VALIDATION_COMPENSATION_OBJECT_CODE_ERROR_CODE.getErrorCode());
277 errorMessages.add(record.getErrorLinePrefixForLogFile() + " " + BCConstants.RequestImportErrorCode.DATA_VALIDATION_COMPENSATION_OBJECT_CODE_ERROR_CODE.getMessage());
278 }
279
280 // no wage accounts CMPA
281 else if (!record.getAccount().getSubFundGroup().isSubFundGroupWagesIndicator() && laborObject != null) {
282 record.setRequestUpdateErrorCode(BCConstants.RequestImportErrorCode.DATA_VALIDATION_NO_WAGE_ACCOUNT_ERROR_CODE.getErrorCode());
283 errorMessages.add(record.getErrorLinePrefixForLogFile() + " " + BCConstants.RequestImportErrorCode.DATA_VALIDATION_NO_WAGE_ACCOUNT_ERROR_CODE.getMessage());
284 }
285
286 // invalid sub-object code NOSO
287 else if (!record.getFinancialSubObjectCode().equalsIgnoreCase(KFSConstants.getDashFinancialSubObjectCode()) && subObjectCode == null) {
288 record.setRequestUpdateErrorCode(BCConstants.RequestImportErrorCode.DATA_VALIDATION_SUB_OBJECT_INVALID_ERROR_CODE.getErrorCode());
289 errorMessages.add(record.getErrorLinePrefixForLogFile() + " " + BCConstants.RequestImportErrorCode.DATA_VALIDATION_SUB_OBJECT_INVALID_ERROR_CODE.getMessage());
290 }
291
292 // inactive sub-object code
293 else if (!record.getFinancialSubObjectCode().equalsIgnoreCase(KFSConstants.getDashFinancialSubObjectCode()) && !subObjectCode.isActive()) {
294 record.setRequestUpdateErrorCode(BCConstants.RequestImportErrorCode.DATA_VALIDATION_SUB_OBJECT_INACTIVE_ERROR_CODE.getErrorCode());
295 errorMessages.add(record.getErrorLinePrefixForLogFile() + " " + BCConstants.RequestImportErrorCode.DATA_VALIDATION_SUB_OBJECT_INACTIVE_ERROR_CODE.getMessage());
296 }
297
298 importRequestDao.save(record, true);
299 }
300
301 return errorMessages;
302 }
303
304 /**
305 * @see org.kuali.kfs.module.bc.document.service.BudgetRequestImportService#loadBudget()
306 */
307 @Transactional
308 public List<String> loadBudget(Person user, String fileType, Integer budgetYear) throws Exception {
309 List<BudgetConstructionRequestMove> recordsToLoad = importRequestDao.findAllNonErrorCodeRecords(user.getPrincipalId());
310 List<String> errorMessages = new ArrayList<String>();
311 Map<String, BudgetConstructionRequestMove> recordMap = new HashMap<String, BudgetConstructionRequestMove>();
312
313 for (BudgetConstructionRequestMove recordToLoad : recordsToLoad) {
314 BudgetConstructionHeader header = importRequestDao.getHeaderRecord(recordToLoad, budgetYear);
315
316 if (recordMap.containsKey(recordToLoad.getSubAccountingString())) {
317 BudgetConstructionRequestMove temp = recordMap.get(recordToLoad.getSubAccountingString());
318
319 recordToLoad.setHasAccess(temp.getHasAccess());
320 recordToLoad.setHasLock(temp.getHasLock());
321 recordToLoad.setRequestUpdateErrorCode(temp.getRequestUpdateErrorCode());
322 }
323 else {
324 boolean hasAccess = false;
325 if (header != null) {
326 BudgetConstructionDocument document;
327 try {
328 document = (BudgetConstructionDocument) documentService.getByDocumentHeaderId(header.getDocumentNumber());
329 }
330 catch (WorkflowException e) {
331 throw new RuntimeException("Fail to retrieve budget document for doc id " + header.getDocumentNumber());
332 }
333
334 TransactionalDocumentAuthorizer documentAuthorizer = (TransactionalDocumentAuthorizer) getDocumentHelperService().getDocumentAuthorizer(document);
335 hasAccess = documentAuthorizer.isAuthorizedByTemplate(document, KNSConstants.KNS_NAMESPACE, KimConstants.PermissionTemplateNames.EDIT_DOCUMENT, user.getPrincipalId());
336 }
337
338 if (hasAccess) {
339 recordToLoad.setHasAccess(true);
340 }
341 else {
342 recordToLoad.setRequestUpdateErrorCode(BCConstants.RequestImportErrorCode.UPDATE_ERROR_CODE_NO_ACCESS_TO_BUDGET_ACCOUNT.getErrorCode());
343 errorMessages.add(recordToLoad.getErrorLinePrefixForLogFile() + " " + BCConstants.RequestImportErrorCode.UPDATE_ERROR_CODE_NO_ACCESS_TO_BUDGET_ACCOUNT.getMessage());
344 }
345
346 if (recordToLoad.getHasAccess()) {
347 BudgetConstructionLockStatus lockStatus = this.lockService.lockAccountAndCommit(header, user.getPrincipalId());
348 if (lockStatus.getLockStatus().equals(BCConstants.LockStatus.SUCCESS)) {
349 recordToLoad.setHasLock(true);
350 } else {
351 recordToLoad.setRequestUpdateErrorCode(BCConstants.RequestImportErrorCode.UPDATE_ERROR_CODE_BUDGET_ACCOUNT_LOCKED.getErrorCode());
352 errorMessages.add(recordToLoad.getErrorLinePrefixForLogFile() + " " + BCConstants.RequestImportErrorCode.UPDATE_ERROR_CODE_BUDGET_ACCOUNT_LOCKED.getMessage());
353 }
354 }
355
356 recordMap.put(recordToLoad.getSubAccountingString(), recordToLoad);
357 }
358
359 //since error codes are copied based on the locking key, the previous records error code from the updateBudgetAmounts may have been copied to this record and should be ignored.
360 String updateAmountPreviousErrorMessage =BCConstants.RequestImportErrorCode.UPDATE_ERROR_CODE_MONTHLY_BUDGET_DELETED.getErrorCode();
361 if (recordToLoad.getHasAccess() && recordToLoad.getHasLock() &&
362 ( StringUtils.isBlank(recordToLoad.getRequestUpdateErrorCode()) || recordToLoad.getRequestUpdateErrorCode().endsWith(updateAmountPreviousErrorMessage)) ) {
363 String updateBudgetAmountErrorMessage = updateBudgetAmounts(fileType, recordToLoad, header, budgetYear);
364 if (!StringUtils.isEmpty(updateBudgetAmountErrorMessage))
365 errorMessages.add(recordToLoad.getErrorLinePrefixForLogFile() + " " + updateBudgetAmountErrorMessage);
366 }
367
368 importRequestDao.save(recordToLoad, true);
369 }
370
371 for (String key : recordMap.keySet()) {
372 BudgetConstructionRequestMove record = recordMap.get(key);
373 BudgetConstructionHeader header = importRequestDao.getHeaderRecord(record, budgetYear);
374 if (record.getHasAccess() && record.getHasLock() && StringUtils.isBlank(record.getRequestUpdateErrorCode())) {
375 udpateBenefits(fileType, header);
376 }
377
378 if (record.getHasLock() && header != null) {
379 this.lockService.unlockAccount(header);
380 }
381 }
382
383 deleteBudgetConstructionMoveRecords(user.getPrincipalId());
384 return errorMessages;
385 }
386
387 /**
388 * @see org.kuali.kfs.module.bc.document.service.BudgetRequestImportService#getImportRequestDao()
389 */
390 @NonTransactional
391 public ImportRequestDao getImportRequestDao() {
392 return this.importRequestDao;
393 }
394
395 /**
396 * @see org.kuali.kfs.module.bc.document.service.BudgetRequestImportService#setImportRequestDao(org.kuali.kfs.module.bc.document.dataaccess.ImportRequestDao)
397 */
398 @NonTransactional
399 public void setImportRequestDao(ImportRequestDao dao) {
400 this.importRequestDao = dao;
401
402 }
403
404 /**
405 * updates budget amounts
406 *
407 * @param fileType
408 * @param importLine
409 * @return error message
410 */
411 protected String updateBudgetAmounts(String fileType, BudgetConstructionRequestMove importLine, BudgetConstructionHeader header, Integer budgetYear) {
412 String errorMessage = "";
413
414 //set primary key values
415 PendingBudgetConstructionGeneralLedger pendingEntry = new PendingBudgetConstructionGeneralLedger();
416 pendingEntry.setDocumentNumber(header.getDocumentNumber());
417 pendingEntry.setUniversityFiscalYear(budgetYear);
418 pendingEntry.setChartOfAccountsCode(importLine.getChartOfAccountsCode());
419 pendingEntry.setAccountNumber(importLine.getAccountNumber());
420 pendingEntry.setSubAccountNumber(importLine.getSubAccountNumber());
421 pendingEntry.setFinancialObjectCode(importLine.getFinancialObjectCode());
422 pendingEntry.setFinancialSubObjectCode(importLine.getFinancialSubObjectCode());
423 pendingEntry.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_BASE_BUDGET);
424 pendingEntry.setFinancialObjectTypeCode(importLine.getFinancialObjectTypeCode());
425
426 //if entry already exists, use existing entry
427 PendingBudgetConstructionGeneralLedger retrievedPendingEntry = (PendingBudgetConstructionGeneralLedger) businessObjectService.retrieve(pendingEntry);
428 if (retrievedPendingEntry != null) pendingEntry = retrievedPendingEntry;
429 else pendingEntry.setFinancialBeginningBalanceLineAmount(new KualiInteger(0));
430
431 if (fileType.equalsIgnoreCase(BCConstants.RequestImportFileType.ANNUAL.toString())) {
432 List<BudgetConstructionMonthly> monthlyRecords = pendingEntry.getBudgetConstructionMonthly();
433
434 if (!monthlyRecords.isEmpty()) {
435 importLine.setRequestUpdateErrorCode(BCConstants.RequestImportErrorCode.UPDATE_ERROR_CODE_MONTHLY_BUDGET_DELETED.getErrorCode());
436 errorMessage = BCConstants.RequestImportErrorCode.UPDATE_ERROR_CODE_MONTHLY_BUDGET_DELETED.getMessage();
437 for (BudgetConstructionMonthly monthlyRecord : monthlyRecords) {
438 businessObjectService.delete(monthlyRecord);
439 }
440
441 importRequestDao.save(importLine, true);
442 }
443
444 pendingEntry.setAccountLineAnnualBalanceAmount(importLine.getAccountLineAnnualBalanceAmount());
445 this.businessObjectService.save(pendingEntry);
446 }
447 else if (fileType.equalsIgnoreCase(BCConstants.RequestImportFileType.MONTHLY.toString())) {
448
449 //calculate account line annual balance amount
450 KualiInteger annualAmount = new KualiInteger(0);
451 annualAmount = annualAmount.add(importLine.getFinancialDocumentMonth1LineAmount());
452 annualAmount = annualAmount.add(importLine.getFinancialDocumentMonth2LineAmount());
453 annualAmount = annualAmount.add(importLine.getFinancialDocumentMonth3LineAmount());
454 annualAmount = annualAmount.add(importLine.getFinancialDocumentMonth4LineAmount());
455 annualAmount = annualAmount.add(importLine.getFinancialDocumentMonth5LineAmount());
456 annualAmount = annualAmount.add(importLine.getFinancialDocumentMonth6LineAmount());
457 annualAmount = annualAmount.add(importLine.getFinancialDocumentMonth7LineAmount());
458 annualAmount = annualAmount.add(importLine.getFinancialDocumentMonth8LineAmount());
459 annualAmount = annualAmount.add(importLine.getFinancialDocumentMonth9LineAmount());
460 annualAmount = annualAmount.add(importLine.getFinancialDocumentMonth10LineAmount());
461 annualAmount = annualAmount.add(importLine.getFinancialDocumentMonth11LineAmount());
462 annualAmount = annualAmount.add(importLine.getFinancialDocumentMonth12LineAmount());
463 pendingEntry.setAccountLineAnnualBalanceAmount(annualAmount);
464
465
466 //set primary key values
467 BudgetConstructionMonthly monthlyEntry = new BudgetConstructionMonthly();
468 monthlyEntry.setDocumentNumber(header.getDocumentNumber());
469 monthlyEntry.setUniversityFiscalYear(budgetYear);
470 monthlyEntry.setChartOfAccountsCode(importLine.getChartOfAccountsCode());
471 monthlyEntry.setAccountNumber(importLine.getAccountNumber());
472 monthlyEntry.setSubAccountNumber(importLine.getSubAccountNumber());
473 monthlyEntry.setFinancialObjectCode(importLine.getFinancialObjectCode());
474 monthlyEntry.setFinancialSubObjectCode(importLine.getFinancialSubObjectCode());
475 monthlyEntry.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_BASE_BUDGET);
476 monthlyEntry.setFinancialObjectTypeCode(importLine.getFinancialObjectTypeCode());
477
478 //if entry already exists, use existing entry
479 BudgetConstructionMonthly retrievedMonthlyEntry = (BudgetConstructionMonthly) businessObjectService.retrieve(monthlyEntry);
480 if (retrievedMonthlyEntry != null) {
481 monthlyEntry = retrievedMonthlyEntry;
482 //monthlyEntry.getPendingBudgetConstructionGeneralLedger().setAccountLineAnnualBalanceAmount(annualAmount);
483 }
484 /*else {
485 pendingEntry.setAccountLineAnnualBalanceAmount(annualAmount);
486 monthlyEntry.setPendingBudgetConstructionGeneralLedger(pendingEntry);
487 }*/
488
489 monthlyEntry.setFinancialDocumentMonth1LineAmount(importLine.getFinancialDocumentMonth1LineAmount());
490 monthlyEntry.setFinancialDocumentMonth2LineAmount(importLine.getFinancialDocumentMonth2LineAmount());
491 monthlyEntry.setFinancialDocumentMonth3LineAmount(importLine.getFinancialDocumentMonth3LineAmount());
492 monthlyEntry.setFinancialDocumentMonth4LineAmount(importLine.getFinancialDocumentMonth4LineAmount());
493 monthlyEntry.setFinancialDocumentMonth5LineAmount(importLine.getFinancialDocumentMonth5LineAmount());
494 monthlyEntry.setFinancialDocumentMonth6LineAmount(importLine.getFinancialDocumentMonth6LineAmount());
495 monthlyEntry.setFinancialDocumentMonth7LineAmount(importLine.getFinancialDocumentMonth7LineAmount());
496 monthlyEntry.setFinancialDocumentMonth8LineAmount(importLine.getFinancialDocumentMonth8LineAmount());
497 monthlyEntry.setFinancialDocumentMonth9LineAmount(importLine.getFinancialDocumentMonth9LineAmount());
498 monthlyEntry.setFinancialDocumentMonth10LineAmount(importLine.getFinancialDocumentMonth10LineAmount());
499 monthlyEntry.setFinancialDocumentMonth11LineAmount(importLine.getFinancialDocumentMonth11LineAmount());
500 monthlyEntry.setFinancialDocumentMonth12LineAmount(importLine.getFinancialDocumentMonth12LineAmount());
501
502 this.businessObjectService.save(pendingEntry);
503 this.businessObjectService.save(monthlyEntry);
504
505 }
506
507 return errorMessage;
508 }
509
510 /**
511 * Updates benefits
512 *
513 * @param fileType
514 * @param importLine
515 */
516 protected void udpateBenefits(String fileType, BudgetConstructionHeader header) {
517 BenefitsCalculationService benefitsCalculationService = SpringContext.getBean(BenefitsCalculationService.class);
518
519 benefitsCalculationService.calculateAnnualBudgetConstructionGeneralLedgerBenefits(header.getDocumentNumber(), header.getUniversityFiscalYear(), header.getChartOfAccountsCode(), header.getAccountNumber(), header.getSubAccountNumber());
520
521 if (fileType.equalsIgnoreCase(BCConstants.RequestImportFileType.MONTHLY.toString())) {
522 benefitsCalculationService.calculateMonthlyBudgetConstructionGeneralLedgerBenefits(header.getDocumentNumber(), header.getUniversityFiscalYear(), header.getChartOfAccountsCode(), header.getAccountNumber(), header.getSubAccountNumber());
523 }
524 }
525
526 /**
527 * Checks line validations and returns error messages for line
528 *
529 * @param budgetConstructionRequestMove
530 * @param lineNumber
531 * @param isAnnual
532 * @return
533 */
534
535 protected String validateLine(BudgetConstructionRequestMove budgetConstructionRequestMove, int lineNumber, boolean isAnnual) {
536
537 if ( !this.dictionaryValidationService.isBusinessObjectValid(budgetConstructionRequestMove)) {
538 return BCConstants.REQUEST_IMPORT_FILE_PROCESSING_ERROR_MESSAGE_GENERIC + " " + lineNumber + ".";
539 }
540
541 if (isAnnual) {
542 if (budgetConstructionRequestMove.getAccountLineAnnualBalanceAmount().compareTo(new KualiInteger(999999999)) >= 0 || budgetConstructionRequestMove.getAccountLineAnnualBalanceAmount().compareTo(new KualiInteger(-999999999)) <= 0) {
543 return BCConstants.REQUEST_IMPORT_FILE_PROCESSING_ERROR_MESSAGE_GENERIC + " " + lineNumber + ".";
544 }
545 }
546
547 if (!isAnnual) {
548
549 if (budgetConstructionRequestMove.getFinancialDocumentMonth1LineAmount().compareTo(new KualiInteger(999999999)) >= 0 || budgetConstructionRequestMove.getFinancialDocumentMonth1LineAmount().compareTo(new KualiInteger(-999999999)) <= 0) {
550 return BCConstants.REQUEST_IMPORT_FILE_PROCESSING_ERROR_MESSAGE_GENERIC + " " + lineNumber + ".";
551 }
552 if (budgetConstructionRequestMove.getFinancialDocumentMonth2LineAmount().compareTo(new KualiInteger(999999999)) >= 0 || budgetConstructionRequestMove.getFinancialDocumentMonth2LineAmount().compareTo(new KualiInteger(-999999999)) <= 0) {
553 return BCConstants.REQUEST_IMPORT_FILE_PROCESSING_ERROR_MESSAGE_GENERIC + " " + lineNumber + ".";
554 }
555 if (budgetConstructionRequestMove.getFinancialDocumentMonth3LineAmount().compareTo(new KualiInteger(999999999)) >= 0 || budgetConstructionRequestMove.getFinancialDocumentMonth3LineAmount().compareTo(new KualiInteger(-999999999)) <= 0) {
556 return BCConstants.REQUEST_IMPORT_FILE_PROCESSING_ERROR_MESSAGE_GENERIC + " " + lineNumber + ".";
557 }
558 if (budgetConstructionRequestMove.getFinancialDocumentMonth4LineAmount().compareTo(new KualiInteger(999999999)) >= 0 || budgetConstructionRequestMove.getFinancialDocumentMonth4LineAmount().compareTo(new KualiInteger(-999999999)) <= 0) {
559 return BCConstants.REQUEST_IMPORT_FILE_PROCESSING_ERROR_MESSAGE_GENERIC + " " + lineNumber + ".";
560 }
561 if (budgetConstructionRequestMove.getFinancialDocumentMonth5LineAmount().compareTo(new KualiInteger(999999999)) >= 0 || budgetConstructionRequestMove.getFinancialDocumentMonth5LineAmount().compareTo(new KualiInteger(-999999999)) <= 0) {
562 return BCConstants.REQUEST_IMPORT_FILE_PROCESSING_ERROR_MESSAGE_GENERIC + " " + lineNumber + ".";
563 }
564 if (budgetConstructionRequestMove.getFinancialDocumentMonth6LineAmount().compareTo(new KualiInteger(999999999)) >= 0 || budgetConstructionRequestMove.getFinancialDocumentMonth6LineAmount().compareTo(new KualiInteger(-999999999)) <= 0) {
565 return BCConstants.REQUEST_IMPORT_FILE_PROCESSING_ERROR_MESSAGE_GENERIC + " " + lineNumber + ".";
566 }
567 if (budgetConstructionRequestMove.getFinancialDocumentMonth7LineAmount().compareTo(new KualiInteger(999999999)) >= 0 || budgetConstructionRequestMove.getFinancialDocumentMonth7LineAmount().compareTo(new KualiInteger(-999999999)) <= 0) {
568 return BCConstants.REQUEST_IMPORT_FILE_PROCESSING_ERROR_MESSAGE_GENERIC + " " + lineNumber + ".";
569 }
570 if (budgetConstructionRequestMove.getFinancialDocumentMonth8LineAmount().compareTo(new KualiInteger(999999999)) >= 0 || budgetConstructionRequestMove.getFinancialDocumentMonth8LineAmount().compareTo(new KualiInteger(-999999999)) <= 0) {
571 return BCConstants.REQUEST_IMPORT_FILE_PROCESSING_ERROR_MESSAGE_GENERIC + " " + lineNumber + ".";
572 }
573 if (budgetConstructionRequestMove.getFinancialDocumentMonth9LineAmount().compareTo(new KualiInteger(999999999)) >= 0 || budgetConstructionRequestMove.getFinancialDocumentMonth9LineAmount().compareTo(new KualiInteger(-999999999)) <= 0) {
574 return BCConstants.REQUEST_IMPORT_FILE_PROCESSING_ERROR_MESSAGE_GENERIC + " " + lineNumber + ".";
575 }
576 if (budgetConstructionRequestMove.getFinancialDocumentMonth10LineAmount().compareTo(new KualiInteger(999999999)) >= 0 || budgetConstructionRequestMove.getFinancialDocumentMonth10LineAmount().compareTo(new KualiInteger(-999999999)) <= 0) {
577 return BCConstants.REQUEST_IMPORT_FILE_PROCESSING_ERROR_MESSAGE_GENERIC + " " + lineNumber + ".";
578 }
579 if (budgetConstructionRequestMove.getFinancialDocumentMonth11LineAmount().compareTo(new KualiInteger(999999999)) >= 0 || budgetConstructionRequestMove.getFinancialDocumentMonth11LineAmount().compareTo(new KualiInteger(-999999999)) <= 0) {
580 return BCConstants.REQUEST_IMPORT_FILE_PROCESSING_ERROR_MESSAGE_GENERIC + " " + lineNumber + ".";
581 }
582 if (budgetConstructionRequestMove.getFinancialDocumentMonth12LineAmount().compareTo(new KualiInteger(999999999)) >= 0 || budgetConstructionRequestMove.getFinancialDocumentMonth12LineAmount().compareTo(new KualiInteger(-999999999)) <= 0) {
583 return BCConstants.REQUEST_IMPORT_FILE_PROCESSING_ERROR_MESSAGE_GENERIC + " " + lineNumber + ".";
584 }
585 }
586
587 return "";
588 }
589
590 protected ObjectCode getObjectCode(BudgetConstructionRequestMove record, Integer budgetYear) {
591 Map searchCriteria = new HashMap();
592
593 searchCriteria.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, budgetYear);
594 searchCriteria.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, record.getChartOfAccountsCode());
595 searchCriteria.put(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, record.getFinancialObjectCode());
596
597 List<ObjectCode> objectList = new ArrayList<ObjectCode>(businessObjectService.findMatching(ObjectCode.class, searchCriteria));
598
599 if (objectList.size() == 1)
600 return objectList.get(0);
601
602 return null;
603 }
604
605 protected SubObjectCode getSubObjectCode(BudgetConstructionRequestMove record, Integer budgetYear) {
606 Map searchCriteria = new HashMap();
607
608 searchCriteria.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, budgetYear);
609 searchCriteria.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, record.getChartOfAccountsCode());
610 searchCriteria.put(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, record.getFinancialObjectCode());
611 searchCriteria.put(KFSPropertyConstants.ACCOUNT_NUMBER, record.getAccountNumber());
612 searchCriteria.put(KFSPropertyConstants.FINANCIAL_SUB_OBJECT_CODE, record.getFinancialSubObjectCode());
613
614 List<SubObjectCode> objectList = new ArrayList<SubObjectCode> (this.businessObjectService.findMatching(SubObjectCode.class, searchCriteria));
615
616 if (objectList.size() == 1)
617 return objectList.get(0);
618
619 return null;
620 }
621
622 protected List<BudgetConstructionFundingLock> findBudgetLocks(BudgetConstructionRequestMove record, Integer budgetYear) {
623 Map searchCriteria = new HashMap();
624
625 searchCriteria.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, budgetYear);
626 searchCriteria.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, record.getChartOfAccountsCode());
627 searchCriteria.put(KFSPropertyConstants.ACCOUNT_NUMBER, record.getAccountNumber());
628 searchCriteria.put(KFSPropertyConstants.SUB_ACCOUNT_NUMBER, record.getSubAccountNumber());
629
630 List<BudgetConstructionFundingLock> lockList = new ArrayList<BudgetConstructionFundingLock> (this.businessObjectService.findMatching(BudgetConstructionFundingLock.class, searchCriteria));
631
632 return lockList;
633 }
634
635 List<BudgetConstructionMonthly> getMonthlyRecords(BudgetConstructionRequestMove record, BudgetConstructionHeader header) {
636 Map searchCriteria = new HashMap();
637
638 searchCriteria.put(KFSPropertyConstants.DOCUMENT_NUMBER, header.getDocumentNumber());
639 searchCriteria.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, header.getUniversityFiscalYear());
640 searchCriteria.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, record.getChartOfAccountsCode());
641 searchCriteria.put(KFSPropertyConstants.ACCOUNT_NUMBER, record.getAccountNumber());
642 searchCriteria.put(KFSPropertyConstants.SUB_ACCOUNT_NUMBER, record.getSubAccountNumber());
643 searchCriteria.put(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, record.getFinancialObjectCode());
644 searchCriteria.put(KFSPropertyConstants.FINANCIAL_SUB_OBJECT_CODE, record.getFinancialSubObjectCode());
645 searchCriteria.put(KFSPropertyConstants.FINANCIAL_OBJECT_TYPE_CODE, record.getFinancialObjectTypeCode());
646 searchCriteria.put(KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE, KFSConstants.BALANCE_TYPE_BASE_BUDGET);
647
648 return new ArrayList<BudgetConstructionMonthly> (this.businessObjectService.findMatching(BudgetConstructionMonthly.class, searchCriteria));
649 }
650
651 /**
652 * Clears BudgetConstructionRequestMove
653 *
654 * @param principalId
655 */
656 protected void deleteBudgetConstructionMoveRecords(String principalId) {
657 Map<String, String> fieldValues = new HashMap<String, String>();
658 fieldValues.put(KFSPropertyConstants.PERSON_UNIVERSAL_IDENTIFIER, principalId);
659 businessObjectService.deleteMatching(BudgetConstructionRequestMove.class, fieldValues);
660 }
661
662 /**
663 *
664 * @see org.kuali.kfs.module.bc.document.service.BudgetRequestImportService#setDictionaryValidationService(org.kuali.rice.kns.service.DictionaryValidationService)
665 */
666 @NonTransactional
667 public void setDictionaryValidationService(DictionaryValidationService dictionaryValidationService) {
668 this.dictionaryValidationService = dictionaryValidationService;
669
670 }
671
672 /**
673 *
674 * @see org.kuali.kfs.module.bc.document.service.BudgetRequestImportService#setLockService(org.kuali.kfs.module.bc.document.service.LockService)
675 */
676 @NonTransactional
677 public void setLockService(LockService lockService) {
678 this.lockService = lockService;
679 }
680
681 /**
682 * Sets BudgetDocumentService
683 *
684 * @param budgetDocumentService
685 */
686 @NonTransactional
687 public void setBudgetDocumentService(BudgetDocumentService budgetDocumentService) {
688 this.budgetDocumentService = budgetDocumentService;
689 }
690
691 @NonTransactional
692 public void setLaborModuleService(LaborModuleService laborModuleService) {
693 this.laborModuleService = laborModuleService;
694 }
695
696 @NonTransactional
697 public LaborModuleService getLaborModuleService() {
698 return this.laborModuleService;
699 }
700
701 @NonTransactional
702 public BudgetParameterService getBudgetParameterService() {
703 return budgetParameterService;
704 }
705
706 @NonTransactional
707 public void setBudgetParameterService(BudgetParameterService budgetParameterService) {
708 this.budgetParameterService = budgetParameterService;
709 }
710
711 @NonTransactional
712 public OptionsService getOptionsService() {
713 return optionsService;
714 }
715
716 @NonTransactional
717 public void setOptionsService(OptionsService optionsService) {
718 this.optionsService = optionsService;
719 }
720
721 @NonTransactional
722 public DocumentHelperService getDocumentHelperService() {
723 return documentHelperService;
724 }
725
726 @NonTransactional
727 public void setDocumentHelperService(DocumentHelperService documentHelperService) {
728 this.documentHelperService = documentHelperService;
729 }
730
731 @NonTransactional
732 protected DocumentService getDocumentService() {
733 return documentService;
734 }
735
736 @NonTransactional
737 public void setDocumentService(DocumentService documentService) {
738 this.documentService = documentService;
739 }
740
741 }
742