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 }