/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.coa.dataaccess.impl; import java.sql.Date; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.apache.ojb.broker.query.Criteria; import org.apache.ojb.broker.query.QueryFactory; import org.apache.ojb.broker.query.ReportQueryByCriteria; import org.kuali.kfs.coa.businessobject.Account; import org.kuali.kfs.coa.businessobject.AccountDelegate; import org.kuali.kfs.coa.dataaccess.AccountDao; import org.kuali.kfs.sys.KFSConstants; import org.kuali.kfs.sys.KFSPropertyConstants; import org.kuali.kfs.sys.businessobject.AccountResponsibility; import org.kuali.rice.core.api.util.type.KualiDecimal; import org.kuali.rice.core.framework.persistence.ojb.dao.PlatformAwareDaoBaseOjb; import org.kuali.rice.kim.api.identity.Person; import org.kuali.rice.krad.util.ObjectUtils; /** * This class is the OJB implementation of the AccountDao interface. */ public class AccountDaoOjb extends PlatformAwareDaoBaseOjb implements AccountDao { private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AccountDaoOjb.class); /** * Retrieves account business object by primary key * * @param chartOfAccountsCode - the FIN_COA_CD of the Chart Code that is part of the composite key of Account * @param accountNumber - the ACCOUNT_NBR part of the composite key of Accont * @return Account * @see AccountDao */ public Account getByPrimaryId(String chartOfAccountsCode, String accountNumber) { LOG.debug("getByPrimaryId() started"); Criteria criteria = new Criteria(); criteria.addEqualTo("chartOfAccountsCode", chartOfAccountsCode); criteria.addEqualTo("accountNumber", accountNumber); return (Account) getPersistenceBrokerTemplate().getObjectByQuery(QueryFactory.newQuery(Account.class, criteria)); } /** * fetch the accounts that the user is either the fiscal officer or a delegate of the fiscal officer * * @param kualiUser * @return a list of Accounts that the user has responsibility for */ public List getAccountsThatUserIsResponsibleFor(Person person, java.util.Date currentDate) { LOG.debug("getAccountsThatUserIsResponsibleFor() started"); List accountResponsibilities = new ArrayList(); accountResponsibilities.addAll(getFiscalOfficerResponsibilities(person)); accountResponsibilities.addAll(getDelegatedResponsibilities(person, currentDate)); return accountResponsibilities; } /** * @see org.kuali.kfs.coa.dataaccess.AccountDao#determineUserResponsibilityOnAccount(org.kuali.rice.kim.api.identity.Person, * org.kuali.kfs.coa.businessobject.Account, java.sql.Date) */ public boolean determineUserResponsibilityOnAccount(Person person, Account account, Date currentSqlDate) { boolean result = hasFiscalOfficerResponsibility(person, account); if (!result) { result = hasDelegatedResponsibility(person, account, currentSqlDate); } return result; } /** * Resolves the Primary Delegate for the given delegate example. If the primary delegate exists for a specific Document Type * Code and for a Document Type Code of "KFS", the delegate for the specific document type code is returned; * * @see org.kuali.kfs.coa.dataaccess.AccountDao#getPrimaryDelegationByExample(org.kuali.kfs.coa.businessobject.AccountDelegate, * java.lang.String) */ public List getPrimaryDelegationByExample(AccountDelegate delegateExample, Date currentSqlDate, String totalDollarAmount) { return new ArrayList(getPersistenceBrokerTemplate().getCollectionByQuery(QueryFactory.newQuery(AccountDelegate.class, getDelegateByExampleCriteria(delegateExample, currentSqlDate, totalDollarAmount, "Y")))); } /** * @see org.kuali.kfs.coa.dataaccess.AccountDao#getSecondaryDelegationsByExample(org.kuali.kfs.coa.businessobject.AccountDelegate, * java.lang.String) */ public List getSecondaryDelegationsByExample(AccountDelegate delegateExample, Date currentSqlDate, String totalDollarAmount) { return new ArrayList(getPersistenceBrokerTemplate().getCollectionByQuery(QueryFactory.newQuery(AccountDelegate.class, getDelegateByExampleCriteria(delegateExample, currentSqlDate, totalDollarAmount, "N")))); } /** * This method creates a {@link Criteria} based on {@link Delegate}, dollar amount and whether or not it is the primary delegate * * @param delegateExample * @param totalDollarAmount * @param accountsDelegatePrmrtIndicator * @return example {@link Delegate} {@link Criteria} */ protected Criteria getDelegateByExampleCriteria(AccountDelegate delegateExample, Date currentSqlDate, String totalDollarAmount, String accountsDelegatePrmrtIndicator) { Criteria criteria = new Criteria(); criteria.addEqualTo(KFSConstants.CHART_OF_ACCOUNTS_CODE_PROPERTY_NAME, delegateExample.getChartOfAccountsCode()); criteria.addEqualTo(KFSConstants.ACCOUNT_NUMBER_PROPERTY_NAME, delegateExample.getAccountNumber()); criteria.addEqualTo("active", "Y"); criteria.addLessOrEqualThan("accountDelegateStartDate", currentSqlDate); criteria.addEqualTo("accountsDelegatePrmrtIndicator", accountsDelegatePrmrtIndicator); if (totalDollarAmount != null) { // (toAmt is nullish and (fromAmt is nullish or fromAmt <= total)) or (fromAmt is nullish and (toAmt is nullish or toAmt // >= total)) or (fromAmt <= total and toAmount >= total) /* to not active clause: (toAmt is nullish and (fromAmt is nullish or fromAmt <= total)) */ Criteria toAmountIsNullish = new Criteria(); toAmountIsNullish.addIsNull(KFSPropertyConstants.FIN_DOC_APPROVAL_TO_THIS_AMOUNT); Criteria toAmountIsZero1 = new Criteria(); toAmountIsZero1.addEqualTo(KFSPropertyConstants.FIN_DOC_APPROVAL_TO_THIS_AMOUNT, "0"); toAmountIsNullish.addOrCriteria(toAmountIsZero1); Criteria fromMatchesClause = new Criteria(); fromMatchesClause.addIsNull(KFSPropertyConstants.FIN_DOC_APPROVAL_FROM_THIS_AMT); Criteria fromAmountIsLessThanTotal = new Criteria(); fromAmountIsLessThanTotal.addLessOrEqualThan(KFSPropertyConstants.FIN_DOC_APPROVAL_FROM_THIS_AMT, totalDollarAmount); fromMatchesClause.addOrCriteria(fromAmountIsLessThanTotal); Criteria toNotActiveClause = new Criteria(); toNotActiveClause.addAndCriteria(toAmountIsNullish); toNotActiveClause.addAndCriteria(fromMatchesClause); /* from not active clause: (fromAmt is nullish and (toAmt is nullish or toAmt >= total)) */ Criteria toMatchesClause = new Criteria(); toMatchesClause.addIsNull(KFSPropertyConstants.FIN_DOC_APPROVAL_TO_THIS_AMOUNT); Criteria toAmountIsZero2 = new Criteria(); toAmountIsZero2.addEqualTo(KFSPropertyConstants.FIN_DOC_APPROVAL_TO_THIS_AMOUNT, "0"); toMatchesClause.addOrCriteria(toAmountIsZero2); Criteria toAmountIsGreaterThanTotal = new Criteria(); toAmountIsGreaterThanTotal.addGreaterOrEqualThan(KFSPropertyConstants.FIN_DOC_APPROVAL_TO_THIS_AMOUNT, totalDollarAmount); toMatchesClause.addOrCriteria(toAmountIsGreaterThanTotal); Criteria fromIsNullClause = new Criteria(); fromIsNullClause.addIsNull(KFSPropertyConstants.FIN_DOC_APPROVAL_FROM_THIS_AMT); Criteria fromIsZeroClause = new Criteria(); fromIsZeroClause.addEqualTo(KFSPropertyConstants.FIN_DOC_APPROVAL_FROM_THIS_AMT, "0"); Criteria fromIsNullishClause = new Criteria(); fromIsNullishClause.addOrCriteria(fromIsNullClause); fromIsNullishClause.addOrCriteria(fromIsZeroClause); Criteria fromNotActiveClause = new Criteria(); fromNotActiveClause.addAndCriteria(fromIsNullishClause); fromNotActiveClause.addAndCriteria(toMatchesClause); Criteria bothActive = new Criteria(); bothActive.addLessOrEqualThan(KFSPropertyConstants.FIN_DOC_APPROVAL_FROM_THIS_AMT, totalDollarAmount); bothActive.addGreaterOrEqualThan(KFSPropertyConstants.FIN_DOC_APPROVAL_TO_THIS_AMOUNT, totalDollarAmount); Criteria totalDollarAmountCriteria = new Criteria(); totalDollarAmountCriteria.addOrCriteria(toNotActiveClause); totalDollarAmountCriteria.addOrCriteria(fromNotActiveClause); totalDollarAmountCriteria.addOrCriteria(bothActive); criteria.addAndCriteria(totalDollarAmountCriteria); } return criteria; } /** * method to get the fo responsibilities for the account * * @param person - fiscal officer to check for * @return list of {@link AccountResponsibility} for this fiscal officer */ protected List getFiscalOfficerResponsibilities(Person person) { List fiscalOfficerResponsibilities = new ArrayList(); Criteria criteria = new Criteria(); criteria.addEqualTo("accountFiscalOfficerSystemIdentifier", person.getPrincipalId()); Collection accounts = getPersistenceBrokerTemplate().getCollectionByQuery(QueryFactory.newQuery(Account.class, criteria)); for (Iterator iter = accounts.iterator(); iter.hasNext();) { Account account = (Account) iter.next(); AccountResponsibility accountResponsibility = new AccountResponsibility(AccountResponsibility.FISCAL_OFFICER_RESPONSIBILITY, KualiDecimal.ZERO, KualiDecimal.ZERO, "", account); fiscalOfficerResponsibilities.add(accountResponsibility); } return fiscalOfficerResponsibilities; } /** * This method determines if a given user has fiscal officer responsiblity on a given account. * * @param person the user to check responsibilities for * @param account the account to check responsibilities on * @return true if user does have fiscal officer responsibility on account, false if otherwise */ protected boolean hasFiscalOfficerResponsibility(Person person, Account account) { boolean hasFiscalOfficerResponsibility = false; Criteria criteria = new Criteria(); criteria.addEqualTo("accountFiscalOfficerSystemIdentifier", person.getPrincipalId()); criteria.addEqualTo("chartOfAccountsCode", account.getChartOfAccountsCode()); criteria.addEqualTo("accountNumber", account.getAccountNumber()); Collection accounts = getPersistenceBrokerTemplate().getCollectionByQuery(QueryFactory.newQuery(Account.class, criteria)); if (accounts != null && accounts.size() > 0) { Account retrievedAccount = (Account) accounts.iterator().next(); if (ObjectUtils.isNotNull(retrievedAccount)) { hasFiscalOfficerResponsibility = true; } } return hasFiscalOfficerResponsibility; } /** * method to get the fo delegated responsibilities for the account * * @param person - user to check against * @return a list of {@link AccountResponsibility} objects for a delegate */ protected List getDelegatedResponsibilities(Person person, java.util.Date currentDate) { List delegatedResponsibilities = new ArrayList(); Criteria criteria = new Criteria(); criteria.addEqualTo("accountDelegateSystemId", person.getPrincipalId()); Collection accountDelegates = getPersistenceBrokerTemplate().getCollectionByQuery(QueryFactory.newQuery(AccountDelegate.class, criteria)); for (Iterator iter = accountDelegates.iterator(); iter.hasNext();) { AccountDelegate accountDelegate = (AccountDelegate) iter.next(); if (accountDelegate.isActive()) { // the start_date should never be null in the real world, but // there is some test data that // contains null startDates, therefore this check. if (ObjectUtils.isNotNull(accountDelegate.getAccountDelegateStartDate())) { if (!accountDelegate.getAccountDelegateStartDate().after(currentDate)) { Account account = getByPrimaryId(accountDelegate.getChartOfAccountsCode(), accountDelegate.getAccount().getAccountNumber()); AccountResponsibility accountResponsibility = new AccountResponsibility(AccountResponsibility.DELEGATED_RESPONSIBILITY, accountDelegate.getFinDocApprovalFromThisAmt(), accountDelegate.getFinDocApprovalToThisAmount(), accountDelegate.getFinancialDocumentTypeCode(), account); delegatedResponsibilities.add(accountResponsibility); } } } } return delegatedResponsibilities; } /** * This method determines if a user has delegated responsibilities on a given account. * * @param person the user to check responsibilities for * @param account the account to check responsibilities on * @return true if user has delegated responsibilities */ protected boolean hasDelegatedResponsibility(Person person, Account account, java.util.Date currentDate) { boolean hasResponsibility = false; Criteria criteria = new Criteria(); criteria.addEqualTo("accountDelegateSystemId", person.getPrincipalId()); criteria.addEqualTo("chartOfAccountsCode", account.getChartOfAccountsCode()); criteria.addEqualTo("accountNumber", account.getAccountNumber()); Collection accountDelegates = getPersistenceBrokerTemplate().getCollectionByQuery(QueryFactory.newQuery(AccountDelegate.class, criteria)); for (Iterator iter = accountDelegates.iterator(); iter.hasNext() && !hasResponsibility;) { AccountDelegate accountDelegate = (AccountDelegate) iter.next(); if (accountDelegate.isActive()) { // the start_date should never be null in the real world, but // there is some test data that // contains null startDates, therefore this check. if (ObjectUtils.isNotNull(accountDelegate.getAccountDelegateStartDate())) { if (!accountDelegate.getAccountDelegateStartDate().after(currentDate)) { hasResponsibility = true; } } } } return hasResponsibility; } /** * @see org.kuali.kfs.coa.dataaccess.AccountDao#getAllAccounts() * @return an iterator for all accounts */ public Iterator getAllAccounts() { LOG.debug("getAllAccounts() started"); Criteria criteria = new Criteria(); return getPersistenceBrokerTemplate().getIteratorByQuery(QueryFactory.newQuery(Account.class, criteria)); } /** * @see org.kuali.kfs.coa.dataaccess.AccountDao#getActiveAccountsForAccountSupervisor(java.lang.String, java.sql.Date) */ public Iterator<Account> getActiveAccountsForAccountSupervisor(String principalId, Date currentSqlDate) { Criteria criteria = new Criteria(); criteria.addEqualTo("accountsSupervisorySystemsIdentifier", principalId); criteria.addEqualTo("active", true); criteria.addAndCriteria(getAccountNotExpiredCriteria(currentSqlDate)); return (Iterator<Account>) getPersistenceBrokerTemplate().getIteratorByQuery(QueryFactory.newQuery(Account.class, criteria)); } /** * @see org.kuali.kfs.coa.dataaccess.AccountDao#getActiveAccountsForFiscalOfficer(java.lang.String) */ public Iterator<Account> getActiveAccountsForFiscalOfficer(String principalId, Date currentSqlDate) { Criteria criteria = new Criteria(); criteria.addEqualTo("accountFiscalOfficerSystemIdentifier", principalId); criteria.addEqualTo("active", true); criteria.addAndCriteria(getAccountNotExpiredCriteria(currentSqlDate)); return (Iterator<Account>) getPersistenceBrokerTemplate().getIteratorByQuery(QueryFactory.newQuery(Account.class, criteria)); } /** * @see org.kuali.kfs.coa.dataaccess.AccountDao#getExpiredAccountsForAccountSupervisor(java.lang.String) */ public Iterator<Account> getExpiredAccountsForAccountSupervisor(String principalId, Date currentSqlDate) { Criteria criteria = new Criteria(); criteria.addEqualTo("accountsSupervisorySystemsIdentifier", principalId); criteria.addEqualTo("active", true); criteria.addAndCriteria(getAccountExpiredCriteria(currentSqlDate)); return (Iterator<Account>) getPersistenceBrokerTemplate().getIteratorByQuery(QueryFactory.newQuery(Account.class, criteria)); } /** * @see org.kuali.kfs.coa.dataaccess.AccountDao#getExpiredAccountsForFiscalOfficer(java.lang.String) */ public Iterator<Account> getExpiredAccountsForFiscalOfficer(String principalId, Date currentSqlDate) { Criteria criteria = new Criteria(); criteria.addEqualTo("accountFiscalOfficerSystemIdentifier", principalId); criteria.addEqualTo("active", true); criteria.addAndCriteria(getAccountExpiredCriteria(currentSqlDate)); return (Iterator<Account>) getPersistenceBrokerTemplate().getIteratorByQuery(QueryFactory.newQuery(Account.class, criteria)); } /** * Builds a criteria to find expired accounts * * @return a Criteria for expired accounts */ protected Criteria getAccountExpiredCriteria(Date currentSqlDate) { Criteria criteria = new Criteria(); criteria.addNotNull("accountExpirationDate"); criteria.addLessOrEqualThan("accountExpirationDate", currentSqlDate); return criteria; } /** * Builds a criteria to find non-expired accounts * * @return a Criteria for non-expired accounts */ protected Criteria getAccountNotExpiredCriteria(Date currentSqlDate) { Criteria criteria = new Criteria(); criteria.addIsNull("accountExpirationDate"); Criteria notYetExpiredCriteria = new Criteria(); notYetExpiredCriteria.addGreaterThan("accountExpirationDate", currentSqlDate); criteria.addOrCriteria(notYetExpiredCriteria); return criteria; } /** * @see org.kuali.kfs.coa.dataaccess.AccountDao#isPrincipalInAnyWayShapeOrFormAccountManager(java.lang.String) */ public boolean isPrincipalInAnyWayShapeOrFormAccountManager(String principalId) { return queryPrincipalHasAccountRole(principalId, "accountManagerSystemIdentifier"); } /** * Determines if any non-closed accounts exist where the principal id is in the role of the role name * * @param principalId the principal id to check * @param principalRoleName the name of the field on account to check for the principal id in * @return true if the principal has that account role, false otherwise */ protected boolean queryPrincipalHasAccountRole(String principalId, String principalRoleName) { Criteria criteria = new Criteria(); criteria.addEqualTo(principalRoleName, principalId); criteria.addEqualTo("active", "Y"); ReportQueryByCriteria reportQuery = QueryFactory.newReportQuery(Account.class, criteria); reportQuery.setAttributes(new String[] { "count(*)" }); int resultCount = 0; Iterator iter = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(reportQuery); while (iter.hasNext()) { final Object[] results = (Object[]) iter.next(); resultCount = (results[0] instanceof Number) ? ((Number) results[0]).intValue() : new Integer(results[0].toString()).intValue(); } return resultCount > 0; } /** * @see org.kuali.kfs.coa.dataaccess.AccountDao#isPrincipalInAnyWayShapeOrFormAccountSupervisor(java.lang.String) */ public boolean isPrincipalInAnyWayShapeOrFormAccountSupervisor(String principalId) { return queryPrincipalHasAccountRole(principalId, "accountsSupervisorySystemsIdentifier"); } /** * @see org.kuali.kfs.coa.dataaccess.AccountDao#isPrincipalInAnyWayShapeOrFormFiscalOfficer(java.lang.String) */ public boolean isPrincipalInAnyWayShapeOrFormFiscalOfficer(String principalId) { return queryPrincipalHasAccountRole(principalId, "accountFiscalOfficerSystemIdentifier"); } /** * @see org.kuali.kfs.coa.dataaccess.AccountDao#getAccountsForAccountNumber(java.lang.String) */ public Collection<Account> getAccountsForAccountNumber(String accountNumber) { Criteria criteria = new Criteria(); criteria.addEqualTo(KFSPropertyConstants.ACCOUNT_NUMBER, accountNumber); return getPersistenceBrokerTemplate().getCollectionByQuery(QueryFactory.newQuery(Account.class, criteria)); } }