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.coa.document;
017
018 import java.util.ArrayList;
019 import java.util.Collection;
020 import java.util.Collections;
021 import java.util.Comparator;
022 import java.util.List;
023 import java.util.Map;
024
025 import org.kuali.kfs.coa.businessobject.OrganizationReversion;
026 import org.kuali.kfs.coa.businessobject.OrganizationReversionCategory;
027 import org.kuali.kfs.coa.businessobject.OrganizationReversionDetail;
028 import org.kuali.kfs.coa.service.OrganizationReversionDetailTrickleDownInactivationService;
029 import org.kuali.kfs.coa.service.OrganizationReversionService;
030 import org.kuali.kfs.sys.context.SpringContext;
031 import org.kuali.kfs.sys.document.FinancialSystemMaintainable;
032 import org.kuali.rice.kns.bo.PersistableBusinessObject;
033 import org.kuali.rice.kns.document.MaintenanceDocument;
034 import org.kuali.rice.kns.maintenance.Maintainable;
035 import org.kuali.rice.kns.util.KNSConstants;
036 import org.kuali.rice.kns.util.ObjectUtils;
037 import org.kuali.rice.kns.util.TypedArrayList;
038 import org.kuali.rice.kns.web.ui.Field;
039 import org.kuali.rice.kns.web.ui.Row;
040 import org.kuali.rice.kns.web.ui.Section;
041
042 /**
043 * This class provides some specific functionality for the {@link OrganizationReversion} maintenance document inner class for doing
044 * comparisons on {@link OrganizationReversionCategory} populateBusinessObject setBusinessObject - pre-populate the static list of
045 * details with each category isRelationshipRefreshable - makes sure that {@code organizationReversionGlobalDetails} isn't wiped out
046 * accidentally
047 */
048 public class OrganizationReversionMaintainableImpl extends FinancialSystemMaintainable {
049 private transient OrganizationReversionService organizationReversionService;
050
051 /**
052 * This comparator is used internally for sorting the list of categories
053 */
054 private class categoryComparator implements Comparator<OrganizationReversionDetail> {
055
056 public int compare(OrganizationReversionDetail detail0, OrganizationReversionDetail detail1) {
057
058 OrganizationReversionCategory category0 = detail0.getOrganizationReversionCategory();
059 OrganizationReversionCategory category1 = detail1.getOrganizationReversionCategory();
060
061 String code0 = category0.getOrganizationReversionCategoryCode();
062 String code1 = category1.getOrganizationReversionCategoryCode();
063
064 return code0.compareTo(code1);
065 }
066
067 }
068
069 /**
070 * pre-populate the static list of details with each category
071 *
072 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#setBusinessObject(org.kuali.rice.kns.bo.BusinessObject)
073 */
074 public void setBusinessObject(PersistableBusinessObject businessObject) {
075
076 OrganizationReversionService organizationReversionService = SpringContext.getBean(OrganizationReversionService.class);
077 OrganizationReversion organizationReversion = (OrganizationReversion) businessObject;
078 List<OrganizationReversionDetail> details = organizationReversion.getOrganizationReversionDetail();
079
080 if (details == null) {
081 details = new TypedArrayList(OrganizationReversionDetail.class);
082 organizationReversion.setOrganizationReversionDetail(details);
083 }
084
085 if (details.size() == 0) {
086
087 Collection<OrganizationReversionCategory> categories = organizationReversionService.getCategoryList();
088
089 for (OrganizationReversionCategory category : categories) {
090 if (category.isActive()) {
091 OrganizationReversionDetail detail = new OrganizationReversionDetail();
092 detail.setOrganizationReversionCategoryCode(category.getOrganizationReversionCategoryCode());
093 detail.setOrganizationReversionCategory(category);
094 details.add(detail);
095 }
096 }
097
098 Collections.sort(details, new categoryComparator());
099
100 }
101
102 super.setBusinessObject(businessObject);
103 }
104
105 /**
106 * A method that prevents lookups from refreshing the Organization Reversion Detail list (because, if it is refreshed before a
107 * save...it ends up destroying the list).
108 *
109 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#isRelationshipRefreshable(java.lang.Class, java.lang.String)
110 */
111 @Override
112 protected boolean isRelationshipRefreshable(Class boClass, String relationshipName) {
113 if (relationshipName.equals("organizationReversionDetail")) {
114 return false;
115 }
116 else {
117 return super.isRelationshipRefreshable(boClass, relationshipName);
118 }
119 }
120
121 /**
122 * Determines if this maint doc is inactivating an organization reversion
123 * @return true if the document is inactivating an active organization reversion, false otherwise
124 */
125 protected boolean isInactivatingOrganizationReversion() {
126 // the account has to be closed on the new side when editing in order for it to be possible that we are closing the account
127 if (KNSConstants.MAINTENANCE_EDIT_ACTION.equals(getMaintenanceAction()) && !((OrganizationReversion) getBusinessObject()).isActive()) {
128 OrganizationReversion existingOrganizationReversionFromDB = retrieveExistingOrganizationReversion();
129 if (ObjectUtils.isNotNull(existingOrganizationReversionFromDB)) {
130 // now see if the original account was not closed, in which case, we are closing the account
131 if (existingOrganizationReversionFromDB.isActive()) {
132 return true;
133 }
134 }
135 }
136 return false;
137 }
138
139 /**
140 * Determines if this maint doc is activating an organization reversion
141 * @return true if the document is activating an inactive organization reversion, false otherwise
142 */
143 protected boolean isActivatingOrganizationReversion() {
144 // the account has to be closed on the new side when editing in order for it to be possible that we are closing the account
145 if (KNSConstants.MAINTENANCE_EDIT_ACTION.equals(getMaintenanceAction()) && ((OrganizationReversion) getBusinessObject()).isActive()) {
146 OrganizationReversion existingOrganizationReversionFromDB = retrieveExistingOrganizationReversion();
147 if (ObjectUtils.isNotNull(existingOrganizationReversionFromDB)) {
148 // now see if the original account was not closed, in which case, we are closing the account
149 if (!existingOrganizationReversionFromDB.isActive()) {
150 return true;
151 }
152 }
153 }
154 return false;
155 }
156
157 /**
158 * Grabs the old version of this org reversion from the database
159 * @return the old version of this organization reversion
160 */
161 protected OrganizationReversion retrieveExistingOrganizationReversion() {
162 final OrganizationReversion orgRev = (OrganizationReversion)getBusinessObject();
163 final OrganizationReversion oldOrgRev = SpringContext.getBean(OrganizationReversionService.class).getByPrimaryId(orgRev.getUniversityFiscalYear(), orgRev.getChartOfAccountsCode(), orgRev.getOrganizationCode());
164 return oldOrgRev;
165 }
166
167 /**
168 * Overridden to trickle down inactivation or activation to details
169 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#saveBusinessObject()
170 */
171 @Override
172 public void saveBusinessObject() {
173 final boolean isActivatingOrgReversion = isActivatingOrganizationReversion();
174 final boolean isInactivatingOrgReversion = isInactivatingOrganizationReversion();
175
176 super.saveBusinessObject();
177
178 if (isActivatingOrgReversion) {
179 SpringContext.getBean(OrganizationReversionDetailTrickleDownInactivationService.class).trickleDownActiveOrganizationReversionDetails((OrganizationReversion)getBusinessObject(), documentNumber);
180 } else if (isInactivatingOrgReversion) {
181 SpringContext.getBean(OrganizationReversionDetailTrickleDownInactivationService.class).trickleDownInactiveOrganizationReversionDetails((OrganizationReversion)getBusinessObject(), documentNumber);
182 }
183 }
184
185 /**
186 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#getSections(org.kuali.rice.kns.document.MaintenanceDocument, org.kuali.rice.kns.maintenance.Maintainable)
187 */
188 @Override
189 public List getSections(MaintenanceDocument document, Maintainable oldMaintainable) {
190 List<Section> sections = super.getSections(document, oldMaintainable);
191 if (organizationReversionService == null) {
192 organizationReversionService = SpringContext.getBean(OrganizationReversionService.class);
193 }
194 for (Section section : sections) {
195 for (Row row : section.getRows()) {
196 List<Field> updatedFields = new ArrayList<Field>();
197 for (Field field : row.getFields()) {
198 if (shouldIncludeField(field)) {
199 updatedFields.add(field);
200 }
201 }
202 row.setFields(updatedFields);
203 }
204 }
205 return sections;
206 }
207
208 /**
209 * Determines if the given field should be included in the updated row, once we take out inactive categories
210 * @param field the field to check
211 * @return true if the field should be included (ie, it doesn't describe an organization reversion with an inactive category); false otherwise
212 */
213 protected boolean shouldIncludeField(Field field) {
214 boolean includeField = true;
215 if (field.getContainerRows() != null) {
216 for (Row containerRow : field.getContainerRows()) {
217 for (Field containedField : containerRow.getFields()) {
218 if (containedField.getPropertyName().matches("organizationReversionDetail\\[\\d+\\]\\.organizationReversionCategory\\.organizationReversionCategoryName")) {
219 final String categoryValue = containedField.getPropertyValue();
220 includeField = organizationReversionService.isCategoryActiveByName(categoryValue);
221 }
222 }
223 }
224 }
225 return includeField;
226 }
227
228 }