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.fp.businessobject; 017 018 import java.util.ArrayList; 019 import java.util.HashMap; 020 import java.util.Iterator; 021 import java.util.LinkedHashMap; 022 import java.util.List; 023 import java.util.Map; 024 025 import org.kuali.kfs.sys.KFSConstants; 026 import org.kuali.kfs.sys.context.SpringContext; 027 import org.kuali.rice.kns.bo.TransientBusinessObjectBase; 028 import org.kuali.rice.kns.service.DateTimeService; 029 import org.kuali.rice.kns.util.KualiDecimal; 030 031 /** 032 * This class represents a cashiering-related transaction used in the cash management document 033 */ 034 public class CashieringTransaction extends TransientBusinessObjectBase { 035 public static final String DETAIL_DOCUMENT_TYPE = "CM"; 036 037 private String campusCode; 038 private String referenceFinancialDocumentNumber; 039 040 // money in properties 041 private List<Check> moneyInChecks; 042 private CoinDetail moneyInCoin; 043 private CurrencyDetail moneyInCurrency; 044 private CashieringItemInProcess newItemInProcess; 045 private List<Check> baselineChecks; 046 private Check newCheck; 047 private KualiDecimal checkTotal; 048 049 // money out properties 050 private CoinDetail moneyOutCoin; 051 private CurrencyDetail moneyOutCurrency; 052 private List<CashieringItemInProcess> openItemsInProcess; 053 054 private java.util.Date transactionStarted; 055 private java.util.Date transactionEnded; 056 057 // incrementers for detail lines 058 private Integer nextCheckSequenceId; 059 060 061 /** 062 * Constructs a CashieringTransaction 063 */ 064 public CashieringTransaction(String campusCode, String referenceFinancialDocumentNumber) { 065 super(); 066 this.campusCode = campusCode; 067 this.referenceFinancialDocumentNumber = referenceFinancialDocumentNumber; 068 this.transactionStarted = SpringContext.getBean(DateTimeService.class).getCurrentDate(); 069 070 moneyInCoin = new CoinDetail(); 071 moneyInCurrency = new CurrencyDetail(); 072 073 moneyOutCoin = new CoinDetail(); 074 moneyOutCurrency = new CurrencyDetail(); 075 076 newItemInProcess = new CashieringItemInProcess(); 077 moneyInChecks = new ArrayList<Check>(); 078 newCheck = new CheckBase(); 079 baselineChecks = new ArrayList<Check>(); 080 openItemsInProcess = new ArrayList<CashieringItemInProcess>(); 081 nextCheckSequenceId = new Integer(1); 082 } 083 084 /** 085 * Gets the moneyInChecks attribute. 086 * 087 * @return Returns the moneyInChecks. 088 */ 089 public List<Check> getMoneyInChecks() { 090 return moneyInChecks; 091 } 092 093 /** 094 * Sets the moneyInChecks attribute value. 095 * 096 * @param moneyInChecks The moneyInChecks to set. 097 */ 098 public void setMoneyInChecks(List<Check> moneyInChecks) { 099 this.moneyInChecks = moneyInChecks; 100 } 101 102 /** 103 * Retrieves a specific check from the list, by array index 104 * 105 * @param index the index of the checks array to retrieve the check from 106 * @return a Check 107 */ 108 public Check getMoneyInCheck(int index) { 109 if (index >= moneyInChecks.size()) { 110 for (int i = moneyInChecks.size(); i <= index; i++) { 111 moneyInChecks.add(createNewCheck()); 112 } 113 } 114 return moneyInChecks.get(index); 115 } 116 117 /** 118 * Gets the moneyInCoin attribute. 119 * 120 * @return Returns the moneyInCoin. 121 */ 122 public CoinDetail getMoneyInCoin() { 123 return moneyInCoin; 124 } 125 126 /** 127 * Sets the moneyInCoin attribute value. 128 * 129 * @param moneyInCoin The moneyInCoin to set. 130 */ 131 public void setMoneyInCoin(CoinDetail moneyInCoin) { 132 this.moneyInCoin = moneyInCoin; 133 } 134 135 /** 136 * Gets the moneyInCurrency attribute. 137 * 138 * @return Returns the moneyInCurrency. 139 */ 140 public CurrencyDetail getMoneyInCurrency() { 141 return moneyInCurrency; 142 } 143 144 /** 145 * Sets the moneyInCurrency attribute value. 146 * 147 * @param moneyInCurrency The moneyInCurrency to set. 148 */ 149 public void setMoneyInCurrency(CurrencyDetail moneyInCurrency) { 150 this.moneyInCurrency = moneyInCurrency; 151 } 152 153 /** 154 * Gets the moneyOutCoin attribute. 155 * 156 * @return Returns the moneyOutCoin. 157 */ 158 public CoinDetail getMoneyOutCoin() { 159 return moneyOutCoin; 160 } 161 162 /** 163 * Sets the moneyOutCoin attribute value. 164 * 165 * @param moneyOutCoin The moneyOutCoin to set. 166 */ 167 public void setMoneyOutCoin(CoinDetail moneyOutCoin) { 168 this.moneyOutCoin = moneyOutCoin; 169 } 170 171 /** 172 * Gets the transactionEnded attribute. 173 * 174 * @return Returns the transactionEnded. 175 */ 176 public java.util.Date getTransactionEnded() { 177 return transactionEnded; 178 } 179 180 /** 181 * Sets the transactionEnded attribute value. 182 * 183 * @param transactionEnded The transactionEnded to set. 184 */ 185 public void setTransactionEnded(java.util.Date transactionEnded) { 186 this.transactionEnded = transactionEnded; 187 } 188 189 /** 190 * Gets the transactionStarted attribute. 191 * 192 * @return Returns the transactionStarted. 193 */ 194 public java.util.Date getTransactionStarted() { 195 return transactionStarted; 196 } 197 198 /** 199 * Sets the transactionStarted attribute value. 200 * 201 * @param transactionStarted The transactionStarted to set. 202 */ 203 public void setTransactionStarted(java.util.Date transactionStarted) { 204 this.transactionStarted = transactionStarted; 205 } 206 207 /** 208 * Gets the campusCode attribute. 209 * 210 * @return Returns the campusCode. 211 */ 212 public String getCampusCode() { 213 return campusCode; 214 } 215 216 /** 217 * Sets the campusCode attribute value. 218 * 219 * @param campusCode The campusCode to set. 220 */ 221 public void setCampusCode(String campusCode) { 222 this.campusCode = campusCode; 223 } 224 225 /** 226 * Sets the moneyOutCurrency attribute value. 227 * 228 * @param moneyOutCurrency The moneyOutCurrency to set. 229 */ 230 public void setMoneyOutCurrency(CurrencyDetail moneyOutCurrency) { 231 this.moneyOutCurrency = moneyOutCurrency; 232 } 233 234 /** 235 * Gets the referenceFinancialDocumentNumber attribute. 236 * 237 * @return Returns the referenceFinancialDocumentNumber. 238 */ 239 public String getReferenceFinancialDocumentNumber() { 240 return referenceFinancialDocumentNumber; 241 } 242 243 /** 244 * Sets the referenceFinancialDocumentNumber attribute value. 245 * 246 * @param referenceFinancialDocumentNumber The referenceFinancialDocumentNumber to set. 247 */ 248 public void setReferenceFinancialDocumentNumber(String referenceFinancialDocumentNumber) { 249 this.referenceFinancialDocumentNumber = referenceFinancialDocumentNumber; 250 } 251 252 /** 253 * Gets the moneyOutCurrency attribute. 254 * 255 * @return Returns the moneyOutCurrency. 256 */ 257 public CurrencyDetail getMoneyOutCurrency() { 258 return moneyOutCurrency; 259 } 260 261 /** 262 * Gets the newItemInProcess attribute. 263 * 264 * @return Returns the newItemInProcess. 265 */ 266 public CashieringItemInProcess getNewItemInProcess() { 267 return newItemInProcess; 268 } 269 270 /** 271 * Sets the newItemInProcess attribute value. 272 * 273 * @param newItemInProcess The newItemInProcess to set. 274 */ 275 public void setNewItemInProcess(CashieringItemInProcess newItemInProcess) { 276 this.newItemInProcess = newItemInProcess; 277 } 278 279 /** 280 * Gets the openItemsInProcess attribute. 281 * 282 * @return Returns the openItemsInProcess. 283 */ 284 public List<CashieringItemInProcess> getOpenItemsInProcess() { 285 return openItemsInProcess; 286 } 287 288 /** 289 * Sets the openItemsInProcess attribute value. 290 * 291 * @param openItemsInProcess The openItemsInProcess to set. 292 */ 293 public void setOpenItemsInProcess(List<CashieringItemInProcess> openItemsInProcess) { 294 this.openItemsInProcess = openItemsInProcess; 295 } 296 297 /** 298 * This method returns a single open item in process 299 * 300 * @return a cashiering item in process 301 */ 302 public CashieringItemInProcess getOpenItemInProcess(int index) { 303 extendOpenItemsList(index); 304 return this.openItemsInProcess.get(index); 305 } 306 307 /** 308 * make the open items in process list bigger, so it doesn't return a null value 309 * 310 * @param minSize the minsize to make the list 311 */ 312 private void extendOpenItemsList(int minSize) { 313 while (this.openItemsInProcess.size() <= minSize) { 314 this.openItemsInProcess.add(new CashieringItemInProcess()); 315 } 316 } 317 318 /** 319 * Gets the newCheck attribute. 320 * 321 * @return Returns the newCheck. 322 */ 323 public Check getNewCheck() { 324 return newCheck; 325 } 326 327 /** 328 * Sets the newCheck attribute value. 329 * 330 * @param newCheck The newCheck to set. 331 */ 332 public void setNewCheck(Check newCheck) { 333 this.newCheck = newCheck; 334 } 335 336 /** 337 * This method will make sure that all of the various currency, coin, check, and item in process detail records are populated 338 * with the correct info. 339 */ 340 public void prepareForSave() { 341 moneyInCoin.setDocumentNumber(this.referenceFinancialDocumentNumber); 342 moneyInCoin.setFinancialDocumentTypeCode(DETAIL_DOCUMENT_TYPE); 343 moneyInCoin.setCashieringRecordSource(KFSConstants.CurrencyCoinSources.CASH_MANAGEMENT_IN); 344 345 moneyInCurrency.setDocumentNumber(this.referenceFinancialDocumentNumber); 346 moneyInCurrency.setFinancialDocumentTypeCode(DETAIL_DOCUMENT_TYPE); 347 moneyInCurrency.setCashieringRecordSource(KFSConstants.CurrencyCoinSources.CASH_MANAGEMENT_IN); 348 349 moneyOutCoin.setDocumentNumber(this.referenceFinancialDocumentNumber); 350 moneyOutCoin.setFinancialDocumentTypeCode(DETAIL_DOCUMENT_TYPE); 351 moneyOutCoin.setCashieringRecordSource(KFSConstants.CurrencyCoinSources.CASH_MANAGEMENT_OUT); 352 353 moneyOutCurrency.setDocumentNumber(this.referenceFinancialDocumentNumber); 354 moneyOutCurrency.setFinancialDocumentTypeCode(DETAIL_DOCUMENT_TYPE); 355 moneyOutCurrency.setCashieringRecordSource(KFSConstants.CurrencyCoinSources.CASH_MANAGEMENT_OUT); 356 357 newItemInProcess.setCampusCode(this.campusCode); 358 } 359 360 /** 361 * @see org.kuali.rice.kns.bo.BusinessObjectBase#toStringMapper() 362 */ 363 @Override 364 protected LinkedHashMap toStringMapper() { 365 LinkedHashMap pkMap = new LinkedHashMap(); 366 pkMap.put("campusCode", this.campusCode); 367 pkMap.put("referenceFinancialDocumentNumber", this.referenceFinancialDocumentNumber); 368 pkMap.put("transactionStarted", this.transactionStarted); 369 return pkMap; 370 } 371 372 /** 373 * Gets the checks attribute. 374 * 375 * @return Returns the checks. 376 */ 377 public List getChecks() { 378 return getMoneyInChecks(); 379 } 380 381 /** 382 * Sets the checks attribute value. 383 * 384 * @param checks The checks to set. 385 */ 386 public void setChecks(List checks) { 387 moneyInChecks = new ArrayList<Check>(); 388 for (Object o : checks) { 389 moneyInChecks.add((Check) o); 390 } 391 } 392 393 /** 394 * Gets the number of checks, since Sun doesn't have a direct getter for collection size 395 * 396 * @return the number of checks 397 */ 398 public int getCheckCount() { 399 int count = 0; 400 if (moneyInChecks != null) { 401 count = moneyInChecks.size(); 402 } 403 return count; 404 } 405 406 407 /** 408 * Adds a new check to the list. 409 * 410 * @param check 411 */ 412 public void addCheck(Check check) { 413 check.setSequenceId(this.nextCheckSequenceId); 414 415 this.moneyInChecks.add(check); 416 417 this.nextCheckSequenceId = new Integer(this.nextCheckSequenceId.intValue() + 1); 418 } 419 420 /** 421 * Retrieve a particular check at a given index in the list of checks. 422 * 423 * @param index 424 * @return Check 425 */ 426 public Check getCheck(int index) { 427 while (this.moneyInChecks.size() <= index) { 428 moneyInChecks.add(createNewCheck()); 429 } 430 return (Check) moneyInChecks.get(index); 431 } 432 433 /** 434 * @param checks 435 * @return Map containing Checks from the given List, indexed by their sequenceId 436 */ 437 private Map buildCheckMap(List checks) { 438 Map checkMap = new HashMap(); 439 440 for (Iterator i = checks.iterator(); i.hasNext();) { 441 Check check = (Check) i.next(); 442 Integer sequenceId = check.getSequenceId(); 443 444 Object oldCheck = checkMap.put(sequenceId, check); 445 446 // verify that sequence numbers are unique... 447 if (oldCheck != null) { 448 throw new IllegalStateException("sequence id collision detected for sequence id " + sequenceId); 449 } 450 } 451 452 return checkMap; 453 } 454 455 /** 456 * This method removes a check from the list and updates the total appropriately. 457 * 458 * @param index 459 */ 460 public void removeCheck(int index) { 461 Check check = (Check) moneyInChecks.remove(index); 462 KualiDecimal newTotalCheckAmount = getTotalCheckAmount().subtract(check.getAmount()); 463 // if the totalCheckAmount goes negative, bring back to zero. 464 if (newTotalCheckAmount.isNegative()) { 465 newTotalCheckAmount = KualiDecimal.ZERO; 466 } 467 } 468 469 public KualiDecimal getTotalCheckAmount() { 470 KualiDecimal result = KualiDecimal.ZERO; 471 for (Check c : moneyInChecks) { 472 if (c != null && c.getAmount() != null) { 473 result = result.add(c.getAmount()); 474 } 475 } 476 return result; 477 } 478 479 /** 480 * Gets the nextCheckSequenceId attribute. 481 * 482 * @return Returns the nextCheckSequenceId. 483 */ 484 public Integer getNextCheckSequenceId() { 485 return nextCheckSequenceId; 486 } 487 488 /** 489 * Sets the nextCheckSequenceId attribute value. 490 * 491 * @param nextCheckSequenceId The nextCheckSequenceId to set. 492 */ 493 public void setNextCheckSequenceId(Integer nextCheckSequenceId) { 494 this.nextCheckSequenceId = nextCheckSequenceId; 495 } 496 497 public Check createNewCheck() { 498 Check newCheck = new CheckBase(); 499 newCheck.setFinancialDocumentTypeCode(DETAIL_DOCUMENT_TYPE); 500 newCheck.setCashieringRecordSource(KFSConstants.CheckSources.CASH_MANAGEMENT); 501 return newCheck; 502 } 503 504 /** 505 * This method calculates how much money has been paid back in all items in process 506 * 507 * @return the calculated amount 508 */ 509 public KualiDecimal getPaidBackItemsInProcessAmount() { 510 KualiDecimal amount = KualiDecimal.ZERO; 511 if (this.openItemsInProcess != null) { 512 for (CashieringItemInProcess itemInProcess : this.openItemsInProcess) { 513 if (itemInProcess.getCurrentPayment() != null && itemInProcess.getCurrentPayment().isGreaterThan(KualiDecimal.ZERO)) { 514 amount = amount.add(itemInProcess.getCurrentPayment()); 515 } 516 } 517 } 518 return amount; 519 } 520 521 /** 522 * @return current List of baseline checks for use in update detection 523 */ 524 public List getBaselineChecks() { 525 return baselineChecks; 526 } 527 528 /** 529 * Sets the current List of baseline checks to the given List 530 * 531 * @param baselineChecks 532 */ 533 public void setBaselineChecks(List baselineChecks) { 534 this.baselineChecks = baselineChecks; 535 } 536 537 /** 538 * @param index 539 * @return true if a baselineCheck with the given index exists 540 */ 541 public boolean hasBaselineCheck(int index) { 542 boolean has = false; 543 544 if ((index >= 0) && (index <= baselineChecks.size())) { 545 has = true; 546 } 547 548 return has; 549 } 550 551 /** 552 * Implementation creates empty Checks as a side-effect, so that Struts' efforts to set fields of lines which haven't been 553 * created will succeed rather than causing a NullPointerException. 554 * 555 * @param index 556 * @return baseline Check at the given index 557 */ 558 public Check getBaselineCheck(int index) { 559 while (baselineChecks.size() <= index) { 560 baselineChecks.add(this.createNewCheck()); 561 } 562 return (Check) baselineChecks.get(index); 563 } 564 565 /** 566 * This method calcuates how much money has come in to the "Money In" side of the transaction 567 * 568 * @return the amount calculated 569 */ 570 public KualiDecimal getMoneyInTotal() { 571 KualiDecimal result = KualiDecimal.ZERO; 572 result = result.add(this.moneyInCurrency.getTotalAmount()); 573 result = result.add(this.moneyInCoin.getTotalAmount()); 574 result = result.add(this.getTotalCheckAmount()); 575 if (this.newItemInProcess.isPopulated()) { 576 result = result.add(this.newItemInProcess.getItemAmount()); 577 } 578 return result; 579 } 580 581 /** 582 * This method calculates how much money has gone out through the "Money Out" side of the transaction 583 * 584 * @return the amount calculated 585 */ 586 public KualiDecimal getMoneyOutTotal() { 587 KualiDecimal result = KualiDecimal.ZERO; 588 result = result.add(this.moneyOutCurrency.getTotalAmount()); 589 result = result.add(this.moneyOutCoin.getTotalAmount()); 590 result = result.add(this.getPaidBackItemsInProcessAmount()); 591 return result; 592 } 593 594 /** 595 * @param checkTotal 596 * @deprecated 597 */ 598 public void setCheckTotal(KualiDecimal checkTotal) { 599 this.checkTotal = checkTotal; 600 } 601 602 }