001: /*
002: * Copyright 2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.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/ecl1.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.module.cg.maintenance;
017:
018: import static org.kuali.kfs.KFSPropertyConstants.AWARD_ACCOUNTS;
019: import static org.kuali.kfs.KFSPropertyConstants.AWARD_PROJECT_DIRECTORS;
020: import static org.kuali.kfs.KFSPropertyConstants.AWARD_SUBCONTRACTORS;
021: import static org.kuali.kfs.KFSPropertyConstants.DOCUMENT;
022: import static org.kuali.kfs.KFSPropertyConstants.NEW_MAINTAINABLE_OBJECT;
023:
024: import java.util.Collection;
025: import java.util.List;
026: import java.util.Map;
027:
028: import org.apache.commons.lang.StringUtils;
029: import org.kuali.core.bo.DocumentHeader;
030: import org.kuali.core.bo.PersistableBusinessObject;
031: import org.kuali.core.document.MaintenanceDocument;
032: import org.kuali.core.maintenance.KualiMaintainableImpl;
033: import org.kuali.core.service.BusinessObjectService;
034: import org.kuali.core.util.GlobalVariables;
035: import org.kuali.core.util.ObjectUtils;
036: import org.kuali.core.workflow.service.KualiWorkflowDocument;
037: import org.kuali.kfs.KFSConstants;
038: import org.kuali.kfs.KFSKeyConstants;
039: import org.kuali.kfs.KFSPropertyConstants;
040: import org.kuali.kfs.context.SpringContext;
041: import org.kuali.module.cg.bo.Award;
042: import org.kuali.module.cg.bo.AwardAccount;
043: import org.kuali.module.cg.bo.AwardOrganization;
044: import org.kuali.module.cg.bo.AwardProjectDirector;
045: import org.kuali.module.cg.bo.CGProjectDirector;
046: import org.kuali.module.cg.bo.ProjectDirector;
047: import org.kuali.module.cg.bo.Proposal;
048: import org.kuali.module.cg.rules.AwardRuleUtil;
049: import org.kuali.module.cg.service.ProjectDirectorService;
050:
051: /**
052: * Methods for the Award maintenance document UI.
053: */
054: public class AwardMaintainableImpl extends KualiMaintainableImpl {
055:
056: /**
057: * Constructs an AwardMaintainableImpl.
058: */
059: public AwardMaintainableImpl() {
060: super ();
061: }
062:
063: /**
064: * Constructs a AwardMaintainableImpl.
065: *
066: * @param award
067: */
068: public AwardMaintainableImpl(Award award) {
069: super (award);
070: this .setBoClass(award.getClass());
071: }
072:
073: /**
074: * This method is called for refreshing the Agency before display to show the full name in case the agency number was changed by
075: * hand before any submit that causes a redisplay.
076: */
077: @Override
078: public void processAfterRetrieve() {
079: refreshAward(false);
080: super .processAfterRetrieve();
081: }
082:
083: /**
084: * This method is called for refreshing the Agency before a save to display the full name in case the agency number was changed
085: * by hand just before the save.
086: */
087: @Override
088: public void prepareForSave() {
089: refreshAward(false);
090: List<AwardProjectDirector> directors = getAward()
091: .getAwardProjectDirectors();
092: if (directors.size() == 1) {
093: directors.get(0).setAwardPrimaryProjectDirectorIndicator(
094: true);
095: }
096: List<AwardOrganization> organizations = getAward()
097: .getAwardOrganizations();
098: if (organizations.size() == 1) {
099: organizations.get(0).setAwardPrimaryOrganizationIndicator(
100: true);
101: }
102:
103: super .prepareForSave();
104: }
105:
106: /**
107: * This method is called for refreshing the Agency after a lookup to display its full name without AJAX.
108: *
109: * @see org.kuali.core.maintenance.KualiMaintainableImpl#refresh(java.lang.String, java.util.Map,
110: * org.kuali.core.document.MaintenanceDocument)
111: */
112: @SuppressWarnings("unchecked")
113: @Override
114: public void refresh(String refreshCaller, Map fieldValues,
115: MaintenanceDocument document) {
116:
117: if (StringUtils.equals(KFSPropertyConstants.PROPOSAL,
118: (String) fieldValues
119: .get(KFSConstants.REFERENCES_TO_REFRESH))) {
120: String pathToMaintainable = DOCUMENT + "."
121: + NEW_MAINTAINABLE_OBJECT;
122: GlobalVariables.getErrorMap().addToErrorPath(
123: pathToMaintainable);
124:
125: boolean awarded = AwardRuleUtil
126: .isProposalAwarded(getAward());
127: if (awarded) {
128: GlobalVariables.getErrorMap().putError(
129: KFSPropertyConstants.PROPOSAL_NUMBER,
130: KFSKeyConstants.ERROR_AWARD_PROPOSAL_AWARDED,
131: new String[] { getAward().getProposalNumber()
132: .toString() });
133: }
134: // SEE KULCG-315 for details on why this code is commented out.
135: // if (AwardRuleUtil.isProposalInactive(getAward())) {
136: // GlobalVariables.getErrorMap().putError(KFSPropertyConstants.PROPOSAL_NUMBER,
137: // KFSKeyConstants.ERROR_AWARD_PROPOSAL_INACTIVE, new String[] { getAward().getProposalNumber().toString() });
138: // }
139: GlobalVariables.getErrorMap().removeFromErrorPath(
140: pathToMaintainable);
141:
142: // copy over proposal values after refresh
143: if (!awarded) {
144: refreshAward(KFSConstants.KUALI_LOOKUPABLE_IMPL
145: .equals(fieldValues
146: .get(KFSConstants.REFRESH_CALLER)));
147: super .refresh(refreshCaller, fieldValues, document);
148: Award award = getAward();
149: award.populateFromProposal(award.getProposal());
150: refreshAward(KFSConstants.KUALI_LOOKUPABLE_IMPL
151: .equals(fieldValues
152: .get(KFSConstants.REFRESH_CALLER)));
153: }
154: } else {
155: refreshAward(KFSConstants.KUALI_LOOKUPABLE_IMPL
156: .equals(fieldValues
157: .get(KFSConstants.REFRESH_CALLER)));
158: super .refresh(refreshCaller, fieldValues, document);
159: }
160:
161: }
162:
163: /**
164: * Load related objects from the database as needed.
165: *
166: * @param refreshFromLookup
167: */
168: private void refreshAward(boolean refreshFromLookup) {
169: Award award = getAward();
170: award.refreshNonUpdateableReferences();
171:
172: getNewCollectionLine(AWARD_SUBCONTRACTORS)
173: .refreshNonUpdateableReferences();
174: getNewCollectionLine(AWARD_PROJECT_DIRECTORS)
175: .refreshNonUpdateableReferences();
176: getNewCollectionLine(AWARD_ACCOUNTS)
177: .refreshNonUpdateableReferences();
178:
179: // the org list doesn't need any refresh
180: refreshNonUpdateableReferences(award.getAwardOrganizations());
181: refreshNonUpdateableReferences(award.getAwardAccounts());
182: refreshNonUpdateableReferences(award.getAwardSubcontractors());
183: refreshAwardProjectDirectors(refreshFromLookup);
184: }
185:
186: /**
187: * Refresh the collection of associated AwardProjectDirectors.
188: *
189: * @param refreshFromLookup a lookup returns only the primary key, so ignore the secondary key when true
190: */
191: private void refreshAwardProjectDirectors(boolean refreshFromLookup) {
192: if (refreshFromLookup) {
193: getNewCollectionLine(AWARD_PROJECT_DIRECTORS)
194: .refreshNonUpdateableReferences();
195: refreshNonUpdateableReferences(getAward()
196: .getAwardProjectDirectors());
197:
198: getNewCollectionLine(AWARD_ACCOUNTS)
199: .refreshNonUpdateableReferences();
200: refreshNonUpdateableReferences(getAward()
201: .getAwardAccounts());
202: } else {
203: refreshWithSecondaryKey((AwardProjectDirector) getNewCollectionLine(AWARD_PROJECT_DIRECTORS));
204: for (AwardProjectDirector projectDirector : getAward()
205: .getAwardProjectDirectors()) {
206: refreshWithSecondaryKey(projectDirector);
207: }
208:
209: refreshWithSecondaryKey((AwardAccount) getNewCollectionLine(AWARD_ACCOUNTS));
210: for (AwardAccount account : getAward().getAwardAccounts()) {
211: refreshWithSecondaryKey(account);
212: }
213: }
214: }
215:
216: /**
217: * @param collection
218: */
219: private static void refreshNonUpdateableReferences(
220: Collection<? extends PersistableBusinessObject> collection) {
221: for (PersistableBusinessObject item : collection) {
222: item.refreshNonUpdateableReferences();
223: }
224: }
225:
226: /**
227: * Refreshes the reference to ProjectDirector, giving priority to its secondary key. Any secondary key that it has may be user
228: * input, so that overrides the primary key, setting the primary key. If its primary key is blank or nonexistent, then leave the
229: * current reference as it is, because it may be a nonexistent instance which is holding the secondary key (the username, i.e.,
230: * personUserIdentifier) so we can redisplay it to the user for correction. If it only has a primary key then use that, because
231: * it may be coming from the database, without any user input.
232: *
233: * @param director the ProjectDirector to refresh
234: */
235: private static void refreshWithSecondaryKey(
236: CGProjectDirector director) {
237: if (ObjectUtils.isNotNull(director.getProjectDirector())) {
238: String secondaryKey = director.getProjectDirector()
239: .getPersonUserIdentifier();
240: if (StringUtils.isNotBlank(secondaryKey)) {
241: ProjectDirector dir = SpringContext.getBean(
242: ProjectDirectorService.class)
243: .getByPersonUserIdentifier(secondaryKey);
244: director
245: .setPersonUniversalIdentifier(dir == null ? null
246: : dir.getPersonUniversalIdentifier());
247: }
248: if (StringUtils.isNotBlank(director
249: .getPersonUniversalIdentifier())
250: && SpringContext
251: .getBean(ProjectDirectorService.class)
252: .primaryIdExists(
253: director
254: .getPersonUniversalIdentifier())) {
255: ((PersistableBusinessObject) director)
256: .refreshNonUpdateableReferences();
257: }
258: }
259: }
260:
261: /**
262: * Gets the underlying Award.
263: *
264: * @return
265: */
266: public Award getAward() {
267: return (Award) getBusinessObject();
268: }
269:
270: /**
271: * Called for refreshing the {@link Subcontractor} on {@link ProposalSubcontractor} before adding to the proposalSubcontractors
272: * collection on the proposal. this is to ensure that the summary fields are show correctly. i.e. {@link Subcontractor} name
273: *
274: * @see org.kuali.core.maintenance.KualiMaintainableImpl#addNewLineToCollection(java.lang.String)
275: */
276: @Override
277: public void addNewLineToCollection(String collectionName) {
278: refreshAward(false);
279: super .addNewLineToCollection(collectionName);
280: }
281:
282: /**
283: * This method overrides the parent method to check the status of the award document and change the linked
284: * {@link ProposalStatus} to A (Approved) if the {@link Award} is now in approved status.
285: *
286: * @see org.kuali.core.maintenance.KualiMaintainableImpl#handleRouteStatusChange(org.kuali.core.bo.DocumentHeader)
287: */
288: @Override
289: public void handleRouteStatusChange(DocumentHeader header) {
290: super .handleRouteStatusChange(header);
291:
292: Award award = getAward();
293: KualiWorkflowDocument workflowDoc = header
294: .getWorkflowDocument();
295:
296: // Use the stateIsProcessed() method so this code is only executed when the final approval occurs
297: if (workflowDoc.stateIsProcessed()) {
298: Proposal proposal = award.getProposal();
299: proposal.setProposalStatusCode(Proposal.AWARD_CODE);
300: SpringContext.getBean(BusinessObjectService.class).save(
301: proposal);
302: }
303:
304: }
305: }
|