/* * 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.module.ec.document.validation.impl; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import org.kuali.kfs.coa.businessobject.Account; import org.kuali.kfs.coa.businessobject.Organization; import org.kuali.kfs.coa.businessobject.SubFundGroup; import org.kuali.kfs.integration.cg.ContractsAndGrantsModuleService; import org.kuali.kfs.integration.ld.LaborLedgerBalance; import org.kuali.kfs.module.ec.EffortConstants; import org.kuali.kfs.module.ec.EffortKeyConstants; import org.kuali.kfs.module.ec.util.LedgerBalanceConsolidationHelper; import org.kuali.kfs.sys.Message; import org.kuali.kfs.sys.MessageBuilder; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.rice.core.api.util.type.KualiDecimal; import org.kuali.rice.krad.util.ObjectUtils; /** * The validator provides a set of facilities to determine whether the given ledger balances meet the specified requirements. As a * pattern, null would be returned if the requirements are met; otherwise, return an error message. */ public class LedgerBalanceFieldValidator { /** * check if the given ledger balance has an account qualified for effort reporting * * @param ledgerBalance the given ledger balance * @return null if the given ledger balance has an account qualified for effort reporting; otherwise, a message */ public static Message hasValidAccount(LaborLedgerBalance ledgerBalance) { if (ObjectUtils.isNull(ledgerBalance.getAccount())) { String account = new StringBuilder(ledgerBalance.getChartOfAccountsCode()).append(EffortConstants.VALUE_SEPARATOR).append(ledgerBalance.getAccountNumber()).toString(); return MessageBuilder.buildMessage(EffortKeyConstants.ERROR_ACCOUNT_NUMBER_NOT_FOUND, account); } return null; } /** * detetermine if the fund group code associated with the given ledger balance is in the given fund group codes * * @param ledgerBalance the given ledger balance * @param fundGroupCodes the given fund group codes * @return null if the fund group code associated with the given ledger balance is in the given fund group codes; otherwise, a * message */ public static Message isInFundGroups(LaborLedgerBalance ledgerBalance, List<String> fundGroupCodes) { SubFundGroup subFundGroup = getSubFundGroup(ledgerBalance); if (ObjectUtils.isNull(subFundGroup) || !fundGroupCodes.contains(subFundGroup.getFundGroupCode())) { return MessageBuilder.buildMessage(EffortKeyConstants.ERROR_FUND_GROUP_NOT_FOUND, subFundGroup.getFundGroupCode()); } return null; } /** * detetermine if the sub fund group code associated with the given ledger balance is in the given sub fund group codes * * @param ledgerBalance the given ledger balance * @param subFundGroupCodes the given sub fund group codes * @return null if the sub fund group code associated with the given ledger balance is in the given sub fund group codes; * otherwise, an error message */ public static Message isInSubFundGroups(LaborLedgerBalance ledgerBalance, List<String> subFundGroupCodes) { SubFundGroup subFundGroup = getSubFundGroup(ledgerBalance); if (ObjectUtils.isNull(subFundGroup) || !subFundGroupCodes.contains(subFundGroup.getSubFundGroupCode())) { return MessageBuilder.buildMessage(EffortKeyConstants.ERROR_FUND_GROUP_NOT_FOUND, subFundGroup.getSubFundGroupCode()); } return null; } /** * determine if the total amount within the specified periods of the given ledger balance is ZERO * * @param ledgerBalance the given ledger balance * @param reportPeriods the specified periods * @return null the total amount within the specified periods of the given ledger balance is NOT ZERO; otherwise, a message * message */ public static Message isNonZeroAmountBalanceWithinReportPeriod(LaborLedgerBalance ledgerBalance, Map<Integer, Set<String>> reportPeriods) { KualiDecimal totalAmount = LedgerBalanceConsolidationHelper.calculateTotalAmountWithinReportPeriod(ledgerBalance, reportPeriods); if (totalAmount.isZero()) { return MessageBuilder.buildMessage(EffortKeyConstants.ERROR_ZERO_PAYROLL_AMOUNT, Message.TYPE_FATAL); } return null; } /** * determine if the total amount within the specified periods of the given ledger balances is positive * * @param ledgerBalance the given ledger balance * @param reportPeriods the specified periods * @return null the total amount within the specified periods of the given ledger balance is positive; otherwise, a message * message */ public static Message isTotalAmountPositive(Collection<LaborLedgerBalance> ledgerBalances, Map<Integer, Set<String>> reportPeriods) { KualiDecimal totalAmount = LedgerBalanceConsolidationHelper.calculateTotalAmountWithinReportPeriod(ledgerBalances, reportPeriods); if (!totalAmount.isPositive()) { return MessageBuilder.buildMessage(EffortKeyConstants.ERROR_NONPOSITIVE_PAYROLL_AMOUNT, totalAmount.toString()); } return null; } /** * check if there is at least one account of the given ledger balances that has a fund group code or subfund group code that is * in the specifed group codes. If fundGroupDenotesCGIndictor is ture, only examine the fund group code associated with the * ledger balances; otherwise, the sub fund group code. * * @param ledgerBalances the given ledger balances * @return null if one of the group codes associated with the ledger balances is in the specified codes; otherwise, a message * message */ public static Message hasGrantAccount(Collection<LaborLedgerBalance> ledgerBalances) { for (LaborLedgerBalance balance : ledgerBalances) { if (balance.getAccount().isForContractsAndGrants()) { return null; } } return MessageBuilder.buildMessage(EffortKeyConstants.ERROR_NOT_PAID_BY_GRANT_ACCOUNT, Message.TYPE_FATAL); } /** * determine whether there is at least one account of the given ledger balances that is funded by a federal grant. The award * associated with the account must be one of the given federal agency types or have an enabled federal pass through flag. * * @param the given labor ledger balances * @param federalAgencyTypeCodes the given federal agency type codes * @return null if there is at least one account with federal funding; otherwise, a message */ public static Message hasFederalFunds(Collection<LaborLedgerBalance> ledgerBalances, Collection<String> federalAgencyTypeCodes) { for (LaborLedgerBalance balance : ledgerBalances) { Account account = balance.getAccount(); if (SpringContext.getBean(ContractsAndGrantsModuleService.class).isAwardedByFederalAgency(account.getChartOfAccountsCode(), account.getAccountNumber(), federalAgencyTypeCodes)) { return null; } } return MessageBuilder.buildMessage(EffortKeyConstants.ERROR_NOT_PAID_BY_FEDERAL_FUNDS, Message.TYPE_FATAL); } /** * determine if the given ledger balances have the accounts that belong to multiple organizations * * @param ledgerBalance the given ledger balance * @return null if the given ledger balances have the accounts that belong to a single organization; otherwise, a message */ public static Message isFromSingleOrganization(Collection<LaborLedgerBalance> ledgerBalances) { Organization tempOrganization = null; boolean isFirstTime = true; for (LaborLedgerBalance balance : ledgerBalances) { Organization organization = balance.getAccount().getOrganization(); if (isFirstTime) { tempOrganization = organization; isFirstTime = false; } if (!organization.equals(tempOrganization)) { return MessageBuilder.buildMessage(EffortKeyConstants.ERROR_MULTIPLE_ORGANIZATIONS_FOUND, Message.TYPE_FATAL); } } return null; } /** * get the sub fund group associated with the given ledger balance * * @param ledgerBalance the given ledger balance * @return the sub fund group associated with the given ledger balance */ public static SubFundGroup getSubFundGroup(LaborLedgerBalance ledgerBalance) { SubFundGroup subFundGroup = null; try { subFundGroup = ledgerBalance.getAccount().getSubFundGroup(); } catch (NullPointerException npe) { return null; } return subFundGroup; } }