001/* 002 * Copyright 2006 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 */ 016package org.kuali.ole.fp.document.web.struts; 017 018import java.io.FileNotFoundException; 019import java.io.IOException; 020import java.util.ArrayList; 021import java.util.Collections; 022import java.util.List; 023 024import javax.servlet.http.HttpServletRequest; 025import javax.servlet.http.HttpServletResponse; 026 027import org.apache.struts.action.ActionForm; 028import org.apache.struts.action.ActionForward; 029import org.apache.struts.action.ActionMapping; 030import org.kuali.ole.fp.businessobject.CapitalAccountingLines; 031import org.kuali.ole.fp.businessobject.CapitalAssetAccountsGroupDetails; 032import org.kuali.ole.fp.businessobject.CapitalAssetInformation; 033import org.kuali.ole.fp.businessobject.CapitalAssetInformationDetail; 034import org.kuali.ole.fp.businessobject.options.CapitalAccountingLinesComparator; 035import org.kuali.ole.fp.document.CapitalAccountingLinesDocumentBase; 036import org.kuali.ole.fp.document.validation.event.CapitalAccountingLinesSameObjectCodeSubTypeEvent; 037import org.kuali.ole.integration.cab.CapitalAssetBuilderModuleService; 038import org.kuali.ole.sys.OLEConstants; 039import org.kuali.ole.sys.OLEKeyConstants; 040import org.kuali.ole.sys.businessobject.AccountingLine; 041import org.kuali.ole.sys.businessobject.SourceAccountingLine; 042import org.kuali.ole.sys.businessobject.TargetAccountingLine; 043import org.kuali.ole.sys.context.SpringContext; 044import org.kuali.ole.sys.document.AccountingDocument; 045import org.kuali.ole.sys.web.struts.KualiAccountingDocumentFormBase; 046import org.kuali.rice.core.api.config.property.ConfigurationService; 047import org.kuali.rice.core.api.util.RiceConstants; 048import org.kuali.rice.kew.api.exception.WorkflowException; 049import org.kuali.rice.kns.question.ConfirmationQuestion; 050import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase; 051import org.kuali.rice.kns.web.struts.form.KualiForm; 052import org.kuali.rice.krad.document.Document; 053import org.kuali.rice.krad.service.KualiRuleService; 054import org.kuali.rice.krad.util.GlobalVariables; 055import org.kuali.rice.krad.util.ObjectUtils; 056 057/** 058 * This is the action class for the CapitalAccountingLinesActionBase. 059 */ 060public abstract class CapitalAccountingLinesActionBase extends CapitalAssetInformationActionBase { 061 private CapitalAssetBuilderModuleService capitalAssetBuilderModuleService = SpringContext.getBean(CapitalAssetBuilderModuleService.class); 062 063 /** 064 * removes capitalaccountinglines which is a transient bo.. and call the super method to 065 * create a error correction document. 066 * @see org.kuali.ole.sys.document.web.struts.FinancialSystemTransactionalDocumentActionBase#correct(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) 067 */ 068 @Override 069 public ActionForward correct(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 070 CapitalAccountingLinesFormBase capitalAccountingLinesFormBase = (CapitalAccountingLinesFormBase) form; 071 CapitalAccountingLinesDocumentBase caldb = (CapitalAccountingLinesDocumentBase) capitalAccountingLinesFormBase.getFinancialDocument(); 072 caldb.getCapitalAccountingLines().clear(); 073 074 super.correct(mapping, capitalAccountingLinesFormBase, request, response); 075 076 KualiAccountingDocumentFormBase kadfb = (KualiAccountingDocumentFormBase) form; 077 List<CapitalAssetInformation> currentCapitalAssetInformation = this.getCurrentCapitalAssetInformationObject(kadfb); 078 for (CapitalAssetInformation capitalAsset : currentCapitalAssetInformation) { 079 capitalAsset.setCapitalAssetProcessedIndicator(false); 080 capitalAsset.setCapitalAssetLineAmount(capitalAsset.getCapitalAssetLineAmount().negated()); 081 //remove capital asset tag/location asset tag number and serial number as 082 //they will fail because these values will be duplicates. 083 List<CapitalAssetInformationDetail> tagLocationDetails = capitalAsset.getCapitalAssetInformationDetails(); 084 for (CapitalAssetInformationDetail tagLocationDetail : tagLocationDetails) { 085 tagLocationDetail.setCapitalAssetTagNumber(null); 086 tagLocationDetail.setCapitalAssetSerialNumber(null); 087 } 088 089 List<CapitalAssetAccountsGroupDetails> groupAccountLines = capitalAsset.getCapitalAssetAccountsGroupDetails(); 090 for (CapitalAssetAccountsGroupDetails groupAccountLine : groupAccountLines) { 091 groupAccountLine.setAmount(groupAccountLine.getAmount().negated()); 092 } 093 } 094 095 String distributionAmountCode = capitalAccountingLinesFormBase.getCapitalAccountingLine().getDistributionCode(); 096 097 AccountingDocument tdoc = (AccountingDocument) capitalAccountingLinesFormBase.getDocument(); 098 099 List<CapitalAccountingLines> capitalAccountingLines = new ArrayList(); 100 //for every source/target accounting line that has an object code that requires a 101 //capital asset, creates a capital accounting line that the user can select to 102 //perform create or modify asset functions. 103 createCapitalAccountingLines(capitalAccountingLines, tdoc, distributionAmountCode); 104 sortCaptitalAccountingLines(capitalAccountingLines); 105 106 caldb.setCapitalAccountingLines(capitalAccountingLines); 107 //checks capital accounting lines for capital assets and if so checks the select box 108 checkSelectForCapitalAccountingLines(capitalAccountingLinesFormBase); 109 110 checkCapitalAccountingLinesSelected(capitalAccountingLinesFormBase); 111 calculatePercentsForSelectedCapitalAccountingLines(capitalAccountingLinesFormBase); 112 113 //setup the initial next sequence number column.. 114 setupIntialNextCapitalAssetLineNumber(capitalAccountingLinesFormBase); 115 116 return mapping.findForward(RiceConstants.MAPPING_BASIC); 117 } 118 119 /** 120 * All document-load operations get routed through here 121 * 122 * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#loadDocument(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase) 123 */ 124 @Override 125 protected void loadDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException { 126 super.loadDocument(kualiDocumentFormBase); 127 128 CapitalAccountingLinesFormBase capitalAccountingLinesFormBase = (CapitalAccountingLinesFormBase) kualiDocumentFormBase; 129 String distributionAmountCode = capitalAccountingLinesFormBase.getCapitalAccountingLine().getDistributionCode(); 130 131 AccountingDocument tdoc = (AccountingDocument) kualiDocumentFormBase.getDocument(); 132 133 List<CapitalAccountingLines> capitalAccountingLines = new ArrayList(); 134 //for every source/target accounting line that has an object code that requires a 135 //capital asset, creates a capital accounting line that the user can select to 136 //perform create or modify asset functions. 137 createCapitalAccountingLines(capitalAccountingLines, tdoc, distributionAmountCode); 138 sortCaptitalAccountingLines(capitalAccountingLines); 139 140 CapitalAccountingLinesDocumentBase caldb = (CapitalAccountingLinesDocumentBase) tdoc; 141 caldb.setCapitalAccountingLines(capitalAccountingLines); 142 //checks capital accounting lines for capital assets and if so checks the select box 143 checkSelectForCapitalAccountingLines(capitalAccountingLinesFormBase); 144 145 checkCapitalAccountingLinesSelected(capitalAccountingLinesFormBase); 146 calculatePercentsForSelectedCapitalAccountingLines(capitalAccountingLinesFormBase); 147 148 //setup the initial next sequence number column.. 149 setupIntialNextCapitalAssetLineNumber(kualiDocumentFormBase); 150 151 KualiForm kualiForm = kualiDocumentFormBase; 152 //based on the records in capital accounting lines, capital asset information lists 153 //set the tabs to open if lists not empty else set to close 154 setTabStatesForCapitalAssets(kualiForm); 155 } 156 157 /** 158 * 159 * @see org.kuali.rice.kns.web.struts.action.KualiAction#refresh(org.apache.struts.action.ActionMapping, 160 * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) 161 */ 162 // @Override 163 @Override 164 public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 165 super.refresh(mapping, form, request, response); 166 167 CapitalAccountingLinesFormBase capitalAccountingLinesFormBase = (CapitalAccountingLinesFormBase) form; 168 CapitalAccountingLinesDocumentBase caldb = (CapitalAccountingLinesDocumentBase) capitalAccountingLinesFormBase.getFinancialDocument(); 169 170 List<CapitalAccountingLines> capitalAccountingLines = caldb.getCapitalAccountingLines(); 171 KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form; 172 AccountingDocument tdoc = (AccountingDocument) kualiDocumentFormBase.getDocument(); 173 174 capitalAccountingLines = updateCapitalAccountingLines(capitalAccountingLines, tdoc); 175 sortCaptitalAccountingLines(capitalAccountingLines); 176 caldb.setCapitalAccountingLines(capitalAccountingLines); 177 178 //now remove distributed accounting lines if they are not in the capital 179 //accounting lines list. 180 181 KualiAccountingDocumentFormBase kadfb = (KualiAccountingDocumentFormBase) form; 182 List<CapitalAssetInformation> currentCapitalAssetInformation = this.getCurrentCapitalAssetInformationObject(kadfb); 183 184 removeOrphanDisributedAccountingLines(capitalAccountingLines, currentCapitalAssetInformation); 185 checkCapitalAccountingLinesSelected(capitalAccountingLinesFormBase); 186 setTabStatesForCapitalAssets(form); 187 188 return mapping.findForward(OLEConstants.MAPPING_BASIC); 189 } 190 191 /** 192 * When user adds an accounting line to the either source or target, if the object code on 193 * that line has capital object type code group then a capital accounting line is created. 194 * @see org.kuali.ole.sys.web.struts.KualiAccountingDocumentActionBase#insertAccountingLine(boolean, org.kuali.ole.sys.web.struts.KualiAccountingDocumentFormBase, org.kuali.ole.sys.businessobject.AccountingLine) 195 */ 196 @Override 197 protected void insertAccountingLine(boolean isSource, KualiAccountingDocumentFormBase financialDocumentForm, AccountingLine line) { 198 super.insertAccountingLine(isSource, financialDocumentForm, line); 199 200 CapitalAccountingLinesFormBase capitalAccountingLinesFormBase = (CapitalAccountingLinesFormBase) financialDocumentForm; 201 CapitalAccountingLinesDocumentBase caldb = (CapitalAccountingLinesDocumentBase) capitalAccountingLinesFormBase.getFinancialDocument(); 202 String distributionAmountCode = capitalAccountingLinesFormBase.getCapitalAccountingLine().getDistributionCode(); 203 204 List<CapitalAccountingLines> capitalAccountingLines = caldb.getCapitalAccountingLines(); 205 206 //create the corresponding capital accounting line and then 207 //sort the capital accounting lines by object code and account number 208 createCapitalAccountingLine(capitalAccountingLines, line, distributionAmountCode); 209 sortCaptitalAccountingLines(capitalAccountingLines); 210 211 KualiForm kualiForm = financialDocumentForm; 212 //sets the tab states for create/modify capital asset tabs... 213 setTabStatesForCapitalAssets(kualiForm); 214 } 215 216 /** 217 * When user deletes an accounting line to the either source or target, the corresponding line in 218 * capital accounting line is deleted and the distributed accounting line under the 219 * created or modified capital asset line. When a capital asset does not have any 220 * accounting lines, the capital asset is removed. 221 * @see org.kuali.ole.sys.web.struts.KualiAccountingDocumentActionBase#deleteAccountingLine(boolean, org.kuali.ole.sys.web.struts.KualiAccountingDocumentFormBase, int) 222 */ 223 @Override 224 protected void deleteAccountingLine(boolean isSource, KualiAccountingDocumentFormBase financialDocumentForm, int deleteIndex) { 225 226 CapitalAccountingLinesFormBase capitalAccountingLinesFormBase = (CapitalAccountingLinesFormBase) financialDocumentForm; 227 CapitalAccountingLinesDocumentBase caldb = (CapitalAccountingLinesDocumentBase) capitalAccountingLinesFormBase.getFinancialDocument(); 228 229 List<CapitalAccountingLines> capitalAccountingLines = caldb.getCapitalAccountingLines(); 230 231 if (isSource) { 232 // remove from capital accounting lines for this source line 233 AccountingLine line = (AccountingLine) financialDocumentForm.getFinancialDocument().getSourceAccountingLines().get(deleteIndex); 234 deleteCapitalAccountingLine(capitalAccountingLines, line); 235 deleteCapitalAssetLines(financialDocumentForm, line); 236 } 237 else { 238 // remove from document 239 AccountingLine line = (AccountingLine) financialDocumentForm.getFinancialDocument().getTargetAccountingLines().get(deleteIndex); 240 deleteCapitalAccountingLine(capitalAccountingLines, line); 241 deleteCapitalAssetLines(financialDocumentForm, line); 242 } 243 244 super.deleteAccountingLine(isSource, financialDocumentForm, deleteIndex); 245 sortCaptitalAccountingLines(capitalAccountingLines); 246 247 KualiForm kualiForm = financialDocumentForm; 248 249 //checks capital accounting lines for capital assets and if so checks the select box 250 checkSelectForCapitalAccountingLines(capitalAccountingLinesFormBase); 251 checkCapitalAccountingLinesSelected(capitalAccountingLinesFormBase); 252 calculatePercentsForSelectedCapitalAccountingLines(capitalAccountingLinesFormBase); 253 setTabStatesForCapitalAssets(kualiForm); 254 } 255 256 /** 257 * After uploading the accounting lines, the capital accounting lines will be created from these. 258 * @see org.kuali.ole.sys.web.struts.KualiAccountingDocumentActionBase#uploadAccountingLines(boolean, org.apache.struts.action.ActionForm) 259 */ 260 @Override 261 protected void uploadAccountingLines(boolean isSource, ActionForm form) throws FileNotFoundException, IOException { 262 super.uploadAccountingLines(isSource, form); 263 264 KualiAccountingDocumentFormBase kualiAccountingDocumentFormBase = (KualiAccountingDocumentFormBase) form; 265 CapitalAccountingLinesFormBase capitalAccountingLinesFormBase = (CapitalAccountingLinesFormBase) form; 266 CapitalAccountingLinesDocumentBase caldb = (CapitalAccountingLinesDocumentBase) capitalAccountingLinesFormBase.getFinancialDocument(); 267 268 String distributionAmountCode = capitalAccountingLinesFormBase.getCapitalAccountingLine().getDistributionCode(); 269 270 List<CapitalAccountingLines> capitalAccountingLines = caldb.getCapitalAccountingLines(); 271 AccountingDocument tdoc = (AccountingDocument) kualiAccountingDocumentFormBase.getDocument(); 272 273 createCapitalAccountingLines(capitalAccountingLines, tdoc, distributionAmountCode); 274 sortCaptitalAccountingLines(capitalAccountingLines); 275 276 KualiForm kualiForm = (KualiForm) form; 277 setTabStatesForCapitalAssets(kualiForm); 278 } 279 280 /** 281 * creates the capital accounting lines looking at source and/or target accounting lines. 282 * 283 * @param capitalAccountingLines 284 * @param tdoc 285 * @param distributionAmountCode distribution amount code for the line 286 */ 287 protected void createCapitalAccountingLines(List<CapitalAccountingLines> capitalAccountingLines, AccountingDocument tdoc, String distributionAmountCode) { 288 List<SourceAccountingLine> sourceAccountLines = tdoc.getSourceAccountingLines(); 289 290 CapitalAccountingLinesDocumentBase caldb = (CapitalAccountingLinesDocumentBase) tdoc; 291 292 for (SourceAccountingLine line : sourceAccountLines) { 293 //create source capital accounting line 294 createCapitalAccountingLine(capitalAccountingLines, line, distributionAmountCode); 295 } 296 297 List<TargetAccountingLine> targetAccountLines = tdoc.getTargetAccountingLines(); 298 299 for (TargetAccountingLine line : targetAccountLines) { 300 // create target capital accounting line 301 createCapitalAccountingLine(capitalAccountingLines, line, distributionAmountCode); 302 } 303 304 //sort the capital accounting lines collection 305 sortCaptitalAccountingLines(capitalAccountingLines); 306 } 307 308 /** 309 * updates the capital accounting lines looking at source and/or target accounting lines. 310 * 311 * @param capitalAccountingLines 312 * @param tdoc 313 */ 314 protected List<CapitalAccountingLines> updateCapitalAccountingLines(List<CapitalAccountingLines> capitalAccountingLines, AccountingDocument tdoc) { 315 List<SourceAccountingLine> sourceAccountLines = tdoc.getSourceAccountingLines(); 316 317 for (SourceAccountingLine line : sourceAccountLines) { 318 //updates source capital accounting line 319 updateCapitalAccountingLine(capitalAccountingLines, line); 320 } 321 322 List<TargetAccountingLine> targetAccountLines = tdoc.getTargetAccountingLines(); 323 324 for (TargetAccountingLine line : targetAccountLines) { 325 //updates source capital accounting line 326 updateCapitalAccountingLine(capitalAccountingLines, line); 327 } 328 329 //remove the orphan capital accounting lines that does not have corresponding 330 //accounting line from either source or target. 331 return removeOrphanCapitalAccountingLines(capitalAccountingLines, tdoc); 332 } 333 334 /** 335 * updates the capital accounting lines looking at source and/or target accounting lines. 336 * Removes any capital accounting line that does not have a corresponding 337 * source or target accounting line. 338 * @param capitalAccountingLines 339 * @param tdoc 340 */ 341 protected List<CapitalAccountingLines> removeOrphanCapitalAccountingLines(List<CapitalAccountingLines> capitalAccountingLines, AccountingDocument tdoc) { 342 List<CapitalAccountingLines> newCapitalAccountingLines = new ArrayList<CapitalAccountingLines>(); 343 if ( capitalAccountingLines != null ) { 344 List<AccountingLine> sourceAccountLines = tdoc.getSourceAccountingLines(); 345 for (CapitalAccountingLines capitalAccountingLine : capitalAccountingLines) { 346 if (removeOrphanCapitalAccountingLine(sourceAccountLines, capitalAccountingLine)) { 347 newCapitalAccountingLines.add(capitalAccountingLine); 348 } 349 } 350 351 List<AccountingLine> targetAccountLines = tdoc.getTargetAccountingLines(); 352 for (CapitalAccountingLines capitalAccountingLine : capitalAccountingLines) { 353 if (removeOrphanCapitalAccountingLine(targetAccountLines, capitalAccountingLine)) { 354 newCapitalAccountingLines.add(capitalAccountingLine); 355 } 356 } 357 } 358 return newCapitalAccountingLines; 359 } 360 361 /** 362 * If the line exists in capital accounting lines, and that line does not exist in 363 * accounting lines (source or target) then remove the line from capital accounting lines. 364 * 365 * @param capitalAccountingLines 366 * @param line to remove 367 * @return true if the capital accounting line to be removed is found in accounting lines, else false 368 */ 369 protected boolean removeOrphanCapitalAccountingLine(List<AccountingLine> accountLines, CapitalAccountingLines capitalAccountingLine) { 370 boolean found = false; 371 372 for (AccountingLine accountingLine : accountLines) { 373 if (capitalAccountingLine.getChartOfAccountsCode().equals(accountingLine.getChartOfAccountsCode()) && 374 capitalAccountingLine.getAccountNumber().equals(accountingLine.getAccountNumber()) && 375 capitalAccountingLine.getFinancialObjectCode().equals(accountingLine.getFinancialObjectCode()) && 376 capitalAccountingLine.getLineType().equalsIgnoreCase(accountingLine instanceof SourceAccountingLine ? OLEConstants.SOURCE : OLEConstants.TARGET)) { 377 found = true; 378 } 379 } 380 381 return found; 382 } 383 384 /** 385 * Method to check for any distributed accounting lines that are not listed in the 386 * capital accounting lines and remove them. 387 * 388 * @param capitalAccountingLines 389 * @param capitalAssets 390 */ 391 protected void removeOrphanDisributedAccountingLines(List<CapitalAccountingLines> capitalAccountingLines, List<CapitalAssetInformation> capitalAssets) { 392 List<CapitalAssetInformation> removalCaiList = new ArrayList<CapitalAssetInformation>(); 393 394 for (CapitalAssetInformation capitalAsset : capitalAssets) { 395 removeOrphanDisributedAccountingLine(capitalAccountingLines, capitalAsset); 396 if (capitalAsset.getCapitalAssetAccountsGroupDetails().size() == 0) { 397 capitalAsset.getCapitalAssetInformationDetails().clear(); 398 removalCaiList.add(capitalAsset); 399 } 400 } 401 //if the removal list is not empty, remove these bunch of capital asset records 402 //for that accounting line. 403 if (ObjectUtils.isNotNull(removalCaiList)) { 404 capitalAssets.removeAll(removalCaiList); 405 } 406 } 407 408 /** 409 * Method to check for any distributed accounting line for a given capital 410 * accounting line that are not listed in the capital assets accounting lines and remove it. 411 * 412 * @param capitalAccountingLines 413 * @param capitalAsset 414 */ 415 protected void removeOrphanDisributedAccountingLine(List<CapitalAccountingLines> capitalAccountingLines, CapitalAssetInformation capitalAsset) { 416 List<CapitalAssetAccountsGroupDetails> groupAccountLines = capitalAsset.getCapitalAssetAccountsGroupDetails(); 417 CapitalAssetAccountsGroupDetails accountLineToDelete = null; 418 419 for (CapitalAssetAccountsGroupDetails groupAccountLine : groupAccountLines) { 420 if (!checkDistributedAccountingLineExists(capitalAccountingLines, groupAccountLine)) { 421 accountLineToDelete = groupAccountLine; 422 break; 423 } 424 } 425 426 if (ObjectUtils.isNotNull(accountLineToDelete)) { 427 // remove all the group accounting lines so that the asset line can be removed. 428 capitalAsset.getCapitalAssetAccountsGroupDetails().clear(); 429 } 430 } 431 432 /** 433 * checks capital accounting lines again the distributed accounting line and if found 434 * return true else false so that this distributed accounting line may be removed. 435 * 436 * @param capitalAccountingLines 437 * @param groupAccountLine 438 * @return true if accounting line exists else return false 439 */ 440 protected boolean checkDistributedAccountingLineExists(List<CapitalAccountingLines> capitalAccountingLines, CapitalAssetAccountsGroupDetails groupAccountLine) { 441 boolean exists = false; 442 443 for (CapitalAccountingLines capitalAccountingLine : capitalAccountingLines) { 444 if (groupAccountLine.getSequenceNumber().compareTo(capitalAccountingLine.getSequenceNumber()) == 0 && 445 groupAccountLine.getFinancialDocumentLineTypeCode().equals(OLEConstants.SOURCE.equals(capitalAccountingLine.getLineType()) ? OLEConstants.SOURCE_ACCT_LINE_TYPE_CODE : OLEConstants.TARGET_ACCT_LINE_TYPE_CODE) && 446 groupAccountLine.getChartOfAccountsCode().equals(capitalAccountingLine.getChartOfAccountsCode()) && 447 groupAccountLine.getAccountNumber().equals(capitalAccountingLine.getAccountNumber()) && 448 groupAccountLine.getFinancialObjectCode().equals(capitalAccountingLine.getFinancialObjectCode())) { 449 return true; 450 } 451 } 452 453 return false; 454 } 455 456 /** 457 * Checks if the accounting line has an object code that belongs to object sub type group codes and 458 * if so, creates a capital accounting line that will be displayed on the jsp. 459 * 460 * @param capitalAccountingLines 461 * @param line 462 * @param distributionAmountCode 463 * @return List of capitalAccountingLines 464 */ 465 protected List<CapitalAccountingLines> createCapitalAccountingLine(List<CapitalAccountingLines> capitalAccountingLines, AccountingLine line, String distributionAmountCode) { 466 Integer sequenceNumber = capitalAccountingLines.size() + 1; 467 468 if (capitalAssetBuilderModuleService.hasCapitalAssetObjectSubType(line)) { 469 //capital object code so we need to build the capital accounting line... 470 CapitalAccountingLines cal = addCapitalAccountingLine(capitalAccountingLines, line); 471 cal.setDistributionAmountCode(distributionAmountCode); 472 capitalAccountingLines.add(cal); 473 } 474 475 return capitalAccountingLines; 476 } 477 478 /** 479 * Checks if the accounting line exits in the capital accounting lines 480 * and if so, updates the other information. 481 * else inserts a new record into the collection 482 * 483 * @param capitalAccountingLines 484 * @param line 485 * @return List of capitalAccountingLines 486 */ 487 protected void updateCapitalAccountingLine(List<CapitalAccountingLines> capitalAccountingLines, AccountingLine line) { 488 boolean found = false; 489 490 for (CapitalAccountingLines capitalAccountingLine : capitalAccountingLines) { 491 if (capitalAccountingLine.getChartOfAccountsCode().equals(line.getChartOfAccountsCode()) && 492 capitalAccountingLine.getAccountNumber().equals(line.getAccountNumber()) && 493 capitalAccountingLine.getFinancialObjectCode().equals(line.getFinancialObjectCode()) && 494 capitalAccountingLine.getLineType().equalsIgnoreCase(line instanceof SourceAccountingLine ? OLEConstants.SOURCE : OLEConstants.TARGET) && 495 capitalAccountingLine.getSequenceNumber().compareTo(line.getSequenceNumber()) == 0) { 496 capitalAccountingLine.setFinancialSubObjectCode(line.getFinancialSubObjectCode()); 497 capitalAccountingLine.setSubAccountNumber(line.getSubAccountNumber()); 498 capitalAccountingLine.setProjectCode(line.getProjectCode()); 499 capitalAccountingLine.setOrganizationReferenceId(line.getOrganizationReferenceId()); 500 capitalAccountingLine.setAmount(line.getAmount()); 501 capitalAccountingLine.setFinancialDocumentLineDescription(line.getFinancialDocumentLineDescription()); 502 found = true; 503 break; 504 } 505 } 506 507 if (!found) { 508 //capital object code so we need to build the capital accounting line... 509 if (capitalAssetBuilderModuleService.hasCapitalAssetObjectSubType(line)) { 510 CapitalAccountingLines cal = addCapitalAccountingLine(capitalAccountingLines, line); 511 capitalAccountingLines.add(cal); 512 } 513 } 514 } 515 516 /** 517 * convenience method to add a new capital accounting line to the collection of capital 518 * accounting lines. 519 * 520 * @param capitalAccountingLines 521 * @param line 522 * @return cal newly created capital accounting line 523 */ 524 protected CapitalAccountingLines addCapitalAccountingLine(List<CapitalAccountingLines> capitalAccountingLines, AccountingLine line) { 525 CapitalAccountingLines cal = new CapitalAccountingLines(); 526 527 if (line instanceof SourceAccountingLine) { 528 cal.setLineType(OLEConstants.SOURCE); 529 } 530 else { 531 cal.setLineType(OLEConstants.TARGET); 532 } 533 cal.setSequenceNumber(line.getSequenceNumber()); 534 cal.setChartOfAccountsCode(line.getChartOfAccountsCode()); 535 cal.setAccountNumber(line.getAccountNumber()); 536 cal.setSubAccountNumber(line.getSubAccountNumber()); 537 cal.setFinancialObjectCode(line.getFinancialObjectCode()); 538 cal.setFinancialSubObjectCode(line.getFinancialSubObjectCode()); 539 cal.setProjectCode(line.getProjectCode()); 540 cal.setOrganizationReferenceId(line.getOrganizationReferenceId()); 541 cal.setFinancialDocumentLineDescription(line.getFinancialDocumentLineDescription()); 542 cal.setAmount(line.getAmount()); 543 cal.setAccountLinePercent(null); 544 cal.setSelectLine(false); 545 546 return cal; 547 } 548 549 /** 550 * If the line exists in capital accounting lines, that will be deleted. 551 * 552 * @param capitalAccountingLines 553 * @param line to remove 554 * @return List of capitalAccountingLines 555 */ 556 protected List<CapitalAccountingLines> deleteCapitalAccountingLine(List<CapitalAccountingLines> capitalAccountingLines, AccountingLine line) { 557 CapitalAccountingLines cal = null; 558 559 for (CapitalAccountingLines capitalAccountingLine : capitalAccountingLines) { 560 if (capitalAccountingLine.getChartOfAccountsCode().equals(line.getChartOfAccountsCode()) && 561 capitalAccountingLine.getAccountNumber().equals(line.getAccountNumber()) && 562 capitalAccountingLine.getFinancialObjectCode().equals(line.getFinancialObjectCode()) && 563 capitalAccountingLine.getLineType().equalsIgnoreCase(line instanceof SourceAccountingLine ? OLEConstants.SOURCE : OLEConstants.TARGET)) { 564 cal = capitalAccountingLine; 565 break; 566 } 567 } 568 569 if (ObjectUtils.isNotNull(cal)) { 570 capitalAccountingLines.remove(cal); 571 } 572 573 return capitalAccountingLines; 574 } 575 576 /** 577 * sort the capital accounting lines collection based on financial object code and account number. 578 * @param capitalAccountingLines List of capital accounting lines 579 */ 580 protected void sortCaptitalAccountingLines(List<CapitalAccountingLines> capitalAccountingLines) { 581 CapitalAccountingLinesComparator calComparator = new CapitalAccountingLinesComparator(); 582 583 //sort the collection based on financial object code and account number 584 Collections.sort(capitalAccountingLines, calComparator); 585 } 586 587 /** 588 * Action "create" creates assets for the selected capital 589 * accounting lines. An error message is shown if no capital accounting lines 590 * are selected for processing. The action checks if the selected 591 * capital accounting lines object sub type cross based on the system paramter 592 * values for the object subtypes and if so prompts the user to confirm to continue 593 * to create the assets for the select capital accounting lines. 594 * 595 * @param mapping 596 * @param form 597 * @param request 598 * @param response 599 * @return ActionForward 600 * @throws Exception 601 */ 602 public ActionForward createAsset(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 603 CapitalAccountingLinesFormBase calfb = (CapitalAccountingLinesFormBase) form; 604 String distributionAmountCode = calfb.getCapitalAccountingLine().getDistributionCode(); 605 if (OLEConstants.CapitalAssets.DISTRIBUTE_COST_EQUALLY_CODE.equals(distributionAmountCode)) { 606 calfb.setDistributeEqualAmount(true); 607 } 608 else { 609 calfb.setDistributeEqualAmount(false); 610 } 611 612 boolean createAction = calfb.getCapitalAccountingLine().isCanCreateAsset(); 613 calfb.setEditCreateOrModify(false); 614 615 GlobalVariables.getMessageMap().clearErrorMessages(); 616 if (!capitalAccountingLinesSelected(calfb)) { 617 GlobalVariables.getMessageMap().putError(OLEConstants.EDIT_ACCOUNTING_LINES_FOR_CAPITALIZATION_ERRORS, OLEKeyConstants.ERROR_DOCUMENT_ACCOUNTING_LINE_FOR_CAPITALIZATAION_REQUIRED_CREATE); 618 return mapping.findForward(OLEConstants.MAPPING_BASIC); 619 } 620 else { 621 calfb.setEditCreateOrModify(false); 622 } 623 624 Document document = calfb.getFinancialDocument(); 625 626 //if same object subtypes then continue creating capital assets.... 627 if (checkObjecSubTypeCrossingCapitalAccountingLines(document)) { 628 //question the user if to continue.... 629 ActionForward forward = performQuestionPrompt(mapping, form, request, response, OLEConstants.CapitalAssets.CAPITAL_ASSET_CREATE_ACTION_INDICATOR, distributionAmountCode); 630 if (forward != null) { 631 return forward; 632 } 633 } 634 else { 635 createCapitalAssetsForSelectedAccountingLines(form , calfb, OLEConstants.CapitalAssets.CAPITAL_ASSET_CREATE_ACTION_INDICATOR, distributionAmountCode); 636 } 637 638 //restore the tab states.... 639 setTabStatesForCapitalAssets(form); 640 641 return mapping.findForward(OLEConstants.MAPPING_BASIC); 642 } 643 644 /** 645 * Action "modify" creates assets for the selected capital 646 * accounting lines. An error message is shown if no capital accounting lines 647 * are selected for processing. The action checks if the selected 648 * capital accounting lines object sub type cross based on the system paramter 649 * values for the object subtypes and if so prompts the user to confirm to continue 650 * to create the assets for the select capital accounting lines. 651 * 652 * @param mapping 653 * @param form 654 * @param request 655 * @param response 656 * @return ActionForward 657 * @throws Exception 658 */ 659 public ActionForward modifyAsset(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 660 CapitalAccountingLinesFormBase calfb = (CapitalAccountingLinesFormBase) form; 661 String distributionAmountCode = calfb.getCapitalAccountingLine().getDistributionCode(); 662 663 if (OLEConstants.CapitalAssets.DISTRIBUTE_COST_EQUALLY_CODE.equals(distributionAmountCode)) { 664 calfb.setDistributeEqualAmount(true); 665 } 666 else { 667 calfb.setDistributeEqualAmount(false); 668 } 669 670 GlobalVariables.getMessageMap().clearErrorMessages(); 671 if (!capitalAccountingLinesSelected(calfb)) { 672 GlobalVariables.getMessageMap().putError(OLEConstants.EDIT_ACCOUNTING_LINES_FOR_CAPITALIZATION_ERRORS, OLEKeyConstants.ERROR_DOCUMENT_ACCOUNTING_LINE_FOR_CAPITALIZATAION_REQUIRED_MODIFY); 673 return mapping.findForward(OLEConstants.MAPPING_BASIC); 674 } 675 else { 676 calfb.setEditCreateOrModify(false); 677 } 678 679 Document document = calfb.getFinancialDocument(); 680 681 //if same object subtypes then continue creating capital assets.... 682 if (checkObjecSubTypeCrossingCapitalAccountingLines(document)) { 683 //question the user if to continue.... 684 ActionForward forward = performQuestionPrompt(mapping, form, request, response, OLEConstants.CapitalAssets.CAPITAL_ASSET_MODIFY_ACTION_INDICATOR, distributionAmountCode); 685 if (forward != null) { 686 return forward; 687 } 688 } 689 else { 690 createCapitalAssetsForSelectedAccountingLines(form , calfb, OLEConstants.CapitalAssets.CAPITAL_ASSET_MODIFY_ACTION_INDICATOR, distributionAmountCode); 691 } 692 693 //restore the tab states.... 694 setTabStatesForCapitalAssets(form); 695 696 return mapping.findForward(OLEConstants.MAPPING_BASIC); 697 } 698 699 /** 700 * Helper method to first calculate the percents for the selected capital accounting lines as 701 * the percent is required if the user is distributing the amounts by individual amount 702 * method. It then populates created or modified assets with asset accounting lines. 703 * 704 * @param form 705 * @param calfb 706 * @param actionTypeIndicator indicates whether creating an asset for "create" or "modify" actions. 707 * @param distributionAmountCode amount distribution code 708 */ 709 protected void createCapitalAssetsForSelectedAccountingLines(ActionForm form, CapitalAccountingLinesFormBase calfb, String actionTypeIndicator, String distributionAmountCode) { 710 calculatePercentsForSelectedCapitalAccountingLines(calfb); 711 createCapitalAssetForGroupAccountingLines(calfb, actionTypeIndicator, distributionAmountCode); 712 checkCapitalAccountingLinesSelected(calfb); 713 714 KualiForm kualiForm = (KualiForm) form; 715 setTabStatesForCapitalAssets(kualiForm); 716 } 717 718 719 /** 720 * checks the capital accounting lines if any of the lines have been selected for 721 * further processing. 722 * 723 * @param calfb 724 * @return selected return true if lines have been selected else return false 725 */ 726 protected boolean capitalAccountingLinesSelected(CapitalAccountingLinesFormBase calfb) { 727 boolean selected = false; 728 729 CapitalAccountingLinesDocumentBase caldb = (CapitalAccountingLinesDocumentBase) calfb.getFinancialDocument(); 730 List<CapitalAccountingLines> capitalAccountingLines = caldb.getCapitalAccountingLines(); 731 732 for (CapitalAccountingLines capitalAccountingLine : capitalAccountingLines) { 733 if (capitalAccountingLine.isSelectLine()) { 734 selected = true; 735 break; 736 } 737 } 738 739 return selected; 740 } 741 742 /** 743 * runs the validation to check if object subtypes crosses groups on 744 * selected capital accounting lines. 745 * 746 * @param form 747 * @return true if rule passed else false 748 */ 749 protected boolean checkObjecSubTypeCrossingCapitalAccountingLines(Document document) { 750 boolean differentObjecSubtypes = true; 751 differentObjecSubtypes &= getRuleService().applyRules(new CapitalAccountingLinesSameObjectCodeSubTypeEvent(document)); 752 753 return differentObjecSubtypes; 754 } 755 756 /** 757 * 758 * @param mapping An ActionMapping 759 * @param form An ActionForm 760 * @param request The HttpServletRequest 761 * @param response The HttpServletResponse 762 * @throws Exception 763 * @param distributionAmountCode 764 * @return An ActionForward 765 */ 766 protected ActionForward performQuestionPrompt(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String actionTypeCode, String distributionAmountCode) throws Exception { 767 ActionForward forward = null; 768 Object question = request.getParameter(OLEConstants.QUESTION_INST_ATTRIBUTE_NAME); 769 CapitalAccountingLinesFormBase calfb = (CapitalAccountingLinesFormBase) form; 770 771 if (question == null) { 772 String questionText = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(OLEKeyConstants.WARNING_NOT_SAME_OBJECT_SUB_TYPES); 773 return this.performQuestionWithoutInput(mapping, form, request, response, OLEConstants.OBJECT_SUB_TYPES_DIFFERENT_QUESTION, questionText, OLEConstants.CONFIRMATION_QUESTION, OLEConstants.ROUTE_METHOD, ""); 774 } 775 else { 776 Object buttonClicked = request.getParameter(OLEConstants.QUESTION_CLICKED_BUTTON); 777 // If the user replies 'Yes' the question, proceed.. 778 if (OLEConstants.OBJECT_SUB_TYPES_DIFFERENT_QUESTION.equals(question) && ConfirmationQuestion.YES.equals(buttonClicked)) { 779 createCapitalAssetsForSelectedAccountingLines(form , calfb, actionTypeCode, distributionAmountCode); 780 781 KualiForm kualiForm = (KualiForm) form; 782 setTabStatesForCapitalAssets(kualiForm); 783 784 return mapping.findForward(OLEConstants.MAPPING_BASIC); 785 786 } 787 // If the user replies 'No' to either of the questions 788 else { 789 uncheckCapitalAccountingLinesSelected(calfb); 790 forward = mapping.findForward(OLEConstants.MAPPING_BASIC); 791 } 792 } 793 794 return forward; 795 } 796 797 /** 798 * Get the rule service 799 * 800 * @return ruleService 801 */ 802 protected KualiRuleService getRuleService() { 803 return SpringContext.getBean(KualiRuleService.class); 804 } 805}