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.module.bc.batch.service.impl; 017 018 import org.apache.log4j.Logger; 019 import org.kuali.kfs.module.bc.batch.dataaccess.GenesisDao; 020 import org.kuali.kfs.module.bc.batch.service.BudgetConstructionHumanResourcesPayrollInterfaceService; 021 import org.kuali.kfs.module.bc.batch.service.GenesisService; 022 import org.kuali.kfs.sys.KFSConstants; 023 import org.kuali.kfs.sys.KFSConstants.BudgetConstructionConstants; 024 import org.springframework.transaction.annotation.Transactional; 025 026 import java.util.HashMap; 027 import java.util.Map; 028 029 @Transactional 030 public class GenesisServiceImpl implements GenesisService { 031 032 /* settings for common fields for all document headers for budget construction */ 033 034 private GenesisDao genesisDao; 035 private BudgetConstructionHumanResourcesPayrollInterfaceService budgetConstructionHumanResourcesPayrollInterfaceService; 036 037 private static Logger LOG = org.apache.log4j.Logger.getLogger(GenesisServiceImpl.class); 038 039 /* 040 * here are some flag value routines 041 */ 042 043 public boolean BatchPositionSynchAllowed(Integer BaseYear) { 044 Integer RequestYear = BaseYear + 1; 045 boolean ReturnValue = (genesisDao.getBudgetConstructionControlFlag(RequestYear, BudgetConstructionConstants.BUDGET_CONSTRUCTION_GENESIS_RUNNING)) || ((genesisDao.getBudgetConstructionControlFlag(RequestYear, BudgetConstructionConstants.BUDGET_CONSTRUCTION_ACTIVE)) && (genesisDao.getBudgetConstructionControlFlag(RequestYear, BudgetConstructionConstants.BUDGET_BATCH_SYNCHRONIZATION_OK))); 046 return ReturnValue; 047 } 048 049 public boolean CSFUpdatesAllowed(Integer BaseYear) { 050 Integer RequestYear = BaseYear + 1; 051 boolean ReturnValue = (genesisDao.getBudgetConstructionControlFlag(RequestYear, BudgetConstructionConstants.BUDGET_CONSTRUCTION_GENESIS_RUNNING)) || ((genesisDao.getBudgetConstructionControlFlag(RequestYear, BudgetConstructionConstants.BUDGET_CONSTRUCTION_ACTIVE)) && (genesisDao.getBudgetConstructionControlFlag(RequestYear, BudgetConstructionConstants.CSF_UPDATES_OK))); 052 return ReturnValue; 053 } 054 055 public boolean GLUpdatesAllowed(Integer BaseYear) { 056 Integer RequestYear = BaseYear + 1; 057 boolean ReturnValue = (genesisDao.getBudgetConstructionControlFlag(RequestYear, BudgetConstructionConstants.BUDGET_CONSTRUCTION_GENESIS_RUNNING)) || ((genesisDao.getBudgetConstructionControlFlag(RequestYear, BudgetConstructionConstants.BUDGET_CONSTRUCTION_ACTIVE)) && (genesisDao.getBudgetConstructionControlFlag(BaseYear, BudgetConstructionConstants.BASE_BUDGET_UPDATES_OK))); 058 return ReturnValue; 059 } 060 061 public boolean IsBudgetConstructionInUpdateMode(Integer baseYear) 062 { 063 Integer requestYear = baseYear + 1; 064 return genesisDao.getBudgetConstructionControlFlag(requestYear, BudgetConstructionConstants.BUDGET_CONSTRUCTION_GENESIS_RUNNING) || ((genesisDao.getBudgetConstructionControlFlag(requestYear, BudgetConstructionConstants.BUDGET_CONSTRUCTION_ACTIVE)) && (genesisDao.getBudgetConstructionControlFlag(requestYear, BudgetConstructionConstants.BUDGET_CONSTRUCTION_UPDATES_OK))); 065 } 066 067 public void clearDBForGenesis(Integer BaseYear) { 068 genesisDao.clearDBForGenesis(BaseYear); 069 } 070 071 // use today's date to return the base fiscal year 072 public Integer genesisFiscalYearFromToday() { 073 return genesisDao.fiscalYearFromToday(); 074 } 075 076 // this step updates the budget from the payroll (CSF) and the GL once 077 // genesis has run. 078 public void bCUpdateStep(Integer BaseYear) { 079 /** 080 * the calling order is important 081 * for example, GL cannot be created without a document number, appointment funding needs the normal work months 082 * from the budget construction position table 083 * the calling order is constrained further if an institution implements referential integrity 084 */ 085 LOG.warn(String.format("\n\nStarting BC Update:\n clear hanging locks\n")); 086 genesisDao.clearHangingBCLocks(BaseYear); 087 LOG.warn(String.format("\n validate object classes\n")); 088 genesisDao.ensureObjectClassRIForBudget(BaseYear); 089 LOG.warn(String.format("\n create new documents\n")); 090 genesisDao.createNewBCDocumentsFromGLCSF(BaseYear, GLUpdatesAllowed(BaseYear), CSFUpdatesAllowed(BaseYear)); 091 if (GLUpdatesAllowed(BaseYear)) { 092 LOG.warn(String.format("\n add rows to pending general ledger\n")); 093 genesisDao.updateToPBGL(BaseYear); 094 } 095 boolean CSFOK = CSFUpdatesAllowed(BaseYear); 096 boolean PSSynchOK = BatchPositionSynchAllowed(BaseYear); 097 boolean BCUpdatesAllowed = IsBudgetConstructionInUpdateMode(BaseYear); 098 LOG.warn(String.format("\n update Budget Construction Position\n")); 099 budgetConstructionHumanResourcesPayrollInterfaceService.refreshBudgetConstructionPosition(BaseYear,PSSynchOK,CSFOK); 100 LOG.warn(String.format("\n intended incumbent")); 101 budgetConstructionHumanResourcesPayrollInterfaceService.refreshBudgetConstructionIntendedIncumbent(BaseYear,PSSynchOK,CSFOK,BCUpdatesAllowed); 102 if (CSFOK) { 103 LOG.warn(String.format("\n build appointment funding\n")); 104 genesisDao.buildAppointmentFundingAndBCSF(BaseYear); 105 } 106 LOG.warn(String.format("\n rebuild the organization hierarchy\n")); 107 genesisDao.rebuildOrganizationHierarchy(BaseYear); 108 // look for accounts coming from payroll or GL that have not been entered into the Budget Construction Accounting table 109 Integer requestFiscalYear = BaseYear + 1; 110 LOG.warn(String.format("\n look for accounts missing from Budget Construction Accounting\n")); 111 HashMap<String,String[]> missingAccounts = (HashMap<String,String[]>) genesisDao.verifyAccountsAreAccessible(requestFiscalYear); 112 for (Map.Entry<String,String[]> missingAccount : missingAccounts.entrySet()) 113 { 114 String[] missingValues = missingAccount.getValue(); 115 LOG.warn(String.format(" (chart: %s, account: %s) not found in Budget Construction Accounting\n", missingValues[0], missingValues[1])); 116 } 117 } 118 119 public void genesisStep(Integer BaseYear) { 120 /** 121 * the calling order is important 122 * for example, GL cannot be created without a document number, appointment funding needs the normal work months 123 * from the budget construction position table 124 * the calling order is constrained further if an institution implements referential integrity 125 */ 126 LOG.warn(String.format("\nstarting Genesis:\n flags")); 127 genesisDao.setControlFlagsAtTheStartOfGenesis(BaseYear); 128 LOG.warn(String.format("\n clear database")); 129 genesisDao.clearDBForGenesis(BaseYear); 130 LOG.warn(String.format("\n chart for budget")); 131 genesisDao.createChartForNextBudgetCycle(); 132 LOG.warn(String.format("\n referential integrity for object classes")); 133 genesisDao.ensureObjectClassRIForBudget(BaseYear); 134 LOG.warn(String.format("\n new BC documents")); 135 genesisDao.createNewBCDocumentsFromGLCSF(BaseYear, GLUpdatesAllowed(BaseYear), CSFUpdatesAllowed(BaseYear)); 136 LOG.warn(String.format("\n load to PBGL")); 137 genesisDao.initialLoadToPBGL(BaseYear); 138 LOG.warn(String.format("\n new positions")); 139 boolean CSFOK = CSFUpdatesAllowed(BaseYear); 140 boolean PSSynchOK = BatchPositionSynchAllowed(BaseYear); 141 boolean BCUpdatesAllowed = IsBudgetConstructionInUpdateMode(BaseYear); 142 budgetConstructionHumanResourcesPayrollInterfaceService.refreshBudgetConstructionPosition(BaseYear,PSSynchOK,CSFOK); 143 LOG.warn(String.format("\n intended incumbent")); 144 budgetConstructionHumanResourcesPayrollInterfaceService.refreshBudgetConstructionIntendedIncumbent(BaseYear,PSSynchOK,CSFOK,BCUpdatesAllowed); 145 if (CSFOK) { 146 LOG.warn("\n appointment funding/BCSF"); 147 genesisDao.buildAppointmentFundingAndBCSF(BaseYear); 148 } 149 LOG.warn("\n organization hierarchy"); 150 genesisDao.rebuildOrganizationHierarchy(BaseYear); 151 LOG.warn("\n reset control flags"); 152 genesisDao.setControlFlagsAtTheEndOfGenesis(BaseYear); 153 LOG.warn("\n end of genesis"); 154 } 155 156 /* 157 * look of accounts from the payroll (CSF) or GL that came into budget construction but are *not* in the budget construction accounting table. 158 * this can be due to an oversight on the part of the chart manager, or to problems with the current year's budget control. 159 * such accounts will not appear in the pull-up list, since they can't be added to the reporting hierarchy, which is built from budget construction accounting. 160 * this method is provided for use by a report an institution might want to write. such accounts will always appear in the log from bCUpdateStep above, whether this method is used or not. 161 */ 162 public Map verifyAccountsAreAccessible(Integer requestFiscalYear) 163 { 164 return genesisDao.verifyAccountsAreAccessible(requestFiscalYear); 165 } 166 167 public void setGenesisDao(GenesisDao genesisDao) { 168 this.genesisDao = genesisDao; 169 } 170 171 public void setBudgetConstructionHumanResourcesPayrollInterfaceService(BudgetConstructionHumanResourcesPayrollInterfaceService budgetConstructionHumanResourcesPayrollInterfaceService) 172 { 173 this.budgetConstructionHumanResourcesPayrollInterfaceService = budgetConstructionHumanResourcesPayrollInterfaceService; 174 } 175 }