/* * Copyright (c) 2005-2011 Grameen Foundation USA * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * * See also http://www.apache.org/licenses/LICENSE-2.0.html for an * explanation of the license and how it is applied. */ package org.mifos.accounts.financial.util.helpers; import java.io.IOException; import java.util.List; import org.hibernate.Hibernate; import org.hibernate.Query; import org.hibernate.Session; import org.mifos.accounts.financial.business.COABO; import org.mifos.accounts.financial.business.COAHierarchyEntity; import org.mifos.accounts.financial.business.FinancialActionTypeEntity; import org.mifos.accounts.financial.exceptions.FinancialException; import org.mifos.accounts.financial.exceptions.FinancialExceptionConstants; import org.mifos.accounts.persistence.LegacyAccountDao; import org.mifos.application.NamedQueryConstants; import org.mifos.application.servicefacade.ApplicationContextProvider; import org.mifos.config.ChartOfAccountsConfig; import org.mifos.config.GLAccount; import org.mifos.config.exceptions.ConfigurationException; import org.mifos.framework.hibernate.helper.StaticHibernateUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class FinancialInitializer { private static final Logger logger = LoggerFactory.getLogger(FinancialInitializer.class); public static void initialize() throws FinancialException { try { StaticHibernateUtil.startTransaction(); initalizeFinancialAction(); loadCOA(); StaticHibernateUtil.commitTransaction(); // necessary or cacheCOA() doesn't work correctly. Is that because // the commitTransaction() isn't clearing the session? StaticHibernateUtil.clearSession(); cacheCOA(); } catch (Exception e) { StaticHibernateUtil.rollbackTransaction(); throw new FinancialException(FinancialExceptionConstants.ACTIONNOTFOUND, e); } } /** * Reads chart of accounts from a configuration file and inserts into the * database. Deleting accounts is not currently supported, but if the user * tries to do this (by leaving it out of the custom chart of accounts * config file), there is currently no error reported. * <p> * QUESION: what if custom config was missing entries from default config, * but then is moved _out_ of the app server classpath? * <p> * ANSWER: once ChartOfAccountsConfig.isLoaded() returns true, <em>only * the custom CoA config file will be considered</em>. Using the custom * config will be the only way to add new accounts after the initial CoA * data is loaded in the database. */ public static void loadCOA() throws FinancialException { Session session = StaticHibernateUtil.getSessionTL(); final String coaLocation; try { if (!ChartOfAccountsConfig.canLoadCoa(session)) { logger.info("Chart of accounts data will not be modified since " + "the custom chart of accounts configuration file was " + "not found on the classpath."); return; } coaLocation = ChartOfAccountsConfig.getCoaUri(session); logger.info("going to load or modify chart of accounts " + "configuration from " + coaLocation); } catch (IOException e) { throw new FinancialException("Charts of accounts loading failed", e); } ChartOfAccountsConfig coa; try { coa = ChartOfAccountsConfig.load(coaLocation); } catch (ConfigurationException e) { throw new FinancialException(coaLocation + " loading failed", e); } LegacyAccountDao ap = ApplicationContextProvider.getBean(LegacyAccountDao.class); for (GLAccount glAccount : coa.getGLAccounts()) { Short accountId = ap.getAccountIdFromGlCode(glAccount.glCode); if (null == accountId) { logger.info("Adding new general ledger account: " + glAccount); ap.addGeneralLedgerAccount(glAccount.name, glAccount.glCode, glAccount.parentGlCode, glAccount.categoryType); } else { COABO account = (COABO) session.load(COABO.class, accountId); if (account.getCategoryType() != glAccount.categoryType) { throw new FinancialException("category type change not supported"); } if (!accountHierarchyMatch(account, glAccount)) { throw new FinancialException("chart of accounts hierarchy change not supported"); } if (!account.getAccountName().equals(glAccount.name)) { logger.info("updating general ledger account name. code=" + account.getGlCode() + ". old name=" + account.getAccountName() + ", new name=" + glAccount.name); ap.updateAccountName(account, glAccount.name); } } } } /** * Compares hierarchy (parent GL codes) of a general ledger account in the * database to an unpersisted general ledger account. */ private static boolean accountHierarchyMatch(COABO account1, GLAccount account2) { COAHierarchyEntity account1hierarchy = account1.getCoaHierarchy().getParentAccount(); if (null == account1hierarchy) { if (null == account2.parentGlCode) { return true; } logger.error("persisted account has no parent, but new account does"); return false; } COABO account1parent = account1hierarchy.getCoa(); String account1parentGlCode = account1parent.getGlCode(); if (!account1parentGlCode.equals(account2.parentGlCode)) { logger.error("persistent account parent gl code was " + account1parentGlCode + ", but new account parent gl code was " + account2.parentGlCode); return false; } return true; } /** * Reads chart of accounts from the database and caches in memory. */ @SuppressWarnings("unchecked") public static void cacheCOA() { if (ChartOfAccountsCache.isInitialized()) { return; } Session session = StaticHibernateUtil.getSessionTL(); Query query = session.getNamedQuery(NamedQueryConstants.GET_ALL_COA); List<COABO> coaBoList = query.list(); for (COABO coabo : coaBoList) { ChartOfAccountsCache.add(hibernateInitalize(coabo)); } } @SuppressWarnings("unchecked") public static void initalizeFinancialAction() throws FinancialException { Session session = StaticHibernateUtil.getSessionTL(); try { Query queryFinancialAction = session.getNamedQuery(FinancialQueryConstants.GET_ALL_FINANCIAL_ACTION); List<FinancialActionTypeEntity> listFinancialAction = queryFinancialAction.list(); for (FinancialActionTypeEntity fabo : listFinancialAction) { FinancialActionCache.addToCache(fabo); } } catch (Exception e) { throw new FinancialException(FinancialExceptionConstants.FINANCIALACTION_INITFAILED, e); } } private static COABO hibernateInitalize(COABO coa) { Hibernate.initialize(coa); Hibernate.initialize(coa.getCOAHead()); Hibernate.initialize(coa.getAssociatedGlcode()); Hibernate.initialize(coa.getSubCategory()); return coa; } }