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.coa.businessobject; 017 018 import java.sql.Date; 019 import java.util.ArrayList; 020 import java.util.Collection; 021 import java.util.HashMap; 022 import java.util.Iterator; 023 import java.util.LinkedHashMap; 024 import java.util.List; 025 import java.util.Map; 026 027 import org.apache.commons.lang.StringUtils; 028 import org.kuali.kfs.sys.KFSPropertyConstants; 029 import org.kuali.kfs.sys.context.SpringContext; 030 import org.kuali.rice.kns.bo.GlobalBusinessObject; 031 import org.kuali.rice.kns.bo.GlobalBusinessObjectDetail; 032 import org.kuali.rice.kns.bo.PersistableBusinessObject; 033 import org.kuali.rice.kns.bo.PersistableBusinessObjectBase; 034 import org.kuali.rice.kns.exception.BusinessObjectNotFoundException; 035 import org.kuali.rice.kns.service.BusinessObjectService; 036 import org.kuali.rice.kns.service.PersistenceStructureService; 037 import org.kuali.rice.kns.util.KualiDecimal; 038 import org.kuali.rice.kns.util.TypedArrayList; 039 040 /** 041 * This class simply acts as a container to hold the List of Delegate Changes and the list of Account entries, for the Global 042 * Delegate Change Document. 043 */ 044 public class AccountDelegateGlobal extends PersistableBusinessObjectBase implements GlobalBusinessObject { 045 046 private String documentNumber; 047 048 private String modelName; 049 private String modelChartOfAccountsCode; 050 private String modelOrganizationCode; 051 052 private AccountDelegateModel model; 053 054 List<AccountGlobalDetail> accountGlobalDetails; 055 List<AccountDelegateGlobalDetail> delegateGlobals; 056 057 /** 058 * Constructs a DelegateGlobal.java. 059 */ 060 public AccountDelegateGlobal() { 061 super(); 062 accountGlobalDetails = new TypedArrayList(AccountGlobalDetail.class); 063 delegateGlobals = new TypedArrayList(AccountDelegateGlobalDetail.class); 064 } 065 066 /** 067 * This method adds a single AccountGlobalDetail instance to the list. If one is already present in the list with the same 068 * chartCode and accountNumber, then this new one will not be added. 069 * 070 * @param accountGlobalDetail - populated AccountGlobalDetail instance 071 */ 072 public void addAccount(AccountGlobalDetail accountGlobalDetail) { 073 074 // validate the argument 075 if (accountGlobalDetail == null) { 076 throw new IllegalArgumentException("The accountGlobalDetail instanced passed in was null."); 077 } 078 else if (StringUtils.isBlank(accountGlobalDetail.getChartOfAccountsCode())) { 079 throw new IllegalArgumentException("The chartOfAccountsCode member of the accountGlobalDetail object was not populated."); 080 } 081 else if (StringUtils.isBlank(accountGlobalDetail.getAccountNumber())) { 082 throw new IllegalArgumentException("The accountNumber member of the accountGlobalDetail object was not populated."); 083 } 084 085 // add the object if one doesnt already exist, otherwise silently do nothing 086 AccountGlobalDetail testObject = getAccount(accountGlobalDetail.getChartOfAccountsCode(), accountGlobalDetail.getAccountNumber()); 087 if (testObject == null) { 088 this.accountGlobalDetails.add(accountGlobalDetail); 089 } 090 } 091 092 /** 093 * This method retrieves the specific AccountGlobalDetail object that corresponds to your requested chartCode and accountNumber 094 * (or a null object if there is no match). 095 * 096 * @param chartCode 097 * @param accountNumber 098 * @return returns the AccountGlobalDetail instance matching the chartCode & accountNumber passed in, or Null if none match 099 */ 100 public AccountGlobalDetail getAccount(String chartCode, String accountNumber) { 101 102 // validate the argument 103 if (StringUtils.isBlank(chartCode)) { 104 throw new IllegalArgumentException("The chartCode argument was null or empty."); 105 } 106 else if (StringUtils.isBlank(accountNumber)) { 107 throw new IllegalArgumentException("The accountNumber argument was null or empty."); 108 } 109 110 // walk the list of AccountGlobalDetail objects 111 for (Iterator iter = this.accountGlobalDetails.iterator(); iter.hasNext();) { 112 AccountGlobalDetail accountGlobalDetail = (AccountGlobalDetail) iter.next(); 113 114 // if this one is a match, then quit 115 if (chartCode.equalsIgnoreCase(accountGlobalDetail.getChartOfAccountsCode()) && accountNumber.equalsIgnoreCase(accountGlobalDetail.getAccountNumber())) { 116 return accountGlobalDetail; 117 } 118 } 119 120 // we return null if one is not found 121 return null; 122 } 123 124 /** 125 * @see org.kuali.rice.kns.document.GlobalBusinessObject#getGlobalChangesToDelete() 126 */ 127 public List<PersistableBusinessObject> generateDeactivationsToPersist() { 128 BusinessObjectService boService = SpringContext.getBean(BusinessObjectService.class); 129 130 // retreive all the existing delegates for these accounts 131 List<AccountDelegate> bosToDeactivate = new ArrayList(); 132 Map<String, Object> fieldValues; 133 Collection existingDelegates; 134 for (AccountGlobalDetail accountDetail : getAccountGlobalDetails()) { 135 fieldValues = new HashMap(); 136 fieldValues.put("chartOfAccountsCode", accountDetail.getChartOfAccountsCode()); 137 fieldValues.put("accountNumber", accountDetail.getAccountNumber()); 138 fieldValues.put("active", true); 139 existingDelegates = boService.findMatching(AccountDelegate.class, fieldValues); 140 bosToDeactivate.addAll(existingDelegates); 141 } 142 143 // mark all the delegates as inactive 144 for (AccountDelegate accountDelegate : bosToDeactivate) { 145 accountDelegate.setActive(false); 146 } 147 return new ArrayList<PersistableBusinessObject>(bosToDeactivate); 148 } 149 150 /** 151 * @see org.kuali.rice.kns.document.GlobalBusinessObject#applyGlobalChanges(org.kuali.rice.kns.bo.BusinessObject) 152 */ 153 @SuppressWarnings("deprecation") 154 public List<PersistableBusinessObject> generateGlobalChangesToPersist() { 155 156 BusinessObjectService boService = SpringContext.getBean(BusinessObjectService.class); 157 List<AccountDelegate> persistables = new ArrayList(); 158 159 List<AccountDelegateGlobalDetail> changeDocuments = this.getDelegateGlobals(); 160 List<AccountGlobalDetail> accountDetails = this.getAccountGlobalDetails(); 161 162 for (AccountDelegateGlobalDetail changeDocument : changeDocuments) { 163 for (AccountGlobalDetail accountDetail : accountDetails) { 164 165 Account account = (Account) boService.findByPrimaryKey(Account.class, accountDetail.getPrimaryKeys()); 166 167 // if the account doesnt exist, fail fast, as this should never happen, 168 // the busines rules for this document should have caught this. 169 if (account == null) { 170 throw new BusinessObjectNotFoundException("Account [" + accountDetail.getChartOfAccountsCode() + "-" + accountDetail.getAccountNumber() + "] was not present in the database. " + "This should never happen under normal circumstances, as an invalid account should have " + "been caught by the Business Rules infrastructure."); 171 } 172 173 // attempt to load the existing Delegate from the DB, if it exists. we do this to avoid 174 // versionNumber conflicts if we tried to just insert a new record that already existed. 175 Map pkMap = new HashMap(); 176 pkMap.putAll(accountDetail.getPrimaryKeys()); // chartOfAccountsCode & accountNumber 177 pkMap.put("financialDocumentTypeCode", changeDocument.getFinancialDocumentTypeCode()); 178 pkMap.put("accountDelegateSystemId", changeDocument.getAccountDelegateUniversalId()); 179 AccountDelegate delegate = (AccountDelegate) boService.findByPrimaryKey(AccountDelegate.class, pkMap); 180 181 // if there is no existing Delegate with these primary keys, then we're creating a new one, 182 // so lets populate it with the primary keys 183 if (delegate == null) { 184 delegate = new AccountDelegate(); 185 delegate.setChartOfAccountsCode(accountDetail.getChartOfAccountsCode()); 186 delegate.setAccountNumber(accountDetail.getAccountNumber()); 187 delegate.setAccountDelegateSystemId(changeDocument.getAccountDelegateUniversalId()); 188 delegate.setFinancialDocumentTypeCode(changeDocument.getFinancialDocumentTypeCode()); 189 delegate.setActive(true); 190 } 191 else { 192 delegate.setActive(true); 193 } 194 195 // APPROVAL FROM AMOUNT 196 if (changeDocument.getApprovalFromThisAmount() != null) { 197 if (!changeDocument.getApprovalFromThisAmount().equals(KualiDecimal.ZERO)) { 198 delegate.setFinDocApprovalFromThisAmt(changeDocument.getApprovalFromThisAmount()); 199 } 200 } 201 202 // APPROVAL TO AMOUNT 203 if (changeDocument.getApprovalToThisAmount() != null) { 204 if (!changeDocument.getApprovalToThisAmount().equals(KualiDecimal.ZERO)) { 205 delegate.setFinDocApprovalToThisAmount(changeDocument.getApprovalToThisAmount()); 206 } 207 } 208 209 // PRIMARY ROUTING 210 delegate.setAccountsDelegatePrmrtIndicator(changeDocument.getAccountDelegatePrimaryRoutingIndicator()); 211 212 // START DATE 213 if (changeDocument.getAccountDelegateStartDate() != null) { 214 delegate.setAccountDelegateStartDate(new Date(changeDocument.getAccountDelegateStartDate().getTime())); 215 } 216 217 persistables.add(delegate); 218 219 } 220 } 221 222 return new ArrayList<PersistableBusinessObject>(persistables); 223 } 224 225 /** 226 * @see org.kuali.rice.kns.bo.BusinessObjectBase#toStringMapper() 227 */ 228 @Override 229 protected LinkedHashMap toStringMapper() { 230 231 LinkedHashMap m = new LinkedHashMap(); 232 233 m.put(KFSPropertyConstants.DOCUMENT_NUMBER, this.documentNumber); 234 return m; 235 } 236 237 /** 238 * @see org.kuali.rice.kns.document.GlobalBusinessObject#getDocumentNumber() 239 */ 240 public String getDocumentNumber() { 241 return documentNumber; 242 } 243 244 /** 245 * @see org.kuali.rice.kns.document.GlobalBusinessObject#setDocumentNumber(java.lang.String) 246 */ 247 public void setDocumentNumber(String documentNumber) { 248 this.documentNumber = documentNumber; 249 250 } 251 252 /** 253 * Gets the accountGlobalDetails attribute. 254 * 255 * @return Returns the accountGlobalDetails. 256 */ 257 public final List<AccountGlobalDetail> getAccountGlobalDetails() { 258 return accountGlobalDetails; 259 } 260 261 /** 262 * Sets the accountGlobalDetails attribute value. 263 * 264 * @param accountGlobalDetails The accountGlobalDetails to set. 265 */ 266 public final void setAccountGlobalDetails(List<AccountGlobalDetail> accountGlobalDetails) { 267 this.accountGlobalDetails = accountGlobalDetails; 268 } 269 270 /** 271 * Gets the delegateGlobals attribute. 272 * 273 * @return Returns the delegateGlobals. 274 */ 275 public final List<AccountDelegateGlobalDetail> getDelegateGlobals() { 276 return delegateGlobals; 277 } 278 279 /** 280 * Sets the delegateGlobals attribute value. 281 * 282 * @param delegateGlobals The delegateGlobals to set. 283 */ 284 public final void setDelegateGlobals(List<AccountDelegateGlobalDetail> delegateGlobals) { 285 this.delegateGlobals = delegateGlobals; 286 } 287 288 /** 289 * @see org.kuali.rice.kns.document.GlobalBusinessObject#isPersistable() 290 */ 291 public boolean isPersistable() { 292 PersistenceStructureService persistenceStructureService = SpringContext.getBean(PersistenceStructureService.class); 293 294 // fail if the PK for this object is emtpy 295 if (StringUtils.isBlank(documentNumber)) { 296 return false; 297 } 298 299 // fail if the PKs for any of the contained objects are empty 300 for (AccountDelegateGlobalDetail delegateGlobals : getDelegateGlobals()) { 301 if (!persistenceStructureService.hasPrimaryKeyFieldValues(delegateGlobals)) { 302 return false; 303 } 304 } 305 for (AccountGlobalDetail account : getAccountGlobalDetails()) { 306 if (!persistenceStructureService.hasPrimaryKeyFieldValues(account)) { 307 return false; 308 } 309 } 310 311 // otherwise, its all good 312 return true; 313 } 314 315 public String getModelName() { 316 return modelName; 317 } 318 319 public void setModelName(String loadModelName) { 320 this.modelName = loadModelName; 321 } 322 323 public String getModelChartOfAccountsCode() { 324 return modelChartOfAccountsCode; 325 } 326 327 public void setModelChartOfAccountsCode(String loadModelChartOfAccountsCode) { 328 this.modelChartOfAccountsCode = loadModelChartOfAccountsCode; 329 } 330 331 public String getModelOrganizationCode() { 332 return modelOrganizationCode; 333 } 334 335 public void setModelOrganizationCode(String loadModelOrganizationCode) { 336 this.modelOrganizationCode = loadModelOrganizationCode; 337 } 338 339 public AccountDelegateModel getModel() { 340 return model; 341 } 342 343 public void setModel(AccountDelegateModel loadModel) { 344 this.model = loadModel; 345 } 346 347 public List<? extends GlobalBusinessObjectDetail> getAllDetailObjects() { 348 ArrayList<GlobalBusinessObjectDetail> details = new ArrayList<GlobalBusinessObjectDetail>(accountGlobalDetails.size() + delegateGlobals.size()); 349 details.addAll(accountGlobalDetails); 350 details.addAll(delegateGlobals); 351 return details; 352 } 353 354 @Override 355 public void linkEditableUserFields() { 356 super.linkEditableUserFields(); 357 if (this == null) { 358 throw new IllegalArgumentException("globalDelegate parameter passed in was null"); 359 } 360 List bos = new ArrayList(); 361 bos.addAll(getDelegateGlobals()); 362 SpringContext.getBean(BusinessObjectService.class).linkUserFields(bos); 363 } 364 365 /** 366 * @see org.kuali.rice.kns.bo.PersistableBusinessObjectBase#buildListOfDeletionAwareLists() 367 */ 368 @Override 369 public List buildListOfDeletionAwareLists() { 370 List<List> managedLists = super.buildListOfDeletionAwareLists(); 371 372 managedLists.add(getAccountGlobalDetails()); 373 managedLists.add(getDelegateGlobals()); 374 375 return managedLists; 376 } 377 }