View Javadoc
1   /*
2    * Copyright 2005-2006 The Kuali Foundation
3    * 
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.opensource.org/licenses/ecl2.php
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.coa.dataaccess.impl;
17  
18  import java.sql.Date;
19  import java.util.ArrayList;
20  import java.util.Collection;
21  import java.util.Iterator;
22  import java.util.List;
23  
24  import org.apache.ojb.broker.query.Criteria;
25  import org.apache.ojb.broker.query.QueryFactory;
26  import org.apache.ojb.broker.query.ReportQueryByCriteria;
27  import org.kuali.ole.coa.businessobject.Account;
28  import org.kuali.ole.coa.businessobject.AccountDelegate;
29  import org.kuali.ole.coa.dataaccess.AccountDao;
30  import org.kuali.ole.sys.OLEConstants;
31  import org.kuali.ole.sys.OLEPropertyConstants;
32  import org.kuali.ole.sys.businessobject.AccountResponsibility;
33  import org.kuali.rice.core.api.util.type.KualiDecimal;
34  import org.kuali.rice.core.framework.persistence.ojb.dao.PlatformAwareDaoBaseOjb;
35  import org.kuali.rice.kim.api.identity.Person;
36  import org.kuali.rice.krad.util.ObjectUtils;
37  
38  /**
39   * This class is the OJB implementation of the AccountDao interface.
40   */
41  public class AccountDaoOjb extends PlatformAwareDaoBaseOjb implements AccountDao {
42      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AccountDaoOjb.class);
43  
44      /**
45       * Retrieves account business object by primary key
46       * 
47       * @param chartOfAccountsCode - the FIN_COA_CD of the Chart Code that is part of the composite key of Account
48       * @param accountNumber - the ACCOUNT_NBR part of the composite key of Accont
49       * @return Account
50       * @see AccountDao
51       */
52      public Account getByPrimaryId(String chartOfAccountsCode, String accountNumber) {
53          LOG.debug("getByPrimaryId() started");
54  
55          Criteria criteria = new Criteria();
56          criteria.addEqualTo("chartOfAccountsCode", chartOfAccountsCode);
57          criteria.addEqualTo("accountNumber", accountNumber);
58  
59          return (Account) getPersistenceBrokerTemplate().getObjectByQuery(QueryFactory.newQuery(Account.class, criteria));
60      }
61  
62      /**
63       * fetch the accounts that the user is either the fiscal officer or a delegate of the fiscal officer
64       * 
65       * @param kualiUser
66       * @return a list of Accounts that the user has responsibility for
67       */
68      public List getAccountsThatUserIsResponsibleFor(Person person, java.util.Date currentDate) {
69          LOG.debug("getAccountsThatUserIsResponsibleFor() started");
70  
71          List accountResponsibilities = new ArrayList();
72          accountResponsibilities.addAll(getFiscalOfficerResponsibilities(person));
73          accountResponsibilities.addAll(getDelegatedResponsibilities(person, currentDate));
74          return accountResponsibilities;
75      }
76  
77      /**
78       * @see org.kuali.ole.coa.dataaccess.AccountDao#determineUserResponsibilityOnAccount(org.kuali.rice.kim.api.identity.Person,
79       *      org.kuali.ole.coa.businessobject.Account, java.sql.Date)
80       */
81      public boolean determineUserResponsibilityOnAccount(Person person, Account account, Date currentSqlDate) {
82          boolean result = hasFiscalOfficerResponsibility(person, account);
83          if (!result) {
84              result = hasDelegatedResponsibility(person, account, currentSqlDate);
85          }
86          return result;
87      }
88  
89      /**
90       * Resolves the Primary Delegate for the given delegate example. If the primary delegate exists for a specific Document Type
91       * Code and for a Document Type Code of "OLE", the delegate for the specific document type code is returned;
92       * 
93       * @see org.kuali.ole.coa.dataaccess.AccountDao#getPrimaryDelegationByExample(org.kuali.ole.coa.businessobject.AccountDelegate,
94       *      java.lang.String)
95       */
96      public List getPrimaryDelegationByExample(AccountDelegate delegateExample, Date currentSqlDate, String totalDollarAmount) {
97          return new ArrayList(getPersistenceBrokerTemplate().getCollectionByQuery(QueryFactory.newQuery(AccountDelegate.class, getDelegateByExampleCriteria(delegateExample, currentSqlDate, totalDollarAmount, "Y"))));
98      }
99  
100     /**
101      * @see org.kuali.ole.coa.dataaccess.AccountDao#getSecondaryDelegationsByExample(org.kuali.ole.coa.businessobject.AccountDelegate,
102      *      java.lang.String)
103      */
104     public List getSecondaryDelegationsByExample(AccountDelegate delegateExample, Date currentSqlDate, String totalDollarAmount) {
105         return new ArrayList(getPersistenceBrokerTemplate().getCollectionByQuery(QueryFactory.newQuery(AccountDelegate.class, getDelegateByExampleCriteria(delegateExample, currentSqlDate, totalDollarAmount, "N"))));
106     }
107 
108     /**
109      * This method creates a {@link Criteria} based on {@link Delegate}, dollar amount and whether or not it is the primary delegate
110      * 
111      * @param delegateExample
112      * @param totalDollarAmount
113      * @param accountsDelegatePrmrtIndicator
114      * @return example {@link Delegate} {@link Criteria}
115      */
116     protected Criteria getDelegateByExampleCriteria(AccountDelegate delegateExample, Date currentSqlDate, String totalDollarAmount, String accountsDelegatePrmrtIndicator) {
117         Criteria criteria = new Criteria();
118         criteria.addEqualTo(OLEConstants.CHART_OF_ACCOUNTS_CODE_PROPERTY_NAME, delegateExample.getChartOfAccountsCode());
119         criteria.addEqualTo(OLEConstants.ACCOUNT_NUMBER_PROPERTY_NAME, delegateExample.getAccountNumber());
120         criteria.addEqualTo("active", "Y");
121         criteria.addLessOrEqualThan("accountDelegateStartDate", currentSqlDate);
122         criteria.addEqualTo("accountsDelegatePrmrtIndicator", accountsDelegatePrmrtIndicator);
123         if (totalDollarAmount != null) {
124             // (toAmt is nullish and (fromAmt is nullish or fromAmt <= total)) or (fromAmt is nullish and (toAmt is nullish or toAmt
125             // >= total)) or (fromAmt <= total and toAmount >= total)
126 
127             /* to not active clause: (toAmt is nullish and (fromAmt is nullish or fromAmt <= total)) */
128             Criteria toAmountIsNullish = new Criteria();
129             toAmountIsNullish.addIsNull(OLEPropertyConstants.FIN_DOC_APPROVAL_TO_THIS_AMOUNT);
130             Criteria toAmountIsZero1 = new Criteria();
131             toAmountIsZero1.addEqualTo(OLEPropertyConstants.FIN_DOC_APPROVAL_TO_THIS_AMOUNT, "0");
132             toAmountIsNullish.addOrCriteria(toAmountIsZero1);
133 
134             Criteria fromMatchesClause = new Criteria();
135             fromMatchesClause.addIsNull(OLEPropertyConstants.FIN_DOC_APPROVAL_FROM_THIS_AMT);
136             Criteria fromAmountIsLessThanTotal = new Criteria();
137             fromAmountIsLessThanTotal.addLessOrEqualThan(OLEPropertyConstants.FIN_DOC_APPROVAL_FROM_THIS_AMT, totalDollarAmount);
138             fromMatchesClause.addOrCriteria(fromAmountIsLessThanTotal);
139 
140             Criteria toNotActiveClause = new Criteria();
141             toNotActiveClause.addAndCriteria(toAmountIsNullish);
142             toNotActiveClause.addAndCriteria(fromMatchesClause);
143 
144             /* from not active clause: (fromAmt is nullish and (toAmt is nullish or toAmt >= total)) */
145             Criteria toMatchesClause = new Criteria();
146             toMatchesClause.addIsNull(OLEPropertyConstants.FIN_DOC_APPROVAL_TO_THIS_AMOUNT);
147             Criteria toAmountIsZero2 = new Criteria();
148             toAmountIsZero2.addEqualTo(OLEPropertyConstants.FIN_DOC_APPROVAL_TO_THIS_AMOUNT, "0");
149             toMatchesClause.addOrCriteria(toAmountIsZero2);
150             Criteria toAmountIsGreaterThanTotal = new Criteria();
151             toAmountIsGreaterThanTotal.addGreaterOrEqualThan(OLEPropertyConstants.FIN_DOC_APPROVAL_TO_THIS_AMOUNT, totalDollarAmount);
152             toMatchesClause.addOrCriteria(toAmountIsGreaterThanTotal);
153 
154             Criteria fromIsNullClause = new Criteria();
155             fromIsNullClause.addIsNull(OLEPropertyConstants.FIN_DOC_APPROVAL_FROM_THIS_AMT);
156             Criteria fromIsZeroClause = new Criteria();
157             fromIsZeroClause.addEqualTo(OLEPropertyConstants.FIN_DOC_APPROVAL_FROM_THIS_AMT, "0");
158             Criteria fromIsNullishClause = new Criteria();
159             fromIsNullishClause.addOrCriteria(fromIsNullClause);
160             fromIsNullishClause.addOrCriteria(fromIsZeroClause);
161             Criteria fromNotActiveClause = new Criteria();
162             fromNotActiveClause.addAndCriteria(fromIsNullishClause);
163             fromNotActiveClause.addAndCriteria(toMatchesClause);
164 
165             Criteria bothActive = new Criteria();
166             bothActive.addLessOrEqualThan(OLEPropertyConstants.FIN_DOC_APPROVAL_FROM_THIS_AMT, totalDollarAmount);
167             bothActive.addGreaterOrEqualThan(OLEPropertyConstants.FIN_DOC_APPROVAL_TO_THIS_AMOUNT, totalDollarAmount);
168 
169             Criteria totalDollarAmountCriteria = new Criteria();
170             totalDollarAmountCriteria.addOrCriteria(toNotActiveClause);
171             totalDollarAmountCriteria.addOrCriteria(fromNotActiveClause);
172             totalDollarAmountCriteria.addOrCriteria(bothActive);
173 
174             criteria.addAndCriteria(totalDollarAmountCriteria);
175         }
176         return criteria;
177     }
178 
179     /**
180      * method to get the fo responsibilities for the account
181      * 
182      * @param person - fiscal officer to check for
183      * @return list of {@link AccountResponsibility} for this fiscal officer
184      */
185     protected List getFiscalOfficerResponsibilities(Person person) {
186         List fiscalOfficerResponsibilities = new ArrayList();
187         Criteria criteria = new Criteria();
188         criteria.addEqualTo("accountFiscalOfficerSystemIdentifier", person.getPrincipalId());
189         Collection accounts = getPersistenceBrokerTemplate().getCollectionByQuery(QueryFactory.newQuery(Account.class, criteria));
190         for (Iterator iter = accounts.iterator(); iter.hasNext();) {
191             Account account = (Account) iter.next();
192             AccountResponsibility accountResponsibility = new AccountResponsibility(AccountResponsibility.FISCAL_OFFICER_RESPONSIBILITY, KualiDecimal.ZERO, KualiDecimal.ZERO, "", account);
193             fiscalOfficerResponsibilities.add(accountResponsibility);
194         }
195         return fiscalOfficerResponsibilities;
196     }
197 
198     /**
199      * This method determines if a given user has fiscal officer responsiblity on a given account.
200      * 
201      * @param person the user to check responsibilities for
202      * @param account the account to check responsibilities on
203      * @return true if user does have fiscal officer responsibility on account, false if otherwise
204      */
205     protected boolean hasFiscalOfficerResponsibility(Person person, Account account) {
206         boolean hasFiscalOfficerResponsibility = false;
207         Criteria criteria = new Criteria();
208         criteria.addEqualTo("accountFiscalOfficerSystemIdentifier", person.getPrincipalId());
209         criteria.addEqualTo("chartOfAccountsCode", account.getChartOfAccountsCode());
210         criteria.addEqualTo("accountNumber", account.getAccountNumber());
211         Collection accounts = getPersistenceBrokerTemplate().getCollectionByQuery(QueryFactory.newQuery(Account.class, criteria));
212         if (accounts != null && accounts.size() > 0) {
213             Account retrievedAccount = (Account) accounts.iterator().next();
214             if (ObjectUtils.isNotNull(retrievedAccount)) {
215                 hasFiscalOfficerResponsibility = true;
216             }
217         }
218         return hasFiscalOfficerResponsibility;
219     }
220 
221     /**
222      * method to get the fo delegated responsibilities for the account
223      * 
224      * @param person - user to check against
225      * @return a list of {@link AccountResponsibility} objects for a delegate
226      */
227     protected List getDelegatedResponsibilities(Person person, java.util.Date currentDate) {
228         List delegatedResponsibilities = new ArrayList();
229         Criteria criteria = new Criteria();
230         criteria.addEqualTo("accountDelegateSystemId", person.getPrincipalId());
231         Collection accountDelegates = getPersistenceBrokerTemplate().getCollectionByQuery(QueryFactory.newQuery(AccountDelegate.class, criteria));
232         for (Iterator iter = accountDelegates.iterator(); iter.hasNext();) {
233             AccountDelegate accountDelegate = (AccountDelegate) iter.next();
234             if (accountDelegate.isActive()) {
235                 // the start_date should never be null in the real world, but
236                 // there is some test data that
237                 // contains null startDates, therefore this check.
238                 if (ObjectUtils.isNotNull(accountDelegate.getAccountDelegateStartDate())) {
239                     if (!accountDelegate.getAccountDelegateStartDate().after(currentDate)) {
240                         Account account = getByPrimaryId(accountDelegate.getChartOfAccountsCode(), accountDelegate.getAccount().getAccountNumber());
241                         AccountResponsibility accountResponsibility = new AccountResponsibility(AccountResponsibility.DELEGATED_RESPONSIBILITY, accountDelegate.getFinDocApprovalFromThisAmt(), accountDelegate.getFinDocApprovalToThisAmount(), accountDelegate.getFinancialDocumentTypeCode(), account);
242                         delegatedResponsibilities.add(accountResponsibility);
243                     }
244                 }
245             }
246         }
247         return delegatedResponsibilities;
248     }
249 
250     /**
251      * This method determines if a user has delegated responsibilities on a given account.
252      * 
253      * @param person the user to check responsibilities for
254      * @param account the account to check responsibilities on
255      * @return true if user has delegated responsibilities
256      */
257     protected boolean hasDelegatedResponsibility(Person person, Account account, java.util.Date currentDate) {
258         boolean hasResponsibility = false;
259         Criteria criteria = new Criteria();
260         criteria.addEqualTo("accountDelegateSystemId", person.getPrincipalId());
261         criteria.addEqualTo("chartOfAccountsCode", account.getChartOfAccountsCode());
262         criteria.addEqualTo("accountNumber", account.getAccountNumber());
263         Collection accountDelegates = getPersistenceBrokerTemplate().getCollectionByQuery(QueryFactory.newQuery(AccountDelegate.class, criteria));
264         for (Iterator iter = accountDelegates.iterator(); iter.hasNext() && !hasResponsibility;) {
265             AccountDelegate accountDelegate = (AccountDelegate) iter.next();
266             if (accountDelegate.isActive()) {
267                 // the start_date should never be null in the real world, but
268                 // there is some test data that
269                 // contains null startDates, therefore this check.
270                 if (ObjectUtils.isNotNull(accountDelegate.getAccountDelegateStartDate())) {
271                     if (!accountDelegate.getAccountDelegateStartDate().after(currentDate)) {
272                         hasResponsibility = true;
273                     }
274                 }
275             }
276         }
277         return hasResponsibility;
278     }
279 
280     /**
281      * @see org.kuali.ole.coa.dataaccess.AccountDao#getAllAccounts()
282      * @return an iterator for all accounts
283      */
284     public Iterator getAllAccounts() {
285         LOG.debug("getAllAccounts() started");
286 
287         Criteria criteria = new Criteria();
288         return getPersistenceBrokerTemplate().getIteratorByQuery(QueryFactory.newQuery(Account.class, criteria));
289     }
290 
291     /**
292      * @see org.kuali.ole.coa.dataaccess.AccountDao#getActiveAccountsForAccountSupervisor(java.lang.String, java.sql.Date)
293      */
294     public Iterator<Account> getActiveAccountsForAccountSupervisor(String principalId, Date currentSqlDate) {
295         Criteria criteria = new Criteria();
296         criteria.addEqualTo("accountsSupervisorySystemsIdentifier", principalId);
297         criteria.addEqualTo("active", true);
298         criteria.addAndCriteria(getAccountNotExpiredCriteria(currentSqlDate));
299         return (Iterator<Account>) getPersistenceBrokerTemplate().getIteratorByQuery(QueryFactory.newQuery(Account.class, criteria));
300     }
301 
302     /**
303      * @see org.kuali.ole.coa.dataaccess.AccountDao#getActiveAccountsForFiscalOfficer(java.lang.String)
304      */
305     public Iterator<Account> getActiveAccountsForFiscalOfficer(String principalId, Date currentSqlDate) {
306         Criteria criteria = new Criteria();
307         criteria.addEqualTo("accountFiscalOfficerSystemIdentifier", principalId);
308         criteria.addEqualTo("active", true);
309         criteria.addAndCriteria(getAccountNotExpiredCriteria(currentSqlDate));
310         return (Iterator<Account>) getPersistenceBrokerTemplate().getIteratorByQuery(QueryFactory.newQuery(Account.class, criteria));
311     }
312 
313     /**
314      * @see org.kuali.ole.coa.dataaccess.AccountDao#getExpiredAccountsForAccountSupervisor(java.lang.String)
315      */
316     public Iterator<Account> getExpiredAccountsForAccountSupervisor(String principalId, Date currentSqlDate) {
317         Criteria criteria = new Criteria();
318         criteria.addEqualTo("accountsSupervisorySystemsIdentifier", principalId);
319         criteria.addEqualTo("active", true);
320         criteria.addAndCriteria(getAccountExpiredCriteria(currentSqlDate));
321         return (Iterator<Account>) getPersistenceBrokerTemplate().getIteratorByQuery(QueryFactory.newQuery(Account.class, criteria));
322     }
323 
324     /**
325      * @see org.kuali.ole.coa.dataaccess.AccountDao#getExpiredAccountsForFiscalOfficer(java.lang.String)
326      */
327     public Iterator<Account> getExpiredAccountsForFiscalOfficer(String principalId, Date currentSqlDate) {
328         Criteria criteria = new Criteria();
329         criteria.addEqualTo("accountFiscalOfficerSystemIdentifier", principalId);
330         criteria.addEqualTo("active", true);
331         criteria.addAndCriteria(getAccountExpiredCriteria(currentSqlDate));
332         return (Iterator<Account>) getPersistenceBrokerTemplate().getIteratorByQuery(QueryFactory.newQuery(Account.class, criteria));
333     }
334 
335     /**
336      * Builds a criteria to find expired accounts
337      * 
338      * @return a Criteria for expired accounts
339      */
340     protected Criteria getAccountExpiredCriteria(Date currentSqlDate) {
341         Criteria criteria = new Criteria();
342         criteria.addNotNull("accountExpirationDate");
343         criteria.addLessOrEqualThan("accountExpirationDate", currentSqlDate);
344         return criteria;
345     }
346 
347     /**
348      * Builds a criteria to find non-expired accounts
349      * 
350      * @return a Criteria for non-expired accounts
351      */
352     protected Criteria getAccountNotExpiredCriteria(Date currentSqlDate) {
353         Criteria criteria = new Criteria();
354         criteria.addIsNull("accountExpirationDate");
355 
356         Criteria notYetExpiredCriteria = new Criteria();
357         notYetExpiredCriteria.addGreaterThan("accountExpirationDate", currentSqlDate);
358 
359         criteria.addOrCriteria(notYetExpiredCriteria);
360         return criteria;
361     }
362 
363     /**
364      * @see org.kuali.ole.coa.dataaccess.AccountDao#isPrincipalInAnyWayShapeOrFormAccountManager(java.lang.String)
365      */
366     public boolean isPrincipalInAnyWayShapeOrFormAccountManager(String principalId) {
367         return queryPrincipalHasAccountRole(principalId, "accountManagerSystemIdentifier");
368     }
369 
370     /**
371      * Determines if any non-closed accounts exist where the principal id is in the role of the role name
372      * 
373      * @param principalId the principal id to check
374      * @param principalRoleName the name of the field on account to check for the principal id in
375      * @return true if the principal has that account role, false otherwise
376      */
377     protected boolean queryPrincipalHasAccountRole(String principalId, String principalRoleName) {
378         Criteria criteria = new Criteria();
379         criteria.addEqualTo(principalRoleName, principalId);
380         criteria.addEqualTo("active", "Y");
381 
382         ReportQueryByCriteria reportQuery = QueryFactory.newReportQuery(Account.class, criteria);
383         reportQuery.setAttributes(new String[] { "count(*)" });
384 
385         int resultCount = 0;
386         Iterator iter = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(reportQuery);
387         while (iter.hasNext()) {
388             final Object[] results = (Object[]) iter.next();
389             resultCount = (results[0] instanceof Number) ? ((Number) results[0]).intValue() : new Integer(results[0].toString()).intValue();
390         }
391         return resultCount > 0;
392     }
393 
394 
395     /**
396      * @see org.kuali.ole.coa.dataaccess.AccountDao#isPrincipalInAnyWayShapeOrFormAccountSupervisor(java.lang.String)
397      */
398     public boolean isPrincipalInAnyWayShapeOrFormAccountSupervisor(String principalId) {
399         return queryPrincipalHasAccountRole(principalId, "accountsSupervisorySystemsIdentifier");
400     }
401 
402     /**
403      * @see org.kuali.ole.coa.dataaccess.AccountDao#isPrincipalInAnyWayShapeOrFormFiscalOfficer(java.lang.String)
404      */
405     public boolean isPrincipalInAnyWayShapeOrFormFiscalOfficer(String principalId) {
406         return queryPrincipalHasAccountRole(principalId, "accountFiscalOfficerSystemIdentifier");
407     }
408 
409     /**
410      * @see org.kuali.ole.coa.dataaccess.AccountDao#getAccountsForAccountNumber(java.lang.String)
411      */
412     public Collection<Account> getAccountsForAccountNumber(String accountNumber) {
413         Criteria criteria = new Criteria();
414         criteria.addEqualTo(OLEPropertyConstants.ACCOUNT_NUMBER, accountNumber);
415 
416         return getPersistenceBrokerTemplate().getCollectionByQuery(QueryFactory.newQuery(Account.class, criteria));
417     }
418 }