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.service.impl; 017 018 import java.util.ArrayList; 019 import java.util.Collection; 020 import java.util.HashSet; 021 import java.util.Iterator; 022 import java.util.List; 023 import java.util.Set; 024 025 import org.apache.commons.lang.StringUtils; 026 import org.apache.log4j.Logger; 027 import org.kuali.kfs.coa.businessobject.Account; 028 import org.kuali.kfs.coa.businessobject.AccountDelegate; 029 import org.kuali.kfs.coa.dataaccess.AccountDao; 030 import org.kuali.kfs.coa.service.AccountService; 031 import org.kuali.kfs.sys.KFSConstants; 032 import org.kuali.kfs.sys.KFSConstants.SystemGroupParameterNames; 033 import org.kuali.kfs.sys.businessobject.AccountingLine; 034 import org.kuali.kfs.sys.context.SpringContext; 035 import org.kuali.kfs.sys.service.NonTransactional; 036 import org.kuali.kfs.sys.service.impl.KfsParameterConstants; 037 import org.kuali.rice.kew.service.KEWServiceLocator; 038 import org.kuali.rice.kim.bo.Person; 039 import org.kuali.rice.kim.util.KimCommonUtils; 040 import org.kuali.rice.kns.service.ParameterService; 041 import org.kuali.rice.kns.util.ObjectUtils; 042 import org.kuali.rice.kns.util.spring.Cached; 043 044 /** 045 * This class is the service implementation for the Account structure. This is the default, Kuali provided implementation. 046 */ 047 048 @NonTransactional 049 public class AccountServiceImpl implements AccountService { 050 private static final Logger LOG = Logger.getLogger(AccountServiceImpl.class); 051 052 private AccountDao accountDao; 053 054 /** 055 * Retrieves an Account object based on primary key. 056 * 057 * @param chartOfAccountsCode - Chart of Accounts Code 058 * @param accountNumber - Account Number 059 * @return Account 060 * @see AccountService 061 */ 062 public Account getByPrimaryId(String chartOfAccountsCode, String accountNumber) { 063 if (LOG.isDebugEnabled()) { 064 LOG.debug("retrieving account by primaryId (" + chartOfAccountsCode + "," + accountNumber + ")"); 065 } 066 067 Account account = accountDao.getByPrimaryId(chartOfAccountsCode, accountNumber); 068 069 if (LOG.isDebugEnabled()) { 070 LOG.debug("retrieved account by primaryId (" + chartOfAccountsCode + "," + accountNumber + ")"); 071 } 072 return account; 073 } 074 075 /** 076 * Method is used by KualiAccountAttribute to enable caching of accounts for routing. 077 * 078 * @see org.kuali.kfs.coa.service.impl.AccountServiceImpl#getByPrimaryId(java.lang.String, java.lang.String) 079 */ 080 @Cached 081 public Account getByPrimaryIdWithCaching(String chartOfAccountsCode, String accountNumber) { 082 return accountDao.getByPrimaryId(chartOfAccountsCode, accountNumber); 083 } 084 085 /** 086 * @see org.kuali.kfs.coa.service.AccountService#getAccountsThatUserIsResponsibleFor(org.kuali.bo.user.KualiUser) 087 */ 088 public List getAccountsThatUserIsResponsibleFor(Person person) { 089 if (LOG.isDebugEnabled()) { 090 LOG.debug("retrieving accountsResponsible list for user " + person.getName()); 091 } 092 093 // gets the list of accounts that the user is the Fiscal Officer of 094 List accountList = accountDao.getAccountsThatUserIsResponsibleFor(person); 095 if (LOG.isDebugEnabled()) { 096 LOG.debug("retrieved accountsResponsible list for user " + person.getName()); 097 } 098 return accountList; 099 } 100 101 /** 102 * @see org.kuali.kfs.coa.service.AccountService#hasResponsibilityOnAccount(org.kuali.rice.kim.bo.Person, 103 * org.kuali.kfs.coa.businessobject.Account) 104 */ 105 public boolean hasResponsibilityOnAccount(Person kualiUser, Account account) { 106 return accountDao.determineUserResponsibilityOnAccount(kualiUser, account); 107 } 108 109 /** 110 * @see org.kuali.kfs.coa.service.AccountService#getPrimaryDelegationByExample(org.kuali.kfs.coa.businessobject.AccountDelegate, 111 * java.lang.String) 112 */ 113 114 public AccountDelegate getPrimaryDelegationByExample(AccountDelegate delegateExample, String totalDollarAmount) { 115 String documentTypeName = delegateExample.getFinancialDocumentTypeCode(); 116 List primaryDelegations = filterAccountDelegates(delegateExample, accountDao.getPrimaryDelegationByExample(delegateExample, totalDollarAmount)); 117 if (primaryDelegations.isEmpty()) { 118 return null; 119 } 120 AccountDelegate delegate; 121 for (Iterator iterator = primaryDelegations.iterator(); iterator.hasNext();) { 122 delegate = (AccountDelegate) iterator.next(); 123 if (!KFSConstants.ROOT_DOCUMENT_TYPE.equals(delegate.getFinancialDocumentTypeCode())) { 124 return delegate; 125 } 126 } 127 return (AccountDelegate)primaryDelegations.iterator().next(); 128 } 129 130 /** 131 * @see org.kuali.kfs.coa.service.AccountService#getSecondaryDelegationsByExample(org.kuali.kfs.coa.businessobject.AccountDelegate, 132 * java.lang.String) 133 */ 134 public List getSecondaryDelegationsByExample(AccountDelegate delegateExample, String totalDollarAmount) { 135 List secondaryDelegations = accountDao.getSecondaryDelegationsByExample(delegateExample, totalDollarAmount); 136 return filterAccountDelegates(delegateExample, secondaryDelegations); 137 } 138 139 /** 140 * This method filters account delegates by 141 * 1) performing an exact match on the document type name of delegateExample 142 * 2) if no match is found for 1), then by performing an exact match on 143 * the closest parent document type name of delegateExample document type name. 144 * 145 * @param delegateExample 146 * @param accountDelegatesToFilterFrom 147 * @return 148 */ 149 protected List<AccountDelegate> filterAccountDelegates(AccountDelegate delegateExample, List<AccountDelegate> accountDelegatesToFilterFrom){ 150 String documentTypeName = delegateExample.getFinancialDocumentTypeCode(); 151 AccountDelegate delegate; 152 List<AccountDelegate> filteredAccountDelegates = filterAccountDelegates(accountDelegatesToFilterFrom, documentTypeName); 153 if(filteredAccountDelegates.size()==0){ 154 Set<String> potentialParentDocumentTypeNames = getPotentialParentDocumentTypeNames(accountDelegatesToFilterFrom); 155 String closestParentDocumentTypeName = KimCommonUtils.getClosestParentDocumentTypeName( 156 KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName), 157 potentialParentDocumentTypeNames); 158 filteredAccountDelegates = filterAccountDelegates(accountDelegatesToFilterFrom, closestParentDocumentTypeName); 159 } 160 return filteredAccountDelegates; 161 } 162 163 /** 164 * This method filters account delegates by performing an exact match on the document type name passed in. 165 * 166 * @param delegations 167 * @param documentTypeNameToFilterOn 168 * @return 169 */ 170 protected List<AccountDelegate> filterAccountDelegates(List<AccountDelegate> delegations, String documentTypeNameToFilterOn){ 171 AccountDelegate delegate; 172 List<AccountDelegate> filteredSecondaryDelegations = new ArrayList<AccountDelegate>(); 173 for(Object delegateObject: delegations){ 174 delegate = (AccountDelegate)delegateObject; 175 if(StringUtils.equals(delegate.getFinancialDocumentTypeCode(), documentTypeNameToFilterOn)){ 176 filteredSecondaryDelegations.add(delegate); 177 } 178 } 179 return filteredSecondaryDelegations; 180 } 181 182 /** 183 * This method gets a list of potential parent document type names 184 * by collecting the unique doc type names from the list of account delegations 185 * 186 * @param delegations 187 * @return 188 */ 189 protected Set<String> getPotentialParentDocumentTypeNames(List<AccountDelegate> delegations){ 190 AccountDelegate delegate; 191 Set<String> potentialParentDocumentTypeNames = new HashSet<String>(); 192 for(Object delegateObject: delegations){ 193 delegate = (AccountDelegate)delegateObject; 194 if(!potentialParentDocumentTypeNames.contains(delegate.getFinancialDocumentTypeCode())) 195 potentialParentDocumentTypeNames.add(delegate.getFinancialDocumentTypeCode()); 196 } 197 return potentialParentDocumentTypeNames; 198 } 199 200 /** 201 * get all accounts in the system. This is needed by a sufficient funds rebuilder job 202 * 203 * @return iterator of all accounts 204 */ 205 public Iterator getAllAccounts() { 206 LOG.debug("getAllAccounts() started"); 207 208 Iterator accountIter = accountDao.getAllAccounts(); 209 List accountList = new ArrayList(); 210 while (accountIter.hasNext()) { 211 accountList.add(accountIter.next()); 212 } 213 return accountList.iterator(); 214 } 215 216 /** 217 * @see org.kuali.kfs.coa.service.AccountService#getActiveAccountsForAccountSupervisor(java.lang.String) 218 */ 219 public Iterator<Account> getActiveAccountsForAccountSupervisor(String principalId) { 220 return accountDao.getActiveAccountsForAccountSupervisor(principalId); 221 } 222 223 /** 224 * @see org.kuali.kfs.coa.service.AccountService#getActiveAccountsForFiscalOfficer(java.lang.String) 225 */ 226 public Iterator<Account> getActiveAccountsForFiscalOfficer(String principalId) { 227 return accountDao.getActiveAccountsForFiscalOfficer(principalId); 228 } 229 230 /** 231 * @see org.kuali.kfs.coa.service.AccountService#getExpiredAccountsForAccountSupervisor(java.lang.String) 232 */ 233 public Iterator<Account> getExpiredAccountsForAccountSupervisor(String principalId) { 234 return accountDao.getExpiredAccountsForAccountSupervisor(principalId); 235 } 236 237 /** 238 * @see org.kuali.kfs.coa.service.AccountService#getExpiredAccountsForFiscalOfficer(java.lang.String) 239 */ 240 public Iterator<Account> getExpiredAccountsForFiscalOfficer(String principalId) { 241 return accountDao.getExpiredAccountsForFiscalOfficer(principalId); 242 } 243 244 /** 245 * @see org.kuali.kfs.coa.service.AccountService#isPrincipalInAnyWayShapeOrFormAccountManager(java.lang.String) 246 */ 247 public boolean isPrincipalInAnyWayShapeOrFormAccountManager(String principalId) { 248 return accountDao.isPrincipalInAnyWayShapeOrFormAccountManager(principalId); 249 } 250 251 /** 252 * @see org.kuali.kfs.coa.service.AccountService#isPrincipalInAnyWayShapeOrFormAccountSupervisor(java.lang.String) 253 */ 254 public boolean isPrincipalInAnyWayShapeOrFormAccountSupervisor(String principalId) { 255 return accountDao.isPrincipalInAnyWayShapeOrFormAccountSupervisor(principalId); 256 } 257 258 /** 259 * @see org.kuali.kfs.coa.service.AccountService#isPrincipalInAnyWayShapeOrFormFiscalOfficer(java.lang.String) 260 */ 261 public boolean isPrincipalInAnyWayShapeOrFormFiscalOfficer(String principalId) { 262 return accountDao.isPrincipalInAnyWayShapeOrFormFiscalOfficer(principalId); 263 } 264 265 /** 266 * @see org.kuali.kfs.coa.service.AccountService#getAccountsForAccountNumber(java.lang.String) 267 */ 268 public Collection<Account> getAccountsForAccountNumber(String accountNumber) { 269 return accountDao.getAccountsForAccountNumber(accountNumber); 270 } 271 272 /** 273 * @see org.kuali.kfs.coa.service.AccountService#getUniqueAccountForAccountNumber(java.lang.String) 274 */ 275 public Account getUniqueAccountForAccountNumber(String accountNumber) { 276 Iterator<Account> accounts = accountDao.getAccountsForAccountNumber(accountNumber).iterator(); 277 Account account = null; 278 // there should be only one account in the collection 279 if (accounts.hasNext()) { 280 account = (Account)accounts.next(); 281 } 282 return account; 283 } 284 285 /** 286 * @see org.kuali.kfs.coa.service.AccountService#accountsCanCrossCharts() 287 */ 288 public boolean accountsCanCrossCharts() { 289 return SpringContext.getBean(ParameterService.class).getIndicatorParameter(KfsParameterConstants.FINANCIAL_SYSTEM_ALL.class, SystemGroupParameterNames.ACCOUNTS_CAN_CROSS_CHARTS_IND); 290 } 291 292 /** 293 * @see org.kuali.kfs.coa.service.AccountService#accountsCanCrossCharts() 294 */ 295 public void populateAccountingLineChartIfNeeded(AccountingLine line) { 296 if (!accountsCanCrossCharts() /*&& line.getChartOfAccountsCode() == null*/) { 297 Account account = getUniqueAccountForAccountNumber(line.getAccountNumber()); 298 if (ObjectUtils.isNotNull(account)) { 299 line.setChartOfAccountsCode(account.getChartOfAccountsCode()); 300 } 301 } 302 } 303 304 /** 305 * @param accountDao The accountDao to set. 306 */ 307 public void setAccountDao(AccountDao accountDao) { 308 this.accountDao = accountDao; 309 } 310 311 }