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 }